home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / basic / qb45pgmr.txt < prev    next >
Encoding:
Text File  |  2013-11-08  |  872.7 KB  |  24,289 lines

  1.  Microsoft QuickBASIC:  Programming in BASIC
  2.  
  3.  
  4.  ════════════════════════════════════════════════════════════════════════════
  5.  
  6.  
  7.  Microsoft(R) QuickBASIC:  Programming in BASIC
  8.  
  9.  For IBM(R) Personal Computers and Compatibles
  10.  
  11.  
  12.  ════════════════════════════════════════════════════════════════════════════
  13.  
  14.  
  15.    Information in this document is subject to change without notice and does
  16.    not represent a commitment on the part of Microsoft Corporation. The
  17.    software described in this document is furnished under a license agreement
  18.    or nondisclosure agreement. The software may be used or copied only in
  19.    accordance with the terms of the agreement. It is against the law to copy
  20.    the software on any medium except as specifically allowed in the license
  21.    or nondisclosure agreement. No part of this manual may be reproduced or
  22.    transmitted in any form or by any means, electronic or mechanical,
  23.    including photocopying and recording, for any purpose without the express
  24.    written permission of Microsoft.
  25.  
  26.    (C)Copyright Microsoft Corporation, 1987, 1988. All rights reserved.
  27.  
  28.    Simultaneously published in the U.S. and Canada.
  29.  
  30.    Printed and bound in the United States of America.
  31.  
  32.    Microsoft, MS, MS-DOS, CodeView, GW-BASIC, and XENIX
  33.  
  34.    are registered trademarks of Microsoft Corporation.
  35.  
  36.    Hayes is a registered trademark of Hayes Microcomputer Products, Inc.
  37.  
  38.    IBM and PS/2 are registered trademarks of International Business Machines
  39.    Corporation.
  40.  
  41.    Intel is a registered trademark of Intel Corporation.
  42.  
  43.    ProKey is a trademark of RoseSoft, Inc.
  44.  
  45.    SideKick and SuperKey are registered trademarks of Borland International,
  46.    Inc.
  47.  
  48.    WordStar is a registered trademark of MicroPro International Corporation.
  49.  
  50.  
  51.  
  52.  ────────────────────────────────────────────────────────────────────────────
  53.  Contents
  54.  
  55.  Introduction
  56.             The QuickBASIC Language
  57.             The QuickBASIC Environment
  58.             Using This Manual
  59.               Selected Programming Topics
  60.               The Heart of BASIC
  61.               Appendixes
  62.             Document Conventions
  63.             Programming Style in this Manual
  64.  
  65.  PART 1  SELECTED PROGRAMMING TOPICS
  66.  
  67.  Chapter 1  Control-Flow Structures
  68.             1.1  Changing Statement Execution Order
  69.             1.2  Boolean Expressions
  70.             1.3  Decision Structures
  71.                  1.3.1  Block IF...THEN...ELSE
  72.                  1.3.2  SELECT CASE
  73.                         1.3.2.1  Using the SELECT CASE Statement
  74.                         1.3.2.2  SELECT CASE Versus ON...GOSUB
  75.             1.4  Looping Structures
  76.                  1.4.1  FOR...NEXT Loops
  77.                         1.4.1.1  Exiting a FOR...NEXT Loop with EXIT FOR
  78.                         1.4.1.2  Pausing Program Execution with FOR...NEXT
  79.                  1.4.2  WHILE...WEND Loops
  80.                  1.4.3  DO...LOOP Loops
  81.                         1.4.3.1  Loop Tests: One Way to Exit DO...LOOP
  82.                         1.4.3.2  EXIT DO: An Alternative Way to Exit
  83.                                  DO...LOOP
  84.             1.5  Sample Applications
  85.                  1.5.1  Checkbook-Balancing Program (CHECK.BAS)
  86.                  1.5.2  Carriage-Return and Line-Feed Filter (CRLF.BAS)
  87.  
  88.  Chapter 2  SUB and FUNCTION Procedures
  89.             2.1  Procedures: Building Blocks for Programming
  90.             2.2  Comparing Procedures with Subroutines and Functions
  91.                  2.2.1  Comparing SUB with GOSUB
  92.                         2.2.1.1  Local and Global Variables
  93.                         2.2.1.2  Use in Multiple-Module Programs
  94.                         2.2.1.3  Operating on Different Sets of Variables
  95.                  2.2.2  Comparing FUNCTION with DEF FN
  96.                         2.2.2.1  Local and Global Variables
  97.                         2.2.2.2  Changing Variables Passed to the Procedure
  98.                         2.2.2.3  Calling the Procedure within Its
  99.                                  Definition
  100.                         2.2.2.4  Use in Multiple-Module Programs
  101.             2.3  Defining Procedures
  102.             2.4  Calling Procedures
  103.                  2.4.1  Calling a FUNCTION Procedure
  104.                  2.4.2  Calling a SUB Procedure
  105.             2.5  Passing Arguments to Procedures
  106.                  2.5.1  Parameters and Arguments
  107.                  2.5.2  Passing Constants and Expressions
  108.                  2.5.3  Passing Variables
  109.                         2.5.3.1  Passing Simple Variables
  110.                         2.5.3.2  Passing an Entire Array
  111.                         2.5.3.3  Passing Individual Array Elements
  112.                         2.5.3.4  Using Array-Bound Functions
  113.                         2.5.3.5  Passing an Entire Record
  114.                         2.5.3.6  Passing Individual Elements of a Record
  115.                  2.5.4  Checking Arguments with the DECLARE Statement
  116.                         2.5.4.1  When QuickBASIC Does Not Generate a DECLARE
  117.                                  Statement
  118.                         2.5.4.2  Developing Programs outside the QuickBASIC
  119.                                  Environment
  120.                         2.5.4.3  Using Include Files for Declarations
  121.                         2.5.4.4  Declaring Procedures in Quick Libraries
  122.                  2.5.5  Passing Arguments by Reference
  123.                  2.5.6  Passing Arguments by Value
  124.             2.6  Sharing Variables with SHARED
  125.                  2.6.1  Sharing Variables with Specific Procedures in a
  126.                         Module
  127.                  2.6.2  Sharing Variables with All Procedures in a Module
  128.                  2.6.3  Sharing Variables with Other Modules
  129.                  2.6.4  The Problem of Variable Aliasing
  130.             2.7  Automatic and STATIC Variables
  131.             2.8  Preserving Values of Local Variables with the STATIC
  132.                  Statement
  133.             2.9  Recursive Procedures
  134.                  2.9.1  The Factorial Function
  135.                  2.9.2  Adjusting the Size of the Stack
  136.             2.10  Transferring Control to Another Program with CHAIN
  137.             2.11  Sample Application: Recursive Directory Search
  138.                   (WHEREIS.BAS)
  139.  
  140.  Chapter 3  File and Device I/O
  141.             3.1  Printing Text on the Screen
  142.                  3.1.1  Screen Rows and Columns
  143.                  3.1.2  Displaying Text and Numbers with PRINT
  144.                  3.1.3  Displaying Formatted Output with PRINT USING
  145.                  3.1.4  Skipping Spaces and Advancing to a Specific Column
  146.                  3.1.5  Changing the Number of Columns or Rows
  147.                  3.1.6  Creating a Text Viewport
  148.             3.2  Getting Input from the Keyboard
  149.                  3.2.1  The INPUT Statement
  150.                  3.2.2  The LINE INPUT Statement
  151.                  3.2.3  The INPUT$ Function
  152.                  3.2.4  The INKEY$ Function
  153.             3.3  Controlling the Text Cursor
  154.                  3.3.1  Positioning the Cursor
  155.                  3.3.2  Changing the Cursor's Shape
  156.                  3.3.3  Getting Information about the Cursor's Location
  157.             3.4  Working with Data Files
  158.                  3.4.1  How Data Files Are Organized
  159.                  3.4.2  Sequential and Random-Access Files
  160.                  3.4.3  Opening a Data File
  161.                         3.4.3.1  File Numbers in BASIC
  162.                         3.4.3.2  File Names in BASIC
  163.                  3.4.4  Closing a Data File
  164.                  3.4.5  Using Sequential Files
  165.                         3.4.5.1  Records in Sequential Files
  166.                         3.4.5.2  Putting Data in a New Sequential File
  167.                         3.4.5.3  Reading Data from a Sequential File
  168.                         3.4.5.4  Adding Data to a Sequential File
  169.                         3.4.5.5  Other Ways to Write Data to a Sequential
  170.                                  File
  171.                         3.4.5.6  Other Ways to Read Data from a Sequential
  172.                                  File
  173.                  3.4.6  Using Random-Access Files
  174.                         3.4.6.1  Records in Random-Access Files
  175.                         3.4.6.2  Adding Data to a Random-Access File
  176.                         3.4.6.7  Reading Data Sequentially
  177.                         3.4.6.8  Using Record Numbers to Retrieve Records
  178.                  3.4.7  Binary File I/O
  179.                         3.4.7.1  Comparing Binary Access and Random Access
  180.                         3.4.7.2  Positioning the File Pointer with SEEK
  181.             3.5  Working with Devices
  182.                  3.5.1  Differences between Device I/O and File I/O
  183.                  3.5.2  Communications through the Serial Port
  184.             3.6  Sample Applications
  185.                  3.6.1  Perpetual Calendar (CAL.BAS)
  186.                  3.6.2  Indexing a Random-Access File (INDEX.BAS)
  187.                  3.6.3  Terminal Emulator (TERMINAL.BAS)
  188.  
  189.  Chapter 4  String Processing
  190.             4.1  Strings Defined
  191.             4.2  Variable- and Fixed-Length Strings
  192.                  4.2.1  Variable-Length Strings
  193.                  4.2.2  Fixed-Length Strings
  194.             4.3  Combining Strings
  195.             4.4  Comparing Strings
  196.             4.5  Searching for Strings
  197.             4.6  Retrieving Parts of Strings
  198.                  4.6.1  Retrieving Characters from the Left Side of a
  199.                         String
  200.                  4.6.2  Retrieving Characters from the Right Side of a
  201.                         String
  202.                  4.6.3  Retrieving Characters from Anywhere in a String
  203.             4.7  Generating Strings
  204.             4.8  Changing the Case of Letters
  205.             4.9  Strings and Numbers
  206.             4.10 Changing Strings
  207.             4.11 Sample Application: Converting a String to a Number
  208.                   (STRTONUM.BAS)
  209.  
  210.  Chapter 5  Graphics
  211.             5.1  What You Need for Graphics Programs
  212.             5.2  Pixels and Screen Coordinates
  213.             5.3  Drawing Basic Shapes: Points, Lines, Boxes, and Circles
  214.                  5.3.1  Plotting Points with PSET and PRESET
  215.                  5.3.2  Drawing Lines and Boxes with LINE
  216.                         5.3.2.1  Using the STEP Option
  217.                         5.3.2.2  Drawing Boxes
  218.                         5.3.2.3  Drawing Dotted Lines
  219.             5.4  Drawing Circles and Ellipses with CIRCLE
  220.                  5.4.1  Drawing Circles
  221.                  5.4.2  Drawing Ellipses
  222.                  5.4.3  Drawing Arcs
  223.                  5.4.4  Drawing Pie Shapes
  224.                  5.4.5  Drawing Shapes to Proportion with the Aspect Ratio
  225.             5.5  Defining a Graphics Viewport
  226.             5.6  Redefining Viewport Coordinates with WINDOW
  227.                  5.6.1  The Order of Coordinate Pairs
  228.                  5.6.2  Keeping Track of View and Physical Coordinates
  229.             5.7  Using Colors
  230.                  5.7.1  Selecting a Color for Graphics Output
  231.                  5.7.2  Changing the Foreground or Background Color
  232.                  5.7.3  Changing Colors with PALETTE and PALETTE USING
  233.             5.8  Painting Shapes
  234.                  5.8.1  Painting with Colors
  235.                  5.8.2  Painting with Patterns: Tiling
  236.                         5.8.2.1  Pattern-Tile Size in Different Screen
  237.                                  Modes
  238.                         5.8.2.2  Creating a Single-Color Pattern in Screen
  239.                                  Mode 2
  240.                         5.8.2.3  Creating a Multicolor Pattern in Screen Mode
  241.                                  1
  242.                         5.8.2.4  Creating a Multicolor Pattern in Screen Mode
  243.                                  8
  244.             5.9  DRAW: a Graphics Macro Language
  245.             5.10 Basic Animation Techniques
  246.                  5.10.1  Saving Images with GET
  247.                  5.10.2  Moving Images with PUT
  248.                  5.10.3  Animation with GET and PUT
  249.                  5.10.4  Animating with Screen Pages
  250.             5.11 Sample Applications
  251.                  5.11.1  Bar-Graph Generator (BAR.BAS)
  252.                  5.11.2  Color in a Figure Generated Mathematically
  253.                          (MANDEL.BAS)
  254.                  5.11.3  Pattern Editor (EDPAT.BAS)
  255.  
  256.  Chapter 6  Error and Event Trapping
  257.             6.1  Error Trapping
  258.                  6.1.1  Activating Error Trapping
  259.                  6.1.2  Writing an Error-Handling Routine
  260.                         6.1.2.1  Using ERR to Identify Errors
  261.                         6.1.2.2  Returning from an Error-Handling Routine
  262.             6.2  Event Trapping
  263.                  6.2.1  Detecting Events by Polling
  264.                  6.2.2  Detecting Events by Trapping
  265.                  6.2.3  Specifying the Event to Trap and Activating Event
  266.                         Trapping
  267.                  6.2.4  Events That BASIC Can Trap
  268.                  6.2.5  Suspending or Disabling Event Trapping
  269.                  6.2.6  Trapping Keystrokes
  270.                         6.2.6.1  Trapping User-Defined Keys
  271.                         6.2.6.2  Trapping User-Defined Shifted Keys
  272.                  6.2.7  Trapping Music Events
  273.             6.3  Error and Event Trapping in SUB or FUNCTION Procedures
  274.             6.4  Trapping across Multiple Modules
  275.                  6.4.1  Event Trapping across Modules
  276.                  6.4.2  Error Trapping across Modules
  277.             6.5  Trapping Errors and Events in Programs Compiled with BC
  278.             6.6  Sample Application: Trapping File-Access Errors
  279.                  (FILERR.BAS)
  280.  
  281.  Chapter 7  Programming with Modules
  282.             7.1  Why Use Modules?
  283.             7.2  Main Modules
  284.             7.3  Modules Containing Only Procedures
  285.             7.4  Creating a Procedures-Only Module
  286.             7.5  Loading Modules
  287.             7.6  Using the DECLARE Statement with Multiple Modules
  288.             7.7  Accessing Variables from Two or More Modules
  289.             7.8  Using Modules During Program Development
  290.             7.9  Compiling and Linking Modules
  291.             7.10 Quick Libraries
  292.                  7.10.1  Creating Quick Libraries
  293.             7.11 Tips for Good Programming with Modules
  294.  
  295.  PART 2  HEART OF BASIC
  296.  
  297.  Chapter 8  Statement and Function Summary
  298.             ABS Function
  299.             ASC Function
  300.             ATN Function
  301.             BEEP Statement
  302.             BLOAD Statement
  303.             BSAVE Statement
  304.             CALL Statement (BASIC Procedures)
  305.             CALL, CALLS Statement (Non-BASIC Procedures)
  306.             CALL INT86OLD Statements
  307.             CALL ABSOLUTE Statement
  308.             CALL INTERRUPT Statements
  309.             CDBL Function
  310.             CHAIN Statement
  311.             CHDIR Statement
  312.             CHR$ Function
  313.             CINT Function
  314.             CIRCLE Statement
  315.             CLEAR Statement
  316.             CLNG Function
  317.             CLOSE Statement
  318.             CLS Statement
  319.             COLOR Statement
  320.             COM Statements
  321.             COMMAND$ Function
  322.             COMMON Statement
  323.             CONST Statement
  324.             COS Function
  325.             CSNG Function
  326.             CSRLIN Function
  327.             CVI, CVS, CVL, CVD Functions
  328.             CVSMBF, CVDMBF Functions
  329.             DATA Statement
  330.             DATE$ Function
  331.             DATE$ Statement
  332.             DECLARE Statement (BASIC Procedures)
  333.             DECLARE Statement (Non-BASIC Procedures)
  334.             DEF FN Statement
  335.             DEF SEG Statement
  336.             DEFtype Statements
  337.             DIM Statement
  338.             DO...LOOP Statements
  339.             DRAW Statement
  340.             END Statement
  341.             ENVIRON$ Function
  342.             ENVIRON Statement
  343.             EOF Function
  344.             ERASE Statement
  345.             ERDEV, ERDEV$ Functions
  346.             ERR, ERL Functions
  347.             ERROR Statement
  348.             EXIT Statement
  349.             EXP Function
  350.             FIELD Statement
  351.             FILEATTR Function
  352.             FILES Statement
  353.             FIX Function
  354.             FOR...NEXT Statement
  355.             FRE Function
  356.             FREEFILE Function
  357.             FUNCTION Statement
  358.             GET Statement──File I/O
  359.             GET Statement──Graphics
  360.             GOSUB...RETURN Statements
  361.             GOTO Statement
  362.             HEX$ Function
  363.             IF...THEN...ELSE Statements
  364.             INKEY$ Function
  365.             INP Function
  366.             INPUT$ Function
  367.             INPUT Statement
  368.             INPUT # Statement
  369.             INSTR Function
  370.             INT Function
  371.             IOCTL$ Function
  372.             IOCTL Statement
  373.             KEY Statements
  374.             KEY(n) Statements
  375.             KILL Statement
  376.             LBOUND Function
  377.             LCASE$ Function
  378.             LEFT$ Function
  379.             LEN Function
  380.             LET Statement
  381.             LINE Statement
  382.             LINE INPUT Statement
  383.             LINE INPUT # Statement
  384.             LOC Function
  385.             LOCATE Statement
  386.             LOCK...UNLOCK Statement
  387.             LOF Function
  388.             LOG Function
  389.             LPOS Function
  390.             LPRINT, LPRINT USING Statements
  391.             LSET Statement
  392.             LTRIM$ Function
  393.             MID$ Function
  394.             MID$ Statement
  395.             MKD$, MKI$, MKL$, MKS$ Functions
  396.             MKDIR Statement
  397.             MKSMBF$, MKDMBF$ Functions
  398.             NAME Statement
  399.             OCT$ Function
  400.             ON ERROR Statement
  401.             ON event Statements
  402.             ON UEVENT GOSUB Statement
  403.             ON...GOSUB, ON...GOTO Statements
  404.             OPEN Statement
  405.             OPEN COM Statement
  406.             OPTION BASE Statement
  407.             OUT Statement
  408.             PAINT Statement
  409.             PALETTE, PALETTE USING Statements
  410.             PCOPY Statement
  411.             PEEK Function
  412.             PEN Function
  413.             PEN ON, OFF, and STOP Statements
  414.             PLAY Function
  415.             PLAY Statement
  416.             PLAY ON, OFF, and STOP Statements
  417.             PMAP Function
  418.             POINT Function
  419.             POKE Statement
  420.             POS Function
  421.             PRESET Statement
  422.             PRINT Statement
  423.             PRINT #, PRINT # USING Statements
  424.             PRINT USING Statement
  425.             PSET Statement
  426.             PUT Statement──File I/O
  427.             PUT Statement──Graphics
  428.             RANDOMIZE Statement
  429.             READ Statement
  430.             REDIM Statement
  431.             REM Statement
  432.             RESET Statement
  433.             RESTORE Statement
  434.             RESUME Statement
  435.             RETURN Statement
  436.             RIGHT$ Function
  437.             RMDIR Statement
  438.             RND Function
  439.             RSET Statement
  440.             RTRIM$ Function
  441.             RUN Statement
  442.             SADD Function
  443.             SCREEN Function
  444.             SCREEN Statement
  445.             SEEK Function
  446.             SEEK Statement
  447.             SELECT CASE Statement
  448.             SETMEM Function
  449.             SGN Function
  450.             SHARED Statement
  451.             SHELL Statement
  452.             SIN Function
  453.             SLEEP Statement
  454.             SOUND Statement
  455.             SPACE$ Function
  456.             SPC Function
  457.             SQR Function
  458.             STATIC Statement
  459.             STICK Function
  460.             STOP Statement
  461.             STR$ Function
  462.             STRIG Function and Statement
  463.             STRIG ON, OFF, and STOP Statements
  464.             STRING$ Function
  465.             SUB Statements
  466.             SWAP Statement
  467.             SYSTEM Statement
  468.             TAB Function
  469.             TAN Function
  470.             TIME$ Function
  471.             TIME$ Statement
  472.             TIMER Function
  473.             TIMER ON, OFF, and STOP Statements
  474.             TRON/TROFF Statements
  475.             TYPE Statement
  476.             UBOUND Function
  477.             UCASE$ Function
  478.             UEVENT Statement
  479.             UNLOCK Statement
  480.             VAL Function
  481.             VARPTR, VARSEG Functions
  482.             VARPTR$ Function
  483.             VIEW Statement
  484.             VIEW PRINT Statement
  485.             WAIT Statement
  486.             WHILE...WEND Statement
  487.             WIDTH Statement
  488.             WINDOW Statement
  489.             WRITE Statement
  490.             WRITE # Statement
  491.  
  492.  Chapter 9  Quick-Reference Tables
  493.             9.1  Summary of Control-Flow Statements
  494.             9.2  Summary of Statements Used in BASIC Procedures
  495.             9.3  Summary of Standard I/O Statements
  496.             9.4  Summary of File I/O Statements
  497.             9.5  Summary of String-Processing Statements and Functions
  498.             9.6  Summary of Graphics Statements and Functions
  499.             9.7  Summary of Trapping Statements and Functions
  500.  
  501.  Appendix A  Converting BASICA Programs to QuickBASIC
  502.  
  503.  Appendix B  Differences from Previous Versions of QuickBASIC
  504.  
  505.  Appendix C  Limits in QuickBASIC
  506.  
  507.  Appendix D  Keyboard Scan Codes and ASCII Character Codes
  508.  
  509.  Appendix E  BASIC Reserved Words
  510.  
  511.  Appendix F  Metacommands
  512.  
  513.  Appendix G  Compiling and Linking from DOS
  514.  
  515.  Appendix H  Creating and Using Quick Libraries
  516.  
  517.  Appendix I  Error Messages
  518.  
  519.  Figures
  520.  Figure 1.1  Logic of FOR...NEXT Loop with Positive STEP
  521.  Figure 1.2  Logic of FOR...NEXT Loop with Negative STEP
  522.  Figure 1.3  Logic of WHILE...WEND Loop
  523.  Figure 1.4  Logic of DO WHILE...LOOP
  524.  Figure 1.5  Logic of DO UNTIL...LOOP
  525.  Figure 1.6  Logic of DO...LOOP WHILE
  526.  Figure 1.7  Logic of DO...LOOP UNTIL
  527.  Figure 2.1  Parameters and Arguments
  528.  Figure 3.1  Text Output on Screen
  529.  Figure 3.2  Records in Sequential Files
  530.  Figure 3.3  Records in a Random-Access File
  531.  Figure 5.1  Coordinates of Selected Pixels in Screen Mode 2
  532.  Figure 5.2  How Angles Are Measured for CIRCLE
  533.  Figure 5.3  The Aspect Ratio In Screen Mode 1
  534.  Figure 5.4  WINDOW Contrasted with WINDOW SCREEN
  535.  Figure 5.5  Patterned Circle
  536.  Figure 6.1  Program Flow of Control with RESUME
  537.  Figure 6.2  Program Flow of Control with RESUME NEXT
  538.  Figure 7.1  Main Module Showing Module-Level Code and Procedures
  539.  Figure H.1  Make Library Dialog Box
  540.  
  541.  Tables
  542.  Table 1.1  Relational Operators Used in Basic
  543.  Table 1.2  Block IF...THEN...ELSE Syntax and Example
  544.  Table 1.3  SELECT CASE Syntax and Example
  545.  Table 1.4  FOR...NEXT Syntax and Example
  546.  Table 1.5  WHILE...WEND Syntax and Example
  547.  Table 1.6  DO...LOOP Syntax and Example: Test at the Beginning
  548.  Table 1.7  DO...LOOP Syntax and Example: Test at the End
  549.  Table 3.1  Devices Supported by BASIC for I/O
  550.  Table 5.1  Color Palettes in Screen Mode 1
  551.  Table 5.2  Background Colors in Screen Mode 1
  552.  Table 5.3  Binary to Hexadecimal Conversion
  553.  Table 5.4  The Effect of Different Action Options in Screen Mode 2
  554.  Table 5.5  The Effect of Different Action Options on Color in Screen Mode 1
  555.  (Palette 1)
  556.  Table 6.1  BC Command-Line Options for Error and Event Trapping
  557.  Table 9.1  Statements Used in Looping and Decision-Making
  558.  Table 9.2  Statements Used in Procedures
  559.  Table 9.3  Statements and Functions Used for Standard I/O
  560.  Table 9.4  Statements and Functions Used for Data-File I/O
  561.  Table 9.5  Statements and Functions Used for Processing Strings
  562.  Table 9.6  Statements and Functions Used for Graphics Output
  563.  Table 9.7  Statements andn Functions Used in Error and Event Trapping
  564.  Table A.1  Statements Requiring Modification
  565.  Table B.1  Features of Microsoft QuickBASIC Version 4.5
  566.  Table B.2  Menus with New Commands in QuickBASIC Version 4.5
  567.  Table B.3  Editing-Key Changes
  568.  Table B.4  QB and BC Options Not Used in QuickBASIC Versions 4.0 or 4.5
  569.  Table B.5  Options Introduced in Version 4.0 for the QB and BC Commands
  570.  Table B.6  Debugging-Key Changes
  571.  Table B.7  Changes to the BASIC Language
  572.  Table C.1  QuickBASIC Limits
  573.  Table G.1  Input to the BC Command
  574.  Table G.2  Input to the LINK Command
  575.  Table G.3  Input to the LIB Command
  576.  Table I.1  Run-Time Error Codes
  577.  
  578.  
  579.  
  580.  ────────────────────────────────────────────────────────────────────────────
  581.  Introduction
  582.  
  583.    Microsoft(R) QuickBASIC 4.5 is a major advance in making BASIC both more
  584.    powerful and easier to use. It provides the most advanced BASIC yet
  585.    offered for microcomputers, supported by an operating environment that
  586.    allows you to focus on program creation──not the mechanics of writing or
  587.    debugging.
  588.  
  589.  
  590.  The QuickBASIC Language
  591.  
  592.    If you already know how to program in BASICA (or a similar interpreted
  593.    BASIC), you'll appreciate the enhanced language features QuickBASIC
  594.    provides to make it easier to write and maintain your software. For
  595.    example:
  596.  
  597.    ■ The SELECT CASE statement cleanly transfers control to any block of code
  598.      without the use of nested IF...THEN...ELSE statements. SELECT CASE
  599.      permits an exceptionally wide range of test expressions, so you can
  600.      create exactly the comparison you need.
  601.  
  602.    ■ QuickBASIC's SUB and FUNCTION procedures allow you to place groups of
  603.      program statements into subprograms that your main program can call
  604.      repeatedly. QuickBASIC's modularity makes it easy to save these
  605.      procedures and reuse them in other programs.
  606.  
  607.    ■ QuickBASIC procedures are fully recursive──a procedure can call itself
  608.      repeatedly. This simplifies the programming of many numerical and
  609.      sorting algorithms that are best expressed recursively.
  610.  
  611.    ■ You can define your own data types, made up of any combination of
  612.      integer, real, and string variables. Related variables can be
  613.      conveniently grouped under a single name, which simplifies passing them
  614.      to a procedure or writing them to a file.
  615.  
  616.    ■ QuickBASIC supports binary file access. Your programs can read and
  617.      manipulate files in any format because binary I/O can directly access
  618.      any byte in the file.
  619.  
  620.    QuickBASIC is a powerful development tool for professional use. Yet it is
  621.    also the ideal language for beginning and intermediate programmers──people
  622.    who aren't professional programmers but need a language that helps them
  623.    reach their programming goals efficiently.
  624.  
  625.  
  626.  The QuickBASIC Environment
  627.  
  628.    QuickBASIC isn't just an outstanding language. It is also an integrated
  629.    programming environment that significantly simplifies writing and
  630.    debugging software:
  631.  
  632.    ■ As you type in your program, a smart editor checks each line for syntax
  633.      errors. When you are ready to run, press a single key to execute the
  634.      program instantly. If something is wrong, use the full-screen editor to
  635.      correct the problem, then run the program again.
  636.  
  637.    ■ You can debug your programs without exiting QuickBASIC. The integrated
  638.      debugger lets you examine and alter variables, execute any part of the
  639.      program, or halt execution when a particular condition is met. All these
  640.      things happen within the QuickBASIC environment; you don't have to alter
  641.      the program or add PRINT statements.
  642.  
  643.    ■ QuickBASIC 4.5 has two new commands to make the debugger even more
  644.      powerful: the Instant Watch command and the Break on Errors command.
  645.  
  646.    ■ Also new to QuickBASIC 4.5 is the Microsoft QB Advisor, our on-line
  647.      help. The QB Advisor is always at hand, whether you are writing,
  648.      running, or debugging. Just place the cursor on the keyword or
  649.      user-defined name you want to know more about, then press F1. The QB
  650.      Advisor describes the syntax of BASIC statements and functions, explains
  651.      how to use them, and even provides usable programming examples.
  652.  
  653.  
  654.  Using This Manual
  655.  
  656.    This manual is in three parts. Part 1, "Selected Programming Topics,"
  657.    provides information on specific programming techniques and strategies.
  658.    Part 2, "Heart of BASIC," and the appendixes contain important reference
  659.    material.
  660.  
  661.  Selected Programming Topics
  662.  
  663.    Each chapter in this first section focuses on a single programming area.
  664.    Studying this material will help you to quickly master
  665.  
  666.    ■ Control-flow structures
  667.  
  668.    ■ SUB and FUNCTION procedures
  669.  
  670.    ■ File and device input and output
  671.  
  672.    ■ String processing
  673.  
  674.    ■ Graphics
  675.  
  676.    ■ Error and event trapping
  677.  
  678.    ■ Programming with modules
  679.  
  680.    The presentation of each topic is straightforward and easy to understand,
  681.    with many short programming examples that demonstrate how each part of
  682.    BASIC works. The progression is from simple to more complex topics, so you
  683.    can work through this material at your own pace without worrying about the
  684.    order in which to study it. The focus throughout is on utility, not
  685.    theory──how you can solve common programming problems with QuickBASIC.
  686.  
  687.    In addition to the short examples, the chapters contain complete working
  688.    programs that demonstrate the programming principles presented in that
  689.    chapter. For your convenience, these programs are also included on your
  690.    QuickBASIC release disks.
  691.  
  692.    If you're an experienced BASIC programmer, you'll probably want to browse
  693.    through the table of contents for a topic that catches your interest. If
  694.    you're a novice programmer, though, you should probably work through each
  695.    chapter from beginning to end. If you have never programmed in any
  696.    language, you should start with Chapter 4 of Learning to Use Microsoft
  697.    QuickBASIC, "Interlude: BASIC for Beginners."
  698.  
  699.    Regardless of your interests or background, these seven chapters will help
  700.    you learn almost everything you need to know to write sophisticated BASIC
  701.    applications.
  702.  
  703.  The Heart of BASIC
  704.  
  705.    The second part of this manual, the "Heart of BASIC," is a handy,
  706.    two-part quick reference to BASIC statements and functions.
  707.  
  708.    Chapter 8, "Statement and Function Summary," is an alphabetically
  709.    arranged summary of every BASIC keyword, describing its action or use and
  710.    displaying its syntax. If your memory needs jogging on statement or
  711.    function use, turn to this section.
  712.  
  713.    In Chapter 9, "Quick-Reference Tables," the most commonly used BASIC
  714.    statements and functions are displayed in six sections in table form, with
  715.    each statement given a brief description. The contents of these sections
  716.    match the material presented in Chapters 1 through 6 of "Selected
  717.    Programming Topics." If you are trying to figure out how to accomplish a
  718.    particular programming task, turn to this section.
  719.  
  720.  Appendixes
  721.  
  722.    The third section of this manual is a group of appendixes containing
  723.    reference information on
  724.  
  725.    ■ Converting BASICA programs
  726.  
  727.    ■ Differences from previous versions
  728.  
  729.    ■ Limits in QuickBASIC
  730.  
  731.    ■ Keyboard scan codes and ASCII codes
  732.  
  733.    ■ BASIC reserved words
  734.  
  735.    ■ Metacommands
  736.  
  737.    ■ Compiling and linking from DOS
  738.  
  739.    ■ Creating and using Quick libraries
  740.  
  741.    ■ Error messages
  742.  
  743.  
  744.  Document Conventions
  745.  
  746.    This manual uses the following typographic conventions:
  747.  
  748. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  749.    Example of Convention    Description
  750.    ──────────────────────────────────────────────────────────────────────────
  751.    QB.LIB, ADD.EXE, COPY,   Uppercase (capital) letters indicate file names
  752.    LINK, /X                 and DOS-level commands. Uppercase is also used
  753.                             for command-line options (unless the application
  754.                             accepts only lowercase).
  755.  
  756.    SUB, IF, LOOP, PRINT,    Bold capital letters indicate language-specific
  757.    WHILE, TIME$             keywords with special meaning to Microsoft BASIC.
  758.    Example of Convention    Description
  759.    ──────────────────────────────────────────────────────────────────────────
  760.   WHILE, TIME$             keywords with special meaning to Microsoft BASIC.
  761.                             Keywords are a required part of statement syntax,
  762.                             unless they are enclosed in double brackets as
  763.                             explained below. In programs you write, you must
  764.                             enter keywords exactly as shown. However, you can
  765.                             use uppercase letters or lowercase letters.
  766.  
  767.    CALL NewProc(arg1!,      This kind of type is used for program examples,
  768.    var2%)                   program output, and error messages within the
  769.                             text.
  770.  
  771.    '$INCLUDE:'BC.BI'        A column of three dots indicates that part of the
  772.      .                      example program has been intentionally omitted.
  773.      .
  774.      .
  775.    CHAIN "PROG1"
  776.    END
  777.  
  778.    ' Make one pass          The apostrophe (single right quotation mark)
  779.    Example of Convention    Description
  780.    ──────────────────────────────────────────────────────────────────────────
  781.   ' Make one pass          The apostrophe (single right quotation mark)
  782.                             marks the beginning of a comment in sample
  783.                             programs.
  784.  
  785.    filespec                 Italic letters indicate placeholders for
  786.                             information you must supply, such as a file name.
  787.                             Italics are also occasionally used in the text
  788.                             for emphasis.
  789.  
  790.    [[optional-item]]        Items inside double square brackets are optional.
  791.  
  792.    {choice1 | choice2}      Braces and a vertical bar indicate a choice among
  793.                             two or more items. You must choose one of the
  794.                             items unless all of the items are also enclosed
  795.                             in double square brackets.
  796.  
  797.    repeating elements...    Three dots following an item indicate that more
  798.                             items having the same form may appear.
  799.  
  800.    Example of Convention    Description
  801.    ──────────────────────────────────────────────────────────────────────────
  802. 
  803.    ALT+F1                   Capital letters are used for the names of keys
  804.                             and key sequences, such as ENTER and CTRL+R.
  805.  
  806.                             A plus (+) indicates a combination of keys. For
  807.                             example, CTRL+E means to hold down the CTRL key
  808.                             while pressing the E key.
  809.  
  810.                             The carriage-return key, sometimes marked with a
  811.                             bent arrow, is referred to as ENTER.
  812.  
  813.                             The cursor movement ("arrow") keys on the numeric
  814.                             keypad are called DIRECTION keys. Individual
  815.                             DIRECTION keys are referred to by the direction
  816.                             of the arrow on the key top (LEFT, RIGHT, UP,
  817.                             DOWN) or the name on the key top (PGUP, PGDN).
  818.  
  819.                             The key names used in this manual correspond to
  820.                             the names on the IBM(R) Personal Computer keys.
  821.    Example of Convention    Description
  822.    ──────────────────────────────────────────────────────────────────────────
  823.                            the names on the IBM(R) Personal Computer keys.
  824.                             Other machines may use different names.
  825.  
  826.    "defined term"           Quotation marks usually indicate a new term
  827.                             defined in the text.
  828.  
  829.    Video Graphics Array     Acronyms are usually spelled out the first time
  830.    (VGA)                    they are used.
  831.    ──────────────────────────────────────────────────────────────────────────
  832.  
  833.  
  834.    The syntax below (for the "LOCK...UNLOCK" statements) illustrates many of
  835.    the typographic conventions in this manual:
  836.  
  837.    LOCK[[#]]filenumber[[,{record|[[start]] TO end}]] . . .
  838.    UNLOCK[[#]]filenumber[[,{record |[[start]] TO end}]]
  839.  
  840.    ──────────────────────────────────────────────────────────────────────────
  841.    NOTE
  842.      Throughout this manual, the term "DOS" refers to both the MS-DOS(R) and
  843.      IBM Personal Computer DOS operating systems. The name of a specific
  844.      operating system is used when it is necessary to note features that are
  845.      unique to that system. The term "BASICA" refers to interpreted versions
  846.      of BASIC in general.
  847.    ──────────────────────────────────────────────────────────────────────────
  848.  
  849.  
  850.  Programming Style in this Manual
  851.  
  852.    The following guidelines were used in writing programs in this manual and
  853.    on the distribution disks. These guidelines are only recommendations for
  854.    program readability; you are not obliged to follow them when writing your
  855.    own programs.
  856.  
  857.    ■ Keywords and symbolic constants appear in uppercase letters:
  858.  
  859.      ' PRINT, DO, LOOP, UNTIL are keywords:
  860.      PRINT "Title Page"
  861.      DO LOOP UNTIL Response$ = "N"
  862.  
  863.      ' FALSE and TRUE are symbolic constants
  864.      ' equal to 0 and -1, respectively:
  865.      CONST FALSE = 0, TRUE = NOT FALSE
  866.  
  867.    ■ Variable names are in lowercase with an initial capital letter; variable
  868.      names with more than one syllable may contain other capital letters to
  869.      clarify the division:
  870.  
  871.      NumRecords% = 45
  872.      DateOfBirth$ = "11/24/54"
  873.  
  874.    ■ Line labels are used instead of line numbers. The use of line labels is
  875.      restricted to event-trapping and error-handling routines, as well as
  876.      DATA statements when referenced with RESTORE:
  877.  
  878.      ' TimerHandler and ScreenTwoData are line labels:
  879.      ON TIMER GOSUB TimerHandler
  880.      RESTORE ScreenTwoData
  881.  
  882.    ■ As noted in the preceding section, a single apostrophe (') introduces
  883.      comments:
  884.  
  885.      ' This is a comment; these two lines
  886.      ' are ignored when the program is running.
  887.  
  888.    ■ Control-flow blocks and statements in procedures or subroutines are
  889.      indented from the enclosing code:
  890.  
  891.      SUB GetInput STATIC
  892.         FOR I% = 1 TO 10
  893.            INPUT X
  894.            IF X > 0 THEN
  895.               .
  896.               .
  897.               .
  898.            ELSE
  899.               .
  900.               .
  901.               .
  902.            END IF
  903.         NEXT I%
  904.      END SUB
  905.  
  906.  
  907.  
  908.  ────────────────────────────────────────────────────────────────────────────
  909.  PART 1  SELECTED PROGRAMMING TOPICS
  910.  ────────────────────────────────────────────────────────────────────────────
  911.  
  912.    Part 1 introduces the fundamentals of programming in BASIC. Simpler topics
  913.    are covered first.
  914.  
  915.    Chapter 1 discusses the control-flow structures that direct your
  916.    program's execution. Chapter 2 is about QuickBASIC SUB and FUNCTION
  917.    procedures, two very powerful programming tools. Chapter 3 describes the
  918.    ways you can use QuickBASIC to work with the data your program accepts and
  919.    produces. Chapter 4 covers the use of text strings, and Chapter 5
  920.    presents QuickBASIC's graphics capabilities.
  921.  
  922.    More advanced topics are covered in the last two chapters. Chapter 6
  923.    looks at error and event trapping, and Chapter 7 tells you how to use
  924.    programming with modules to your advantage.
  925.  
  926.  
  927.  
  928.  ────────────────────────────────────────────────────────────────────────────
  929.  Chapter 1  Control-Flow Structures
  930.  
  931.    This chapter shows you how to use control-flow structures──specifically,
  932.    loops and decision statements──to control the flow of your program's
  933.    execution. Loops make a program execute a sequence of statements however
  934.    many times you want. Decision statements let the program decide which of
  935.    several alternative paths to take.
  936.  
  937.    When you are finished with this chapter, you will know how to do the
  938.    following tasks related to using loops and decision statements in your
  939.    BASIC programs:
  940.  
  941.    ■ Compare expressions using relational operators
  942.  
  943.    ■ Combine string or numeric expressions with logical operators and
  944.      determine if the resulting expression is true or false
  945.  
  946.    ■ Create branches in the flow of the program with the statements
  947.      IF...THEN...ELSE and SELECT CASE
  948.  
  949.    ■ Write loops that repeat statements a specific number of times
  950.  
  951.    ■ Write loops that repeat statements while or until a certain condition is
  952.      true
  953.  
  954.  
  955.  1.1  Changing Statement Execution Order
  956.  
  957.    Left unchecked by control-flow statements, a program's logic flows through
  958.    statements from left to right, top to bottom. While some very simple
  959.    programs can be written with only this unidirectional flow, most of the
  960.    power and utility of any programming language comes from its ability to
  961.    change statement execution order with decision structures and loops.
  962.  
  963.    With a decision structure, a program can evaluate an expression, then
  964.    branch to one of several different groups of related statements (statement
  965.    blocks) depending on the result of the evaluation. With a loop, a program
  966.    can repeatedly execute statement blocks.
  967.  
  968.    If you are coming to this version of BASIC after programming in BASICA,
  969.    you will appreciate the added versatility of these additional control-flow
  970.    structures:
  971.  
  972.    ■ The block IF...THEN...ELSE statement
  973.  
  974.    ■ The SELECT CASE statement
  975.  
  976.    ■ The DO...LOOP and EXIT DO statements
  977.  
  978.    ■ The EXIT FOR statement, which provides an alternative way to exit
  979.      FOR...NEXT loops
  980.  
  981.  
  982.  1.2  Boolean Expressions
  983.  
  984.    A Boolean expression is any expression that returns the value "true" or
  985.    "false." BASIC uses Boolean expressions in certain kinds of decision
  986.    structures and loops. The following IF...THEN...ELSE statement contains a
  987.    Boolean expression, X < Y:
  988.  
  989.    IF X < Y THEN CALL Procedure1 ELSE CALL Procedure2
  990.  
  991.    In the previous example, if the Boolean expression is true (if the value
  992.    of the variable X is in fact less than the value of the variable Y), then
  993.    Procedure1 is executed; otherwise (if X is greater than or equal to Y),
  994.    Procedure2 is executed.
  995.  
  996.    The preceding example also demonstrates a common use of Boolean
  997.    expressions: comparing two other expressions (in this case, X and Y) to
  998.    determine the relationship between them. These comparisons are made with
  999.    the relational operators shown in Table 1.1.
  1000.  
  1001.    Table 1.1  Relational Operators Used in BASIC
  1002.    Operator                 Meaning
  1003.    ──────────────────────────────────────────────────────────────────────────
  1004.    =                        Equal
  1005.  
  1006.    < >                      Not equal
  1007.  
  1008.    <                        Less than
  1009.  
  1010.    <=                       Less than or equal to
  1011.  
  1012.    >                        Greater than
  1013.  
  1014.    >=                       Greater than or equal to
  1015.    ──────────────────────────────────────────────────────────────────────────
  1016.  
  1017.    You can use these relational operators to compare string expressions. In
  1018.    this case "greater than," "less than," and so on refer to alphabetical
  1019.    order. For example, the following expression is true, since the word
  1020.    "deduce" comes alphabetically before the word "deduct":
  1021.  
  1022.    "deduce" < "deduct"
  1023.  
  1024.    Logical operators
  1025.  
  1026.    Boolean expressions also frequently use the "logical operators" AND, OR,
  1027.    NOT, XOR, IMP, and EQV. These operators allow you to construct compound
  1028.    tests from one or more Boolean expressions. For example,
  1029.  
  1030.    expression1 AND expression2
  1031.  
  1032.    is true only if expression1 and expression2 are both true. Thus, in the
  1033.    following example, the message All sorted is printed only if both the
  1034.    Boolean expressions X <= Y and Y <= Z are true:
  1035.  
  1036.    IF (X <= Y) AND (Y <= Z) THEN PRINT "All sorted"
  1037.  
  1038.    The parentheses around the Boolean expressions in the last example are not
  1039.    really necessary, since relational operators such as <= are evaluated
  1040.    before logical operators such as AND. However, parentheses make a complex
  1041.    Boolean expression more readable and ensure that its components are
  1042.    evaluated in the order that you intend.
  1043.  
  1044.    BASIC uses the numeric values -1 and 0 to represent true and false,
  1045.    respectively. You can see this by asking BASIC to print a true expression
  1046.    and a false expression, as in the next example:
  1047.  
  1048.    x = 5
  1049.    y = 10
  1050.    PRINT x < y  ' Evaluate, print a "true"  Boolean expression.
  1051.    PRINT x > y  ' Evaluate, print a "false" Boolean expression.
  1052.  
  1053.    Output
  1054.  
  1055.    -1
  1056.     0
  1057.  
  1058.    The value -1 for true makes more sense when you consider how BASIC's NOT
  1059.    operator works: NOT inverts each bit in the binary representation of its
  1060.    operand, changing 1 bits to 0 bits, and 0 bits to 1 bits. Therefore, since
  1061.    the integer value 0 (false) is stored internally as a sequence of sixteen
  1062.    0 bits, NOT 0 (true) is stored internally as sixteen 1 bits, as shown
  1063.    below:
  1064.  
  1065.    0000000000000000
  1066.  
  1067.    TRUE = NOT FALSE = 1111111111111111
  1068.  
  1069.    In the two's-complement method that BASIC uses to store integers, sixteen
  1070.    1 bits represent the value -1.
  1071.  
  1072.    Note that BASIC outputs -1 when it evaluates a Boolean expression as true;
  1073.    however, BASIC considers any nonzero value to be true, as shown by the
  1074.    output from the following example:
  1075.  
  1076.    INPUT "Enter a value: ", x
  1077.  
  1078.    IF x THEN PRINT x "is true."
  1079.  
  1080.    Output
  1081.  
  1082.    Enter a value: 2
  1083.     2 is true.
  1084.  
  1085.    The NOT operator in BASIC is a "bitwise" operator. Some programming
  1086.    languages, such as C and Pascal, have both a bitwise NOT operator and a
  1087.    "logical" NOT operator. The distinction is as follows:
  1088.  
  1089.    ■ A bitwise NOT returns false (0) only for the value -1.
  1090.  
  1091.    ■ A logical NOT returns false (0) for any true (nonzero) value.
  1092.  
  1093.    In BASIC, for any true expression not equal to -1, NOT expression returns
  1094.    another true value, as shown by the following list:
  1095.  
  1096.    Value of expression      Value of NOT expression
  1097.    ──────────────────────────────────────────────────────────────────────────
  1098.     1                       -2
  1099.  
  1100.     2                       -3
  1101.  
  1102.    -2                        1
  1103.  
  1104.    -1                        0
  1105.    ──────────────────────────────────────────────────────────────────────────
  1106.  
  1107.    So beware: NOT expression is false only if expression evaluates to a value
  1108.    of -1. If you define Boolean constants or variables for use in your
  1109.    programs, use -1 for true.
  1110.  
  1111.    You can use the values 0 and -1 to define helpful mnemonic Boolean
  1112.    constants for use in loops or decisions. This technique is used in many of
  1113.    the examples in this manual, as shown in the following program fragment,
  1114.    which sorts the elements of an array named Amount in ascending order:
  1115.  
  1116.    ' Define symbolic constants to use in program:
  1117.    CONST FALSE = 0, TRUE = NOT FALSE
  1118.    .
  1119.    .
  1120.    .
  1121.  
  1122.    DO
  1123.       Swaps = FALSE
  1124.       FOR I = 1 TO TransacNum - 1
  1125.          IF Amount(I) < Amount(I+1) THEN
  1126.             SWAP Amount(I), Amount(I+1)
  1127.             Swaps = TRUE
  1128.          END IF
  1129.       NEXT I
  1130.    LOOP WHILE Swaps        ' Keep looping while Swaps is TRUE.
  1131.    .
  1132.    .
  1133.    .
  1134.  
  1135.  
  1136.  1.3  Decision Structures
  1137.  
  1138.    Based on the value of an expression, decision structures cause a program
  1139.    to take one of the following two actions:
  1140.  
  1141.    1. Execute one of several alternative statements within the decision
  1142.       structure itself
  1143.  
  1144.    2. Branch to another part of the program outside the decision structure
  1145.  
  1146.    In BASICA, decision-making is handled solely by the single-line
  1147.    IF...THEN[[...ELSE]] statement. In its simplest form (IF...THEN) the
  1148.    expression following the IF keyword is evaluated. If the expression is
  1149.    true, the program executes the statements following the THEN keyword; if
  1150.    the expression is false, the program continues with the next line after
  1151.    the IF...THEN statement. Lines 50 and 70 from the following BASICA program
  1152.    fragment show examples of IF...THEN:
  1153.  
  1154.    30  INPUT A
  1155.    40  ' If A is greater than 100, print a message and branch
  1156.    45  ' back to line 30; otherwise, go on to line 60:
  1157.    50  IF A > 100 THEN PRINT "Too big": GOTO 30
  1158.    60  ' If A is equal to 100, branch to line 300;
  1159.    65  ' otherwise, go on to line 80:
  1160.    70  IF A = 100 THEN GOTO 300
  1161.    80  PRINT A/100: GOTO 30
  1162.    .
  1163.    .
  1164.    .
  1165.  
  1166.    By adding the ELSE clause to an IF...THEN statement, you can have your
  1167.    program take one set of actions (those following the THEN keyword) if an
  1168.    expression is true, and another set of actions (those following the ELSE
  1169.    keyword) if it is false. The next program fragment shows how ELSE works in
  1170.    an IF...THEN...ELSE statement:
  1171.  
  1172.    10 INPUT "What is your password"; Pass$
  1173.    15 ' If user enters "sword", branch to line 50;
  1174.    20 ' otherwise, print a message and branch back to line 10:
  1175.    30 IF Pass$="sword" THEN 50 ELSE PRINT "Try again": GOTO 10
  1176.    .
  1177.    .
  1178.    .
  1179.  
  1180.    While BASICA's single-line IF...THEN...ELSE is adequate for simple
  1181.    decisions, it can lead to virtually unreadable code in cases of more
  1182.    complicated ones. This is especially true if you write your programs so
  1183.    all alternative actions take place within the IF...THEN...ELSE statement
  1184.    itself or if you nest IF...THEN... ELSE statements (that is, if you put
  1185.    one IF...THEN...ELSE inside another, a perfectly legal construction). As
  1186.    an example of how difficult it is to follow even a simple test, consider
  1187.    the next fragment from a BASICA program:
  1188.  
  1189.    10 ' The following nested IF...THEN...ELSE statements print
  1190.    15 ' different output for each of the following four cases:
  1191.    20 '    1) A <= 50, B <= 50     3)  A > 50, B <= 50
  1192.    25 '    2) A <= 50, B > 50      4)  A > 50, B > 50
  1193.    30
  1194.    35 INPUT A, B
  1195.    40
  1196.    45 ' Note: even though line 70 extends over several physical
  1197.    50 ' lines on the screen, it is just one "logical line"
  1198.    55 ' (everything typed before the <ENTER> key was pressed).
  1199.    60 ' BASICA wraps long lines on the screen.
  1200.    65
  1201.    70  IF A <= 50 THEN IF B <= 50 THEN PRINT "A <= 50, B <= 50"
  1202.    ELSE PRINT "A <= 50, B > 50" ELSE IF B <= 50 THEN PRINT "A >
  1203.    50, B <= 50" ELSE PRINT "A > 50, B > 50"
  1204.  
  1205.    To avoid the kind of complicated statement shown above, BASIC now includes
  1206.    the block form of the IF...THEN...ELSE statement, so that a decision is no
  1207.    longer restricted to one logical line. The following shows the same BASICA
  1208.    program rewritten to use block IF...THEN...ELSE:
  1209.  
  1210.    INPUT A, B
  1211.    IF A <= 50 THEN
  1212.       IF B <= 50 THEN
  1213.          PRINT "A <= 50, B <= 50"
  1214.       ELSE
  1215.          PRINT "A <= 50, B > 50"
  1216.       END IF
  1217.    ELSE
  1218.       IF B <= 50 THEN
  1219.          PRINT "A > 50, B <= 50"
  1220.       ELSE
  1221.          PRINT "A > 50, B > 50"
  1222.       END IF
  1223.    END IF
  1224.  
  1225.    QuickBASIC also provides the SELECT CASE...END SELECT (referred to as
  1226.    SELECT CASE) statement for structured decisions.
  1227.  
  1228.    Both the block IF...THEN...ELSE statement and the SELECT CASE statement
  1229.    allow the appearance of your code to be based on program logic, rather
  1230.    than requiring many statements to be crowded onto one line. This gives you
  1231.    increased flexibility while you are programming, as well as improved
  1232.    program readability and ease of maintenance when you are done.
  1233.  
  1234.  1.3.1  Block IF...THEN...ELSE
  1235.  
  1236.    Table 1.2 shows the syntax of the block IF...THEN...ELSE statement and
  1237.    gives an example of its use.
  1238.  
  1239.    Table 1.2  Block IF...THEN...ELSE Syntax and Example
  1240.    Syntax                               Example
  1241.    ──────────────────────────────────────────────────────────────────────────
  1242.    IF condition1 THEN                   IF X > 0 THEN
  1243.      [[statementblock-1]]                 PRINT "X is positive"
  1244.    [[ELSEIF condition2 THEN               PosNum = PosNum + 1
  1245.      [[statementblock-2]]]]             ELSEIF X < 0 THEN
  1246.    .                                      PRINT "X is negative"
  1247.    .                                      NegNum = NegNum + 1
  1248.    .                                    ELSE
  1249.    [[ELSE                                 PRINT "X is zero"
  1250.      [[statementblock-n]]]]             END IF
  1251.    END IF
  1252.    ──────────────────────────────────────────────────────────────────────────
  1253.  
  1254.    The arguments condition1, condition2, and so on are expressions. They can
  1255.    be any numeric expression──in which case true becomes any nonzero value,
  1256.    and false is zero──or they can be Boolean expressions, in which case true
  1257.    is -1 and false is zero. As explained in Section 1.2, Boolean expressions
  1258.    typically compare two numeric or string expressions using one of the
  1259.    relational operators such as < or >=.
  1260.  
  1261.    Each IF, ELSEIF, and ELSE clause is followed by a block of statements.
  1262.    None of the statements in the block can be on the same line as the IF,
  1263.    ELSEIF, or ELSE clause; otherwise, BASIC considers it a single-line
  1264.    IF...THEN statement.
  1265.  
  1266.    BASIC evaluates each of the expressions in the IF and ELSEIF clauses from
  1267.    top to bottom, skipping over statement blocks until it finds the first
  1268.    true expression. When it finds a true expression, it executes the
  1269.    statements corresponding to the expression, then branches out of the block
  1270.    to the statement following the END IF clause.
  1271.  
  1272.    If none of the expressions in the IF or ELSEIF clauses is true, BASIC
  1273.    skips to the ELSE clause, if there is one, and executes its statements.
  1274.    Otherwise, if there is no ELSE clause, the program continues with the next
  1275.    statement after the END IF clause.
  1276.  
  1277.    The ELSE and ELSEIF clauses are both optional, as shown in the following
  1278.    example:
  1279.  
  1280.    ' If the value of X is less than 100, do the two statements
  1281.    ' before END IF; otherwise, go to the INPUT statement
  1282.    ' following END IF:
  1283.  
  1284.    IF X < 100 THEN
  1285.       PRINT X
  1286.       Number = Number + 1
  1287.    END IF
  1288.    INPUT "New value"; Response$
  1289.    .
  1290.    .
  1291.    .
  1292.  
  1293.    A single block IF...THEN...ELSE can contain multiple ELSEIF statements, as
  1294.    shown below:
  1295.  
  1296.    IF C$ >= "A" AND C$ <= "Z" THEN
  1297.       PRINT "Capital letter"
  1298.    ELSEIF C$ >= "a" AND C$ <= "z" THEN
  1299.       PRINT "Lowercase letter"
  1300.    ELSEIF C$ >= "0" AND C$ <= "9" THEN
  1301.       PRINT "Number"
  1302.    ELSE
  1303.       PRINT "Not alphanumeric"
  1304.    END IF
  1305.  
  1306.    At most, only one block of statements is executed, even if more than one
  1307.    condition is true. For example, if you enter the word ace as input to the
  1308.    next example, it prints the message Input too short but does not print the
  1309.    message Can't start with an a:
  1310.  
  1311.    INPUT Check$
  1312.    IF LEN(Check$) > 6 THEN
  1313.       PRINT "Input too long"
  1314.    ELSEIF LEN(Check$) < 6 THEN
  1315.       PRINT "Input too short"
  1316.    ELSEIF LEFT$(Check$, 1) = "a" THEN
  1317.       PRINT "Can't start with an a"
  1318.    END IF
  1319.  
  1320.    IF...THEN...ELSE statements can be nested; in other words, you can put an
  1321.    IF...THEN...ELSE statement inside another IF...THEN...ELSE statement, as
  1322.    shown here:
  1323.  
  1324.    IF X > 0 THEN
  1325.       IF Y > 0 THEN
  1326.          IF Z > 0 THEN
  1327.             PRINT "All are greater than zero."
  1328.          ELSE
  1329.             PRINT "Only X and Y greater than zero."
  1330.          END IF
  1331.       END IF
  1332.    ELSEIF X = 0 THEN
  1333.       IF Y = 0 THEN
  1334.          IF Z = 0 THEN
  1335.             PRINT "All equal zero."
  1336.          ELSE
  1337.             PRINT "Only X and Y equal zero."
  1338.          END IF
  1339.       END IF
  1340.    ELSE
  1341.       PRINT "X is less than zero."
  1342.    END IF
  1343.  
  1344.  1.3.2  SELECT CASE
  1345.  
  1346.    The SELECT CASE statement is a multiple-choice decision structure similar
  1347.    to the block IF...THEN...ELSE statement. Block IF...THEN...ELSE can be
  1348.    used anywhere SELECT CASE can be used.
  1349.  
  1350.    The major difference between the two is that SELECT CASE evaluates a
  1351.    single expression, then executes different statements or branches to
  1352.    different parts of the program based on the result. In contrast, a block
  1353.    IF...THEN...ELSE can evaluate completely different expressions.
  1354.  
  1355.    Examples
  1356.  
  1357.    The following examples illustrate the similarities and differences between
  1358.    the SELECT CASE and IF...THEN...ELSE statements. Here is an example of
  1359.    using block IF...THEN...ELSE for a multiple-choice decision:
  1360.  
  1361.    INPUT X
  1362.    IF X = 1 THEN
  1363.       PRINT "One"
  1364.    ELSEIF X = 2 THEN
  1365.       PRINT "Two"
  1366.    ELSEIF X = 3 THEN
  1367.       PRINT "Three"
  1368.    ELSE
  1369.       PRINT "Must be integer from 1-3."
  1370.    END IF
  1371.  
  1372.    The above decision is rewritten using SELECT CASE below:
  1373.  
  1374.    INPUT X
  1375.    SELECT CASE X
  1376.       CASE 1
  1377.          PRINT "One"
  1378.       CASE 2
  1379.          PRINT "Two"
  1380.       CASE 3
  1381.          PRINT "Three"
  1382.       CASE ELSE
  1383.          PRINT "Must be integer from 1-3."
  1384.    END SELECT
  1385.  
  1386.    The following decision can be made either with the SELECT CASE or the
  1387.    block IF...THEN...ELSE statement. The comparison is more efficient with
  1388.    the IF...THEN...ELSE statement because different expressions are being
  1389.    evaluated in the IF and ELSEIF clauses.
  1390.  
  1391.    INPUT X, Y
  1392.    IF X = 0 AND Y = 0 THEN
  1393.       PRINT "Both are zero."
  1394.    ELSEIF X = 0 THEN
  1395.       PRINT "Only X is zero."
  1396.    ELSEIF Y = 0 THEN
  1397.       PRINT "Only Y is zero."
  1398.    ELSE
  1399.       PRINT "Neither is zero."
  1400.    END IF
  1401.  
  1402.    1.3.2.1  Using the SELECT CASE Statement
  1403.  
  1404.    Table 1.3 shows the syntax of a SELECT CASE statement and an example.
  1405.  
  1406.    Table 1.3  SELECT CASE Syntax and Example
  1407.    Syntax                               Example
  1408.    ──────────────────────────────────────────────────────────────────────────
  1409.    SELECT CASE expression               INPUT TestValue
  1410.      CASE expressionlist1               SELECT CASE TestValue
  1411.        [[statementblock-1]]               CASE 1, 3, 5, 7, 9
  1412.      [[CASE expressionlist2                 PRINT "Odd"
  1413.        [[statementblock-2]]]]             CASE 2, 4, 6, 8
  1414.      .                                      PRINT "Even"
  1415.      .                                    CASE IS < 1
  1416.      .                                      PRINT "Too low"
  1417.      [[CASE ELSE                          CASE IS > 9
  1418.        [[statementblock-n]]]]               PRINT "Too high"
  1419.    END SELECT                             CASE ELSE
  1420.                                             PRINT "Not an integer"
  1421.                                         END SELECT
  1422.  
  1423.    ──────────────────────────────────────────────────────────────────────────
  1424.  
  1425.    The expressionlist arguments following a CASE clause can be one or more of
  1426.    the following, separated by commas:
  1427.  
  1428.    ■ A numeric expression or a range of numeric expressions
  1429.  
  1430.    ■ A string expression or a range of string expressions
  1431.  
  1432.    To specify a range of expressions, use the following syntax for the CASE
  1433.    statement:
  1434.  
  1435.    CASE expression TO expression CASE IS relational-operator expression
  1436.  
  1437.    The relational-operator is any of the operators shown in Table 1.1. For
  1438.    example, if you use CASE 1 TO 4, the statements associated with this case
  1439.    are executed when the expression in the SELECT CASE statement is greater
  1440.    than or equal to 1 and less than or equal to 4. If you use CASE IS < 5,
  1441.    the associated statements are executed only if expression is less than 5.
  1442.  
  1443.    If you are expressing a range with the TO keyword, be sure to put the
  1444.    lesser value first. For example, if you want to test for a value between
  1445.    -5 and -1, write the CASE statement as follows:
  1446.  
  1447.    CASE -5 TO -1
  1448.  
  1449.    However, the following statement is not a valid way to specify the range
  1450.    from -5 to -1, so the statements associated with this case are never
  1451.    executed:
  1452.  
  1453.    CASE -1 TO -5
  1454.  
  1455.    Similarly, a range of string constants should list the string that comes
  1456.    first alphabetically:
  1457.  
  1458.    CASE "aardvark" TO "bear"
  1459.  
  1460.    Multiple expressions or ranges of expressions can be listed for each CASE
  1461.    clause, as in the following lines:
  1462.  
  1463.    CASE 1 TO 4, 7 TO 9, WildCard1%, WildCard2%
  1464.    CASE IS = Test$, IS = "end of data"
  1465.    CASE IS < LowerBound, 5, 6, 12, IS > UpperBound
  1466.    CASE IS < "HAN", "MAO" TO "TAO"
  1467.  
  1468.    If the value of the SELECT CASE expression appears in the list following a
  1469.    CASE clause, only the statements associated with that CASE clause are
  1470.    executed. Control then jumps to the first executable statement following
  1471.    END SELECT, not the next block of statements inside the SELECT CASE
  1472.    structure, as shown by the output from the next example (where the user
  1473.    enters 1):
  1474.  
  1475.    INPUT x
  1476.    SELECT CASE x
  1477.       CASE 1
  1478.          PRINT "One, ";
  1479.       CASE 2
  1480.          PRINT "Two, ";
  1481.       CASE 3
  1482.          PRINT "Three, ";
  1483.    END SELECT
  1484.    PRINT "that's all"
  1485.  
  1486.    Output
  1487.  
  1488.    ? 1
  1489.    One, that's all
  1490.  
  1491.    If the same value or range of values appears in more than one CASE clause,
  1492.    only the statements associated with the first occurrence are executed, as
  1493.    shown by the next example's output (where the user has entered ABORIGINE):
  1494.  
  1495.    INPUT Test$
  1496.    SELECT CASE Test$
  1497.       CASE "A" TO "AZZZZZZZZZZZZZZZZZ"
  1498.          PRINT "An uppercase word beginning with capital A"
  1499.       CASE IS < "A"
  1500.          PRINT "Some sequence of nonalphabetic characters"
  1501.       CASE "ABORIGINE"
  1502.          ' This case is never executed since ABORIGINE
  1503.          ' falls within the range in the first CASE clause:
  1504.          PRINT "A special case"
  1505.    END SELECT
  1506.  
  1507.    Output
  1508.  
  1509.    ? ABORIGINE
  1510.    An uppercase word beginning with capital A
  1511.  
  1512.    If you use a CASE ELSE clause, it must be the last CASE clause listed in
  1513.    the SELECT CASE statement. The statements between a CASE ELSE clause and
  1514.    an END SELECT clause are executed only if the expression does not match
  1515.    any of the other CASE selections in the SELECT CASE statement. In fact, it
  1516.    is a good idea to have a CASE ELSE statement in your SELECT CASE block to
  1517.    handle unforeseen values for expression. However, if there is no CASE ELSE
  1518.    statement and no match is found in any CASE statement for expression, the
  1519.    program continues execution.
  1520.  
  1521.    Example
  1522.  
  1523.    The following program fragment demonstrates a common use of the SELECT
  1524.    CASE statement: it prints a menu on the screen, then branches to different
  1525.    subprograms based on the number typed by the user.
  1526.  
  1527.    DO                ' Start menu loop.
  1528.  
  1529.       CLS                  ' Clear screen.
  1530.  
  1531.       ' Print five menu choices on the screen:
  1532.       PRINT "MAIN MENU" : PRINT
  1533.       PRINT "1)  Add New Names"
  1534.       PRINT "2)  Delete Names"
  1535.       PRINT "3)  Change Information"
  1536.       PRINT "4)  List Names"
  1537.       PRINT
  1538.       PRINT "5)  EXIT"
  1539.  
  1540.       ' Print input prompt:
  1541.       PRINT : PRINT "Type your selection (1 to 5):"
  1542.  
  1543.       ' Wait for the user to press a key. INPUT$(1)
  1544.       ' reads one character input from the keyboard:
  1545.       Ch$ = INPUT$(1)
  1546.  
  1547.       ' Use SELECT CASE to process response:
  1548.       SELECT CASE Ch$
  1549.  
  1550.          CASE "1"
  1551.             CALL AddData
  1552.          CASE "2"
  1553.             CALL DeleteData
  1554.          CASE "3"
  1555.             CALL ChangeData
  1556.          CASE "4"
  1557.             CALL ListData
  1558.          CASE "5"
  1559.             EXIT DO         ' The only way to exit the menu loop
  1560.          CASE ELSE
  1561.             BEEP
  1562.       END SELECT
  1563.  
  1564.    LOOP                     ' End menu loop.
  1565.  
  1566.    END
  1567.  
  1568.    ' Subprograms AddData, DeleteData, ChangeData, and ListData:
  1569.    .
  1570.    .
  1571.    .
  1572.  
  1573.    1.3.2.2  SELECT CASE Versus ON...GOSUB
  1574.  
  1575.    You can use the more versatile SELECT CASE statement as a replacement for
  1576.    the old ON expression {GOSUB| GOTO} statement. The SELECT CASE statement
  1577.    has many advantages over the ON...GOSUB statement, as summarized below:
  1578.  
  1579.    ■ The expression in SELECT CASE expression can evaluate to either a string
  1580.      or numeric value. The expression given in the statement ON
  1581.      expression{GOSUB| GOTO} must evaluate to a number within the range 0 to
  1582.      255.
  1583.  
  1584.    ■ The SELECT CASE statement branches to a statement block immediately
  1585.      following the matching CASE clause. In contrast, ON expression GOSUB
  1586.      branches to a subroutine in another part of the program.
  1587.  
  1588.    ■ CASE clauses can be used to test an expression against a range of
  1589.      values. When the range is quite large, this is not easily done with ON
  1590.      expression{GOSUB| GOTO}, especially as shown in the following fragments.
  1591.  
  1592.    In the fragment below, the ON...GOSUB statement branches to one of the
  1593.    subroutines 50, 100, or 150, depending on the value input by the user:
  1594.  
  1595.    X% = -1
  1596.    WHILE X%
  1597.       INPUT "Enter choice (0 to quit): ", X%
  1598.       IF X% = 0 THEN END
  1599.       WHILE X% < 1 OR X% > 12
  1600.          PRINT "Must be value from 1 to 12"
  1601.          INPUT "Enter choice (0 to quit): ", X%
  1602.       WEND
  1603.       ON x% GOSUB 50,50,50,50,50,50,50,50,100,100,100,150
  1604.    WEND
  1605.    .
  1606.    .
  1607.    .
  1608.  
  1609.    Contrast the preceding example with the next one, which uses a SELECT CASE
  1610.    statement with ranges of values in each CASE clause:
  1611.  
  1612.    DO
  1613.       INPUT "Enter choice (0 to quit): ", X%
  1614.       SELECT CASE X%
  1615.          CASE 0
  1616.             END
  1617.          CASE 1 TO 8       ' Replaces "subroutine 50"
  1618.                            ' in preceding example
  1619.          CASE 9 TO 11      ' Replaces "subroutine 100"
  1620.                            ' in preceding example
  1621.          CASE 12           ' Replaces "subroutine 150"
  1622.                            ' in preceding example
  1623.          CASE ELSE         ' Input was out of range.
  1624.             PRINT "Must be value from 1 to 12"
  1625.          END SELECT
  1626.    LOOP
  1627.  
  1628.  
  1629.  1.4  Looping Structures
  1630.  
  1631.    Looping structures repeat a block of statements (the loop), either for a
  1632.    specified number of times or until a certain expression (the loop
  1633.    condition) is true or false.
  1634.  
  1635.    Users of BASICA are familiar with two looping structures, FOR...NEXT and
  1636.    WHILE...WEND, which are discussed in Sections 1.4.1 and 1.4.2,
  1637.    respectively. QuickBASIC has extended the available loop structures with
  1638.    the DO...LOOP statement, discussed in Section 1.4.3.
  1639.  
  1640.  1.4.1  FOR...NEXT Loops
  1641.  
  1642.    A FOR...NEXT loop repeats the statements enclosed in the loop a definite
  1643.    number of times, counting from a starting value to an ending value by
  1644.    increasing or decreasing a loop counter. As long as the loop counter has
  1645.    not reached the ending value, the loop continues to execute. Table 1.4
  1646.    shows the syntax of the FOR...NEXT statement and gives an example of its
  1647.    use.
  1648.  
  1649.    Table 1.4  FOR...NEXT Syntax and Example
  1650.    Syntax                               Example
  1651.    ──────────────────────────────────────────────────────────────────────────
  1652.    FOR counter = start TO end [[STEP    FOR I% = 1 to 10
  1653.    stepsize]]                             Array%(I%) = I%
  1654.      [[statementblock-1]]               NEXT
  1655.      [[EXIT FOR
  1656.      [[statementblock-2]]]]
  1657.    NEXT[[counter]]
  1658.    ──────────────────────────────────────────────────────────────────────────
  1659.  
  1660.    In a FOR...NEXT loop, the counter variable initially has the value of the
  1661.    expression start. After each repetition of the loop, the value of counter
  1662.    is adjusted. If you leave off the optional STEP keyword, the default value
  1663.    for this adjustment is one; that is, one is added to counter each time the
  1664.    loop executes. If you use STEP, then counter is adjusted by the amount
  1665.    stepsize. The stepsize argument can be any numeric value; if it is
  1666.    negative, the loop counts down from start to end. After the counter
  1667.    variable is increased or decreased, its value is compared with end. At
  1668.    this point, if either of the following is true, the loop is completed:
  1669.  
  1670.    ■ The loop is counting up (stepsize is positive) and counter is greater
  1671.      than end.
  1672.  
  1673.    ■ The loop is counting down (stepsize is negative) and counter is less
  1674.      than end.
  1675.  
  1676.    Figure 1.1 shows the logic of a FOR...NEXT loop when the value of
  1677.    stepsize is positive.
  1678.  
  1679.  
  1680.    ┌────────────────────────────────────┐
  1681.    │                                    │
  1682.    │   Figure 1.1 can be found on       │
  1683.    │   page 20 of the printed manual.   │
  1684.    │                                    │
  1685.    └────────────────────────────────────┘
  1686.  
  1687.    Figure 1.1  Logic of FOR...NEXT Loop with Positive STEP
  1688.  
  1689.    Figure 1.2 shows the logic of a FOR...NEXT loop when the value of
  1690.    stepsize is negative.
  1691.  
  1692.  
  1693.    ┌────────────────────────────────────┐
  1694.    │                                    │
  1695.    │   Figure 1.2 can be found on       │
  1696.    │   page 21 of the printed manual.   │
  1697.    │                                    │
  1698.    └────────────────────────────────────┘
  1699.  
  1700.    Figure 1.2  Logic of FOR...NEXT Loop with Negative STEP
  1701.  
  1702.    A FOR...NEXT statement always "tests at the top," so if one of the
  1703.    following conditions is true, the loop is never executed:
  1704.  
  1705.    ■ Step size is positive, and the initial value of start is greater than
  1706.      the value of end:
  1707.  
  1708.      ' Loop never executes, because I% starts out greater
  1709.      ' than 9:
  1710.      FOR I% = 10 TO 9
  1711.        .
  1712.        .
  1713.        .
  1714.      NEXT I%
  1715.  
  1716.    ■ Step size is negative, and the initial value of start is less than the
  1717.      value of end:
  1718.  
  1719.      ' Loop never executes, because I% starts out less than 9:
  1720.      FOR I% =  -10 TO -9 STEP -1
  1721.        .
  1722.        .
  1723.        .
  1724.      NEXT I%
  1725.  
  1726.    You don't have to use the counter argument in the NEXT clause; however, if
  1727.    you have several nested FOR...NEXT loops (one loop inside another),
  1728.    listing the counter arguments can be a helpful way to keep track of what
  1729.    loop you are in.
  1730.  
  1731.    Here are some general guidelines for nesting FOR...NEXT loops:
  1732.  
  1733.    ■ If you use a loop counter variable in a NEXT clause, the counter for a
  1734.      nested loop must appear before the counter for any enclosing loop. In
  1735.      other words, the following is a legal nesting:
  1736.  
  1737.      FOR I = 1 TO 10
  1738.         FOR J = -5 TO 0
  1739.         .
  1740.         .
  1741.         .
  1742.         NEXT J
  1743.      NEXT I
  1744.  
  1745.      However, the following is not a legal nesting:
  1746.  
  1747.      FOR I = 1 TO 10
  1748.         FOR J = -5 TO 0
  1749.         .
  1750.         .
  1751.         .
  1752.         NEXT I
  1753.      NEXT J
  1754.  
  1755.    ■ If you use a separate NEXT clause to end each loop, then the number of
  1756.      NEXT clauses must always be the same as the number of FOR clauses.
  1757.  
  1758.    ■ If you use a single NEXT clause to terminate several levels of
  1759.      FOR...NEXT loops, then the loop-counter variables must appear after the
  1760.      NEXT clause in "inside-out" order:
  1761.  
  1762.      NEXT innermost-loopcounter,... , outermost-loopcounter
  1763.  
  1764.      In this case, the number of loop-counter variables in the NEXT clause
  1765.      must be the same as the number of FOR clauses.
  1766.  
  1767.    Examples
  1768.  
  1769.    The three program fragments below illustrate different ways of nesting
  1770.    FOR... NEXT loops to produce the identical output that follows. The first
  1771.    example shows nested FOR...NEXT loops with loop counters and separate NEXT
  1772.    clauses for each loop:
  1773.  
  1774.    FOR I = 1 TO 2
  1775.       FOR J = 4 TO 5
  1776.          FOR K = 7 TO 8
  1777.             PRINT I, J, K
  1778.          NEXT K
  1779.       NEXT J
  1780.    NEXT I
  1781.  
  1782.    The following example also uses loop counters but only one NEXT clause for
  1783.    all three loops:
  1784.  
  1785.    FOR I = 1 TO 2
  1786.       FOR J = 4 TO 5
  1787.          FOR K = 7 TO 8
  1788.             PRINT I, J, K
  1789.    NEXT K, J, I
  1790.  
  1791.    The final example shows nested FOR...NEXT loops without loop counters:
  1792.  
  1793.    FOR I = 1 TO 2
  1794.       FOR J = 4 TO 5
  1795.          FOR K = 7 TO 8
  1796.             PRINT I, J, K
  1797.          NEXT
  1798.       NEXT
  1799.    NEXT
  1800.  
  1801.    Output
  1802.  
  1803.     1             4             7
  1804.     1             4             8
  1805.     1             5             7
  1806.     1             5             8
  1807.     2             4             7
  1808.     2             4             8
  1809.     2             5             7
  1810.     2             5             8
  1811.  
  1812.    1.4.1.1  Exiting a FOR...NEXT Loop with EXIT FOR
  1813.  
  1814.    Sometimes you may want to exit a FOR...NEXT loop before the counter
  1815.    variable reaches the ending value of the loop. You can do this with the
  1816.    EXIT FOR statement. A single FOR...NEXT loop can have any number of EXIT
  1817.    FOR statements, and the EXIT FOR statements can appear anywhere within the
  1818.    loop. The following fragment shows one use for an EXIT FOR statement:
  1819.  
  1820.    ' Print the square roots of the numbers from 1 to 30,000.
  1821.    ' If the user presses any key while this loop is executing,
  1822.    ' control exits from the loop:
  1823.    FOR I% = 1 TO 30000
  1824.       PRINT SQR(I%)
  1825.       IF INKEY$ <> "" THEN EXIT FOR
  1826.    NEXT
  1827.    .
  1828.    .
  1829.    .
  1830.  
  1831.    EXIT FOR exits only the smallest enclosing FOR...NEXT loop in which it
  1832.    appears. For example, if the user pressed a key while the following nested
  1833.    loops were executing, the program would simply exit the innermost loop. If
  1834.    the outermost loop were still active (that is if the value of I% <= 100),
  1835.    control would pass right back to the innermost loop:
  1836.  
  1837.    FOR I% = 1 TO 100
  1838.       FOR J% = 1 TO 100
  1839.          PRINT I% / J%
  1840.          IF INKEY$ <> "" THEN EXIT FOR
  1841.       NEXT J%
  1842.    NEXT I%
  1843.  
  1844.    1.4.1.2  Pausing Program Execution with FOR...NEXT
  1845.  
  1846.    Many BASICA programs use an empty FOR...NEXT loop such as the following to
  1847.    insert a pause in a program:
  1848.  
  1849.    .
  1850.    .
  1851.    .
  1852.    ' There are no statements in the body of this loop;
  1853.    ' all it does is count from 1 to 10,000
  1854.    ' using integers (whole numbers).
  1855.    FOR I% = 1 TO 10000: NEXT
  1856.    .
  1857.    .
  1858.    .
  1859.  
  1860.    For very short pauses or pauses that do not have to be some exact
  1861.    interval, using FOR...NEXT is fine. The problem with using an empty
  1862.    FOR...NEXT loop in this way is that different computers, different
  1863.    versions of BASIC, or different compile-time options can all affect how
  1864.    quickly the arithmetic in a FOR... NEXT loop is performed. So the length
  1865.    of a pause can vary widely. QuickBASIC's SLEEP statement now provides a
  1866.    better alternative. (See Chapter 8, "Statement and Function Summary," for
  1867.    the syntax of SLEEP.)
  1868.  
  1869.  1.4.2  WHILE...WEND Loops
  1870.  
  1871.    The FOR...NEXT statement is useful when you know ahead of time exactly how
  1872.    many times a loop should be executed. When you cannot predict the precise
  1873.    number of times a loop should be executed, but do know the condition that
  1874.    will end the loop, the WHILE...WEND statement is useful. Instead of
  1875.    counting to determine if it should keep executing a loop, WHILE...WEND
  1876.    repeats the loop as long as the loop condition is true.
  1877.  
  1878.    Table 1.5 shows the syntax of the WHILE...WEND statement and an example.
  1879.  
  1880.    Table 1.5  WHILE...WEND Syntax and Example
  1881.    Syntax                               Example
  1882.    ──────────────────────────────────────────────────────────────────────────
  1883.    WHILE condition                      INPUT R$
  1884.      [[statementblock]]                 WHILE R$ <> "Y" AND R$ <> "N"
  1885.    WEND                                   PRINT "Answer must be Y or N."
  1886.                                           INPUT R$
  1887.                                         WEND
  1888.    ──────────────────────────────────────────────────────────────────────────
  1889.  
  1890.    Example
  1891.  
  1892.    The following example assigns an initial value of ten to the variable X,
  1893.    then successively halves that value and keeps halving it until the value
  1894.    of X is less than .00001:
  1895.  
  1896.    X = 10
  1897.  
  1898.    WHILE X > .00001
  1899.       PRINT X
  1900.       X = X/2
  1901.    WEND
  1902.  
  1903.    Figure 1.3 illustrates the logic of a WHILE...WEND loop.
  1904.  
  1905.  
  1906.    ┌────────────────────────────────────┐
  1907.    │                                    │
  1908.    │   Figure 1.3 can be found on       │
  1909.    │   page 26 of the printed manual.   │
  1910.    │                                    │
  1911.    └────────────────────────────────────┘
  1912.  
  1913.    Figure 1.3  Logic of WHILE...WEND Loop
  1914.  
  1915.  1.4.3  DO...LOOP Loops
  1916.  
  1917.    Like the WHILE...WEND statement, the DO...LOOP statement executes a block
  1918.    of statements an indeterminate number of times; that is, exiting from the
  1919.    loop depends on the truth or falsehood of the loop condition. Unlike
  1920.    WHILE...WEND, DO...LOOP allows you to test for either a true or false
  1921.    condition. You can also put the test at either the beginning or the end of
  1922.    the loop.
  1923.  
  1924.    Table 1.6 shows the syntax of a loop that tests at the loop's beginning.
  1925.  
  1926.    Table 1.6  DO...LOOP Syntax and Example: Test at the Beginning
  1927.    Syntax                               Example
  1928.    ──────────────────────────────────────────────────────────────────────────
  1929.    DO[[{WHILE| UNTIL} condition]]       DO UNTIL INKEY$ <> ""
  1930.      [[statementblock-1]]                 ' An empty loop that
  1931.      [[EXIT DO                            ' pauses until a key
  1932.      [[statementblock-2]]]]               ' is pressed
  1933.    LOOP                                 LOOP
  1934.    ──────────────────────────────────────────────────────────────────────────
  1935.  
  1936.    Figures 1.4 and 1.5 illustrate the two kinds of DO...LOOP statements
  1937.    that test at the beginning of the loop.
  1938.  
  1939.  
  1940.    ┌────────────────────────────────────┐
  1941.    │                                    │
  1942.    │   Figure 1.4 can be found on       │
  1943.    │   page 27 of the printed manual.   │
  1944.    │                                    │
  1945.    └────────────────────────────────────┘
  1946.  
  1947.    Figure 1.4  Logic of DO WHILE...LOOP
  1948.  
  1949.  
  1950.    ┌────────────────────────────────────┐
  1951.    │                                    │
  1952.    │   Figure 1.5 can be found on       │
  1953.    │   page 28 of the printed manual.   │
  1954.    │                                    │
  1955.    └────────────────────────────────────┘
  1956.  
  1957.    Figure 1.5  Logic of DO UNTIL...LOOP
  1958.  
  1959.    Table 1.7 shows the syntax of a loop that tests for true or false at the
  1960.    end of the loop.
  1961.  
  1962.    Table 1.7  DO...LOOP Syntax and Example: Test at the End
  1963.    Syntax                               Example
  1964.    ──────────────────────────────────────────────────────────────────────────
  1965.    DO                                   DO
  1966.      [[statementblock-1]]                 INPUT "Change: ", Ch
  1967.      [[EXIT DO                            Total = Total + Ch
  1968.      [[statementblock-2]]]]             LOOP WHILE Ch <> 0
  1969.    LOOP[[{WHILE| UNTIL} condition]]
  1970.    ──────────────────────────────────────────────────────────────────────────
  1971.  
  1972.    Figures 1.6 and 1.7 illustrate the two kinds of DO...LOOP statements
  1973.    that test at the end of the loop.
  1974.  
  1975.  
  1976.    ┌────────────────────────────────────┐
  1977.    │                                    │
  1978.    │   Figure 1.6 can be found on       │
  1979.    │   page 29 of the printed manual.   │
  1980.    │                                    │
  1981.    └────────────────────────────────────┘
  1982.  
  1983.    Figure 1.6  Logic of DO...LOOP WHILE
  1984.  
  1985.  
  1986.    ┌────────────────────────────────────┐
  1987.    │                                    │
  1988.    │   Figure 1.7 can be found on       │
  1989.    │   page 30 of the printed manual.   │
  1990.    │                                    │
  1991.    └────────────────────────────────────┘
  1992.  
  1993.    Figure 1.7  Logic of DO...LOOP UNTIL
  1994.  
  1995.    1.4.3.1  Loop Tests: One Way to Exit DO...LOOP
  1996.  
  1997.    You can use a loop test at the end of a DO...LOOP statement to create a
  1998.    loop in which the statements always execute at least once. With the
  1999.    WHILE...WEND statement, you sometimes have to resort to the trick of
  2000.    presetting the loop variable to some value in order to force the first
  2001.    pass through the loop. With DO...LOOP, such tricks are no longer
  2002.    necessary. The examples below illustrate both approaches:
  2003.  
  2004.    ' WHILE...WEND loop tests at the top, so assigning "Y"
  2005.    ' to Response$ is necessary to force execution of the
  2006.    ' loop at least once:
  2007.    Response$ = "Y"
  2008.    WHILE UCASE$(Response$) = "Y"
  2009.       .
  2010.       .
  2011.       .
  2012.       INPUT "Do again"; Response$
  2013.    WEND
  2014.  
  2015.    ' The same loop using DO...LOOP to test after the
  2016.    ' body of the loop:
  2017.    DO
  2018.       .
  2019.       .
  2020.       .
  2021.       INPUT "Do again"; Response$
  2022.    LOOP WHILE UCASE$(Response$) = "Y"
  2023.  
  2024.    You can also rewrite a condition expressed with WHILE using UNTIL instead,
  2025.    as in the following:
  2026.  
  2027.    ' =======================================================
  2028.    '                  Using DO WHILE NOT...LOOP
  2029.    ' =======================================================
  2030.  
  2031.    ' While the end of file 1 has not been reached, read
  2032.    ' a line from the file and print it on the screen:
  2033.    DO WHILE NOT EOF(1)
  2034.       LINE INPUT #1, LineBuffer$
  2035.       PRINT LineBuffer$
  2036.    LOOP
  2037.  
  2038.    ' =======================================================
  2039.    '                    Using DO UNTIL...LOOP
  2040.    ' =======================================================
  2041.  
  2042.    ' Until the end of file 1 has been reached, read
  2043.    ' a line from the file and print it on the screen:
  2044.    DO UNTIL EOF(1)
  2045.       LINE INPUT #1, LineBuffer$
  2046.       PRINT LineBuffer$
  2047.    LOOP
  2048.  
  2049.    1.4.3.2  EXIT DO: An Alternative Way to Exit DO...LOOP
  2050.  
  2051.    Inside a DO...LOOP statement, other statements are executed that
  2052.    eventually change the loop-test condition from true to false or false to
  2053.    true, ending the loop. In the DO...LOOP examples presented so far, the
  2054.    test has occurred either at the beginning or the end of the loop. However,
  2055.    by using the EXIT DO statement to exit from the loop, you can move the
  2056.    test elsewhere inside the loop. A single DO...LOOP can contain any number
  2057.    of EXIT DO statements, and the EXIT DO statements can appear anywhere
  2058.    within the loop.
  2059.  
  2060.    Example
  2061.  
  2062.    The following example opens a file and reads it, one line at a time, until
  2063.    the end of the file is reached or until it finds the pattern input by the
  2064.    user. If it finds the pattern before getting to the end of the file, an
  2065.    EXIT DO statement exits the loop.
  2066.  
  2067.    INPUT "File to search: ", File$
  2068.    IF File$ = "" THEN END
  2069.  
  2070.    INPUT "Pattern to search for: ", Pattern$
  2071.    OPEN File$ FOR INPUT AS #1
  2072.  
  2073.    DO UNTIL EOF(1)    ' EOF(1) returns a true value if the
  2074.                       ' end of the file has been reached.
  2075.       LINE INPUT #1, TempLine$
  2076.       IF INSTR(TempLine$, Pattern$) > 0 THEN
  2077.  
  2078.          ' Print the first line containing the pattern and
  2079.          ' exit the loop:
  2080.          PRINT TempLine$
  2081.          EXIT DO
  2082.       END IF
  2083.    LOOP
  2084.  
  2085.  
  2086.  1.5  Sample Applications
  2087.  
  2088.    The sample applications for this chapter are a checkbook-balancing program
  2089.    and a program that ensures that every line in a text file ends with a
  2090.    carriage-return and line-feed sequence.
  2091.  
  2092.  1.5.1  Checkbook-Balancing Program (CHECK.BAS)
  2093.  
  2094.    This program prompts the user for the starting checking-account balance
  2095.    and all transactions──withdrawals or deposits──that have occurred. It then
  2096.    prints a sorted list of the transactions and the final balance in the
  2097.    account.
  2098.  
  2099.    Statements and Functions Used
  2100.  
  2101.    The program demonstrates the following statements discussed in this
  2102.    chapter:
  2103.  
  2104.    ■ DO...LOOP WHILE
  2105.  
  2106.    ■ FOR...NEXT
  2107.  
  2108.    ■ EXIT FOR
  2109.  
  2110.    ■ Block IF...THEN...ELSE
  2111.  
  2112.    Program Listing
  2113.  
  2114.    DIM Amount(1 TO 100)
  2115.    CONST FALSE = 0, TRUE = NOT FALSE
  2116.  
  2117.    CLS
  2118.    ' Get account's starting balance:
  2119.    INPUT "Type starting balance, then press <ENTER>: ", Balance
  2120.  
  2121.    ' Get transactions. Continue accepting input
  2122.    ' until the input is zero for a transaction,
  2123.    ' or until 100 transactions have been entered:
  2124.    FOR TransacNum% = 1 TO 100
  2125.       PRINT TransacNum%;
  2126.       PRINT ") Enter transaction amount (0 to end): ";
  2127.       INPUT "", Amount(TransacNum%)
  2128.       IF Amount(TransacNum%) = 0 THEN
  2129.          TransacNum% = TransacNum% - 1
  2130.          EXIT FOR
  2131.       END IF
  2132.    NEXT
  2133.  
  2134.    ' Sort transactions in ascending order,
  2135.    ' using a "bubble sort":
  2136.    Limit% = TransacNum%
  2137.    DO
  2138.       Swaps% = FALSE
  2139.       FOR I% = 1 TO (Limit% - 1)
  2140.  
  2141.          ' If two adjacent elements are out of order,
  2142.          ' switch those elements:
  2143.          IF Amount(I%) < Amount(I% + 1) THEN
  2144.             SWAP Amount(I%), Amount(I% + 1)
  2145.             Swaps% = I%
  2146.          END IF
  2147.       NEXT I%
  2148.  
  2149.       ' Sort on next pass only to where last switch was made:
  2150.       Limit% = Swaps%
  2151.  
  2152.    ' Sort until no elements are exchanged:
  2153.    LOOP WHILE Swaps%
  2154.  
  2155.    ' Print the sorted transaction array. If a transaction
  2156.    ' is greater than zero, print it as a "CREDIT"; if a
  2157.    ' transaction is less than zero, print it as a "DEBIT":
  2158.    FOR I% = 1 TO TransacNum%
  2159.       IF Amount(I%) > 0 THEN
  2160.          PRINT USING "CREDIT: $$#####.##"; Amount(I%)
  2161.       ELSEIF Amount(I%) < 0 THEN
  2162.          PRINT USING "DEBIT: $$#####.##"; Amount(I%)
  2163.       END IF
  2164.  
  2165.       ' Update balance:
  2166.       Balance = Balance + Amount(I%)
  2167.    NEXT I%
  2168.  
  2169.    ' Print the final balance:
  2170.    PRINT
  2171.    PRINT "--------------------------"
  2172.    PRINT USING "Final Balance: $$######.##"; Balance
  2173.    END
  2174.  
  2175.  1.5.2  Carriage-Return and Line-Feed Filter (CRLF.BAS)
  2176.  
  2177.    Some text files are saved in a format that uses only a carriage return
  2178.    (return to the beginning of the line) or a line feed (advance to the next
  2179.    line) to signify the end of a line. Many text editors expand this single
  2180.    carriage return (CR) or line feed (LF) to a carriage-return and line-feed
  2181.    (CR-LF) sequence whenever you load the file for editing. However, if you
  2182.    use a text editor that does not expand a single CR or LF to CR-LF, you may
  2183.    have to modify the file so it has the correct sequence at the end of each
  2184.    line.
  2185.  
  2186.    The following program is a filter that opens a file, expands a single CR
  2187.    or LF to a CR-LF combination, then writes the adjusted lines to a new
  2188.    file. The original contents of the file are saved in a file with a .BAK
  2189.    extension.
  2190.  
  2191.    Statements and Functions Used
  2192.  
  2193.    This program demonstrates the following statements discussed in this
  2194.    chapter:
  2195.  
  2196.    ■ DO...LOOP WHILE
  2197.  
  2198.    ■ DO UNTIL...LOOP
  2199.  
  2200.    ■ Block IF...THEN...ELSE
  2201.  
  2202.    ■ SELECT CASE...END SELECT
  2203.  
  2204.    To make this program more useful, it contains the following constructions
  2205.    not discussed in this chapter:
  2206.  
  2207.    ■ A FUNCTION procedure named Backup$ that creates the file with the .BAK
  2208.      extension.
  2209.  
  2210.      See Chapter 2, "SUB and FUNCTION Procedures," for more information on
  2211.      defining and using procedures.
  2212.  
  2213.    ■ An error-handling routine named ErrorHandler to deal with errors that
  2214.      could occur when the user enters a file name. For instance, if the user
  2215.      enters the name of a nonexistent file, this routine prompts for a new
  2216.      name. Without this routine, such an error would end the program.
  2217.  
  2218.      See Chapter 6, "Error and Event Trapping," for more information on
  2219.      trapping errors.
  2220.  
  2221.    Program Listing
  2222.  
  2223.    DEFINT A-Z             ' Default variable type is integer.
  2224.  
  2225.    ' The Backup$ FUNCTION makes a backup file with
  2226.    ' the same base as FileName$ plus a .BAK extension:
  2227.    DECLARE FUNCTION Backup$ (FileName$)
  2228.  
  2229.    ' Initialize symbolic constants and variables:
  2230.    CONST FALSE = 0, TRUE = NOT FALSE
  2231.  
  2232.    CarReturn$ = CHR$(13)
  2233.    LineFeed$ = CHR$(10)
  2234.  
  2235.    DO
  2236.       CLS
  2237.  
  2238.       ' Input the name of the file to change:
  2239.       INPUT "Which file do you want to convert"; OutFile$
  2240.  
  2241.       InFile$ = Backup$(OutFile$)  ' Get backup file's name.
  2242.  
  2243.       ON ERROR GOTO ErrorHandler   ' Turn on error trapping.
  2244.  
  2245.       NAME OutFile$ AS InFile$     ' Rename input file as
  2246.                                    ' backup file.
  2247.  
  2248.       ON ERROR GOTO 0              ' Turn off error trapping.
  2249.  
  2250.       ' Open backup file for input and old file for output:
  2251.       OPEN InFile$ FOR INPUT AS #1
  2252.       OPEN OutFile$ FOR OUTPUT AS #2
  2253.  
  2254.       ' The PrevCarReturn variable is a flag set to TRUE
  2255.       ' whenever the program reads a carriage-return character:
  2256.       PrevCarReturn = FALSE
  2257.  
  2258.    ' Read from input file until reaching end of file:
  2259.       DO UNTIL EOF(1)
  2260.  
  2261.          ' This is not end of file, so read a character:
  2262.          FileChar$ = INPUT$(1, #1)
  2263.  
  2264.          SELECT CASE FileChar$
  2265.  
  2266.          CASE CarReturn$        ' The character is a CR.
  2267.  
  2268.             ' If the previous character was also a
  2269.             ' CR, put a LF before the character:
  2270.             IF PrevCarReturn THEN
  2271.                 FileChar$ = LineFeed$ + FileChar$
  2272.             END IF
  2273.  
  2274.             ' In any case, set the PrevCarReturn
  2275.             ' variable to TRUE:
  2276.             PrevCarReturn = TRUE
  2277.  
  2278.         CASE LineFeed$         ' The character is a LF.
  2279.  
  2280.             ' If the previous character was not a
  2281.             ' CR, put a CR before the character:
  2282.             IF NOT PrevCarReturn THEN
  2283.                 FileChar$ = CarReturn$ + FileChar$
  2284.             END IF
  2285.  
  2286.             ' Set the PrevCarReturn variable to FALSE:
  2287.             PrevCarReturn = FALSE
  2288.  
  2289.          CASE ELSE              ' Neither a CR nor a LF.
  2290.  
  2291.             ' If the previous character was a CR,
  2292.             ' set the PrevCarReturn variable to FALSE
  2293.             ' and put a LF before the current character:
  2294.             IF PrevCarReturn THEN
  2295.                   PrevCarReturn = FALSE
  2296.                   FileChar$ = LineFeed$ + FileChar$
  2297.             END IF
  2298.  
  2299.          END SELECT
  2300.  
  2301.          ' Write the character(s) to the new file:
  2302.          PRINT #2, FileChar$;
  2303.       LOOP
  2304.  
  2305.       ' Write a LF if the last character in the file was a CR:
  2306.       IF PrevCarReturn THEN PRINT #2, LineFeed$;
  2307.  
  2308.    CLOSE                        ' Close both files.
  2309.       PRINT "Another file (Y/N)?"  ' Prompt to continue.
  2310.  
  2311.       ' Change the input to uppercase (capital letter):
  2312.       More$ = UCASE$(INPUT$(1))
  2313.  
  2314.    ' Continue the program if the user entered a "y" or a "Y":
  2315.    LOOP WHILE More$ = "Y"
  2316.    END
  2317.  
  2318.    ErrorHandler:           ' Error-handling routine
  2319.       CONST NOFILE = 53, FILEEXISTS = 58
  2320.  
  2321.       ' The ERR function returns the error code for last error:
  2322.       SELECT CASE ERR
  2323.          CASE NOFILE       ' Program couldn't find file
  2324.                            ' with input name.
  2325.  
  2326.             PRINT "No such file in current directory."
  2327.             INPUT "Enter new name: ", OutFile$
  2328.             InFile$ = Backup$(OutFile$)
  2329.             RESUME
  2330.          CASE FILEEXISTS   ' There is already a file named
  2331.                            ' <filename>.BAK in this directory:
  2332.                            ' remove it, then continue.
  2333.             KILL InFile$
  2334.             RESUME
  2335.          CASE ELSE         ' An unanticipated error occurred:
  2336.                            ' stop the program.
  2337.             ON ERROR GOTO 0
  2338.       END SELECT
  2339.  
  2340.    ' ======================== BACKUP$ =========================
  2341.    '   This procedure returns a file name that consists of the
  2342.    '   base name of the input file (everything before the ".")
  2343.    '   plus the extension ".BAK"
  2344.    ' ==========================================================
  2345.  
  2346.    FUNCTION Backup$ (FileName$) STATIC
  2347.  
  2348.       ' Look for a period:
  2349.       Extension = INSTR(FileName$, ".")
  2350.  
  2351.       ' If there is a period, add .BAK to the base:
  2352.       IF Extension > 0 THEN
  2353.          Backup$ = LEFT$(FileName$, Extension - 1) + ".BAK"
  2354.  
  2355.       ' Otherwise, add .BAK to the whole name:
  2356.       ELSE
  2357.          Backup$ = FileName$ + ".BAK"
  2358.       END IF
  2359.    END FUNCTION
  2360.  
  2361.  
  2362.  
  2363.  ────────────────────────────────────────────────────────────────────────────
  2364.  Chapter 2  SUB and FUNCTION Procedures
  2365.  
  2366.    This chapter explains how to simplify your programming by breaking
  2367.    programs into smaller logical components. These components──known as
  2368.    "procedures"──can then become building blocks that let you enhance and
  2369.    extend the BASIC language itself.
  2370.  
  2371.    When you are finished with this chapter, you will know how to perform the
  2372.    following tasks with procedures:
  2373.  
  2374.    ■ Define and call BASIC procedures
  2375.  
  2376.    ■ Use local and global variables in procedures
  2377.  
  2378.    ■ Use procedures instead of GOSUB subroutines and DEF FN functions
  2379.  
  2380.    ■ Pass arguments to procedures and return values from procedures
  2381.  
  2382.    ■ Write recursive procedures (procedures that can call themselves)
  2383.  
  2384.    Although you can create a BASIC program with any text editor, the
  2385.    QuickBASIC editor makes it especially easy to write programs that contain
  2386.    procedures. Also, in most cases QuickBASIC automatically generates a
  2387.    DECLARE statement when you save your program. (Using a DECLARE statement
  2388.    ensures that only the correct number and type of arguments are passed to a
  2389.    procedure and allows your program to call procedures defined in separate
  2390.    modules.)
  2391.  
  2392.  
  2393.  2.1  Procedures: Building Blocks for Programming
  2394.  
  2395.    As used in this chapter, the term "procedure" covers both SUB...END SUB
  2396.    and FUNCTION...END FUNCTION constructions. Procedures are useful for
  2397.    condensing repeated tasks. For example, suppose you are writing a program
  2398.    that you eventually intend to compile as a stand-alone application and you
  2399.    want the user of this application to be able to pass several arguments to
  2400.    the application from the command line. It then makes sense to turn this
  2401.    task──breaking the string returned by the COMMAND$ function into two or
  2402.    more arguments──into a separate procedure. Once you have this procedure up
  2403.    and running, you can use it in other programs. In essence, you are
  2404.    extending BASIC to fit your individual needs when you use procedures.
  2405.  
  2406.    These are the two major benefits of programming with procedures:
  2407.  
  2408.    1. Procedures allow you to break your programs into discrete logical
  2409.       units, each of which can be more easily debugged than can an entire
  2410.       program without procedures.
  2411.  
  2412.    2. Procedures used in one program can be used as building blocks in other
  2413.       programs, usually with little or no modification.
  2414.  
  2415.    You can also put procedures in your own Quick library, which is a special
  2416.    file that you can load into memory when you start QuickBASIC. Once the
  2417.    contents of a Quick library are in memory with QuickBASIC, any program
  2418.    that you write has access to the procedures in the library. This makes it
  2419.    easier for all of your programs both to share and save code. (See Appendix
  2420.    H, "Creating and Using Quick Libraries," for more information on how to
  2421.    build Quick libraries.)
  2422.  
  2423.  
  2424.  2.2  Comparing Procedures with Subroutines and Functions
  2425.  
  2426.    If you are familiar with earlier versions of BASIC, you might think of a
  2427.    SUB...END SUB procedure as being roughly similar to a GOSUB...RETURN
  2428.    subroutine. You will also notice some similarities between a FUNCTION...
  2429.    END FUNCTION procedure and a DEF FN...END DEF function. However,
  2430.    procedures have many advantages over these older constructions, as shown
  2431.    in Sections 2.2.1 and 2.2.2 below.
  2432.  
  2433.    ──────────────────────────────────────────────────────────────────────────
  2434.    NOTE
  2435.      To avoid confusion between a SUB procedure and the target of a GOSUB
  2436.      statement, SUBprocedures are referred to in this manual as
  2437.      "subprograms," while statement blocks accessed by
  2438.      GOSUB...RETURN statements are referred to as "subroutines."
  2439.    ──────────────────────────────────────────────────────────────────────────
  2440.  
  2441.  2.2.1  Comparing SUB with GOSUB
  2442.  
  2443.    Although use of the GOSUB subroutine does help break programs into
  2444.    manageable units, SUB procedures have a number of advantages over
  2445.    subroutines, as discussed below.
  2446.  
  2447.    2.2.1.1  Local and Global Variables
  2448.  
  2449.    In SUB procedures, all variables are local by default; that is, they exist
  2450.    only within the scope of the SUB procedure's definition. To illustrate,
  2451.    the variable named I in the Test subprogram below is local to Test, and
  2452.    has no connection with the variable named I in the module-level code:
  2453.  
  2454.    I = 1
  2455.    CALL Test
  2456.    PRINT I  ' I still equals 1.
  2457.    END
  2458.  
  2459.    SUB Test STATIC
  2460.          I = 50
  2461.    END SUB
  2462.  
  2463.    A GOSUB has a major drawback as a building block in programs: it contains
  2464.    only "global variables." With global variables, if you have a variable
  2465.    named I inside your subroutine, and another variable named I outside the
  2466.    subroutine but in the same module, they are one and the same. Any changes
  2467.    to the value of I in the subroutine affect I everywhere it appears in the
  2468.    module. As a result, if you try to patch a subroutine from one module into
  2469.    another module, you may have to rename subroutine variables to avoid
  2470.    conflict with variable names in the new module.
  2471.  
  2472.    2.2.1.2  Use in Multiple-Module Programs
  2473.  
  2474.    A SUB can be defined in one module and called from another. This
  2475.    significantly reduces the amount of code required for a program and
  2476.    increases the ease with which code can be shared among a number of
  2477.    programs.
  2478.  
  2479.    A GOSUB subroutine, however, must be defined and used in the same module.
  2480.  
  2481.    2.2.1.3  Operating on Different Sets of Variables
  2482.  
  2483.    A SUB procedure can be called any number of times within a program, with a
  2484.    different set of variables being passed to it each time. This is done by
  2485.    calling the SUB with an argument list. (See Section 2.5, "Passing
  2486.    Arguments to Procedures," for more information on how to do this.) In the
  2487.    next example, the subprogram Compare is called twice, with different pairs
  2488.    of variables passed to it each time:
  2489.  
  2490.    X = 4: Y = 5
  2491.  
  2492.    CALL Compare (X, Y)
  2493.  
  2494.    Z = 7: W = 2
  2495.    CALL Compare (Z, W)
  2496.    END
  2497.  
  2498.    SUB Compare (A, B)
  2499.       IF A < B THEN SWAP A, B
  2500.    END SUB
  2501.  
  2502.    Calling a GOSUB subroutine more than once in the same program and having
  2503.    it operate on a different set of variables each time is difficult. The
  2504.    process involves copying values to and from global variables, as shown in
  2505.    the next example:
  2506.  
  2507.    X = 4: Y = 5
  2508.    A = X: B = Y
  2509.    GOSUB Compare
  2510.    X = A: Y = B
  2511.  
  2512.    Z = 7 : W = 2
  2513.    A = Z : B = W
  2514.    GOSUB Compare
  2515.    Z = A : W = B
  2516.    END
  2517.  
  2518.    Compare:
  2519.       IF A < B THEN SWAP A, B
  2520.    RETURN
  2521.  
  2522.  2.2.2  Comparing FUNCTION with DEF FN
  2523.  
  2524.    While the multiline DEF FN function definition answers the need for
  2525.    functions more complex than can be squeezed on a single line, FUNCTION
  2526.    procedures give you this capability plus the additional advantages
  2527.    discussed below.
  2528.  
  2529.    2.2.2.1  Local and Global Variables
  2530.  
  2531.    By default, all variables within a FUNCTION procedure are local to it,
  2532.    although you do have the option of using global variables. (See Section
  2533.    2.6, "Sharing Variables with SHARED," for more information on procedures
  2534.    and global variables.)
  2535.  
  2536.    In a DEF FN function, variables used within the function's body are global
  2537.    to the current module by default (this is also true for GOSUB
  2538.    subroutines). However, you can make a variable in a DEF FN function local
  2539.    by putting it in a STATIC statement.
  2540.  
  2541.    2.2.2.2  Changing Variables Passed to the Procedure
  2542.  
  2543.    Variables are passed to FUNCTION procedures by reference or by value. When
  2544.    you pass a variable by reference, you can change the variable by changing
  2545.    its corresponding parameter in the FUNCTION. For example, after the call
  2546.    to GetRemainder in the next program, the value of X is 2, since the value
  2547.    of Mis 2 at the end of the FUNCTION:
  2548.  
  2549.    X = 89
  2550.    Y = 40
  2551.    PRINT GetRemainder(X, Y)
  2552.    PRINT X, Y                ' X is now 2.
  2553.    END
  2554.  
  2555.    FUNCTION GetRemainder (M, N)
  2556.       GetRemainder = M MOD N
  2557.       M = M \ N
  2558.    END FUNCTION
  2559.  
  2560.    Variables are passed to a DEF FN function only by value, so in the next
  2561.    example, FNRemainder changes M without affecting X :
  2562.  
  2563.    DEF FNRemainder (M, N)
  2564.       FNRemainder = M MOD N
  2565.       M = M \ N
  2566.    END DEF
  2567.  
  2568.    X = 89
  2569.    Y = 40
  2570.    PRINT FNRemainder(X, Y)
  2571.  
  2572.    PRINT X,Y   ' X is still
  2573.                ' 89.
  2574.  
  2575.    See Sections 2.5.5 and 2.5.6 for more information on the distinction
  2576.    between passing by reference and by value.
  2577.  
  2578.    2.2.2.3  Calling the Procedure within Its Definition
  2579.  
  2580.    A FUNCTION procedure can be "recursive"; in other words, it can call
  2581.    itself within its own definition. (See Section 2.9 for more information
  2582.    on how procedures can be recursive.) A DEF FN function cannot be
  2583.    recursive.
  2584.  
  2585.    2.2.2.4  Use in Multiple-Module Programs
  2586.  
  2587.    You can define a FUNCTION procedure in one module and use it in another
  2588.    module. You need to put a DECLARE statement in the module in which the
  2589.    FUNCTION is used; otherwise, your program thinks the FUNCTION name refers
  2590.    to a variable. (See Section 2.5.4, "Checking Arguments with the DECLARE
  2591.    Statement," for more information on using DECLARE this way.)
  2592.  
  2593.    A DEF FN function can only be used in the module in which it is defined.
  2594.    Unlike SUB or FUNCTION procedures, which can be called before they appear
  2595.    in the program, a DEF FN function must always be defined before it is used
  2596.    in a module.
  2597.  
  2598.    ──────────────────────────────────────────────────────────────────────────
  2599.    NOTE
  2600.      The name of a FUNCTION procedure can be any valid BASIC variable name,
  2601.      except one beginning with the letters FN. The name of a DEF FN function
  2602.      must always be preceded by FN.
  2603.    ──────────────────────────────────────────────────────────────────────────
  2604.  
  2605.  
  2606.  2.3  Defining Procedures
  2607.  
  2608.    BASIC procedure definitions have the following general syntax:
  2609.  
  2610.    {SUB| FUNCTION} procedurename[[(parameterlist)]] [[STATIC]]
  2611.      [[statementblock-1]]
  2612.      [[EXIT{SUB| FUNCTION}
  2613.        [[statementblock-2]]]]
  2614.    END{SUB| FUNCTION}
  2615.  
  2616.    The following list describes the parts of a procedure definition:
  2617.  
  2618. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  2619.    Part                     Description
  2620.    ──────────────────────────────────────────────────────────────────────────
  2621.    {SUB | FUNCTION}         Marks the beginning of a SUB or FUNCTION
  2622.                             procedure, respectively.
  2623.  
  2624.    procedurename            Any valid variable name up to 40 characters long.
  2625.                             The same name cannot be used for both a SUB and a
  2626.                             FUNCTION.
  2627.    Part                     Description
  2628.    ──────────────────────────────────────────────────────────────────────────
  2629.                            FUNCTION.
  2630.  
  2631.    parameterlist            A list of variables, separated by commas, that
  2632.                             shows the number and type of arguments to be
  2633.                             passed to the procedure. (Section 2.5.1 explains
  2634.                             the difference between parameters and arguments.)
  2635.  
  2636.    STATIC                   If you use the STATIC attribute, local variables
  2637.                             are STATIC; that is, they retain their values
  2638.                             between calls to the procedure.
  2639.                             If you omit the STATIC attribute, local variables
  2640.                             are "automatic" by default; that is, they are
  2641.                             initialized to zeros or null strings at the start
  2642.                             of each procedure call.
  2643.                             See Section 2.7, "Automatic and STATIC
  2644.                             Variables," for more information.
  2645.  
  2646.    END{SUB| FUNCTION}       Ends a SUB or FUNCTION definition. To run
  2647.                             correctly, every procedure must have exactly one
  2648.    Part                     Description
  2649.    ──────────────────────────────────────────────────────────────────────────
  2650.                            correctly, every procedure must have exactly one
  2651.                             END{SUB| FUNCTION} statement.
  2652.                             When your program encounters an END SUB or END
  2653.                             FUNCTION, it exits the procedure and returns to
  2654.                             the statement immediately following the one that
  2655.                             called the procedure. You can also use one or
  2656.                             more optional EXIT{SUB| FUNCTION} statements
  2657.                             within the body of a procedure definition to exit
  2658.                             from the procedure.
  2659.    ──────────────────────────────────────────────────────────────────────────
  2660.  
  2661.  
  2662.    All valid BASIC expressions and statements are allowed within a procedure
  2663.    definition except the following:
  2664.  
  2665.    ■ DEF FN...END DEF, FUNCTION...END FUNCTION, or SUB...END SUB
  2666.  
  2667.      It is not possible to nest procedure definitions or to define a DEF FN
  2668.      function inside a procedure. However, a procedure can call another
  2669.      procedure or a DEF FN function.
  2670.  
  2671.    ■ COMMON
  2672.  
  2673.    ■ DECLARE
  2674.  
  2675.    ■ DIM SHARED
  2676.  
  2677.    ■ OPTION BASE
  2678.  
  2679.    ■ TYPE...END TYPE
  2680.  
  2681.    Example
  2682.  
  2683.    The following example is a FUNCTION procedure named IntegerPower :
  2684.  
  2685.    FUNCTION IntegerPower& (X&, Y&) STATIC
  2686.       PowerVal& = 1
  2687.       FOR I& = 1 TO Y&
  2688.          PowerVal& = PowerVal& * X&
  2689.       NEXT I&
  2690.       IntegerPower& = PowerVal&
  2691.    END FUNCTION
  2692.  
  2693.  
  2694.  2.4  Calling Procedures
  2695.  
  2696.    Calling a FUNCTION procedure is different from calling a SUB procedure, as
  2697.    shown in the next two sections.
  2698.  
  2699.  2.4.1  Calling a FUNCTION Procedure
  2700.  
  2701.    You call a FUNCTION procedure the same way you use an intrinsic BASIC
  2702.    function such as ABS, that is, by using its name in an expression, as
  2703.    shown here:
  2704.  
  2705.    ' Any of the following statements
  2706.    ' would call a FUNCTION named "ToDec" :
  2707.    PRINT 10 * ToDec
  2708.    X = ToDec
  2709.    IF ToDec = 10 THEN PRINT "Out of range."
  2710.  
  2711.    A FUNCTION can return values by changing variables passed to it as
  2712.    arguments. (See Section 2.5.5, "Passing Arguments by Reference," for an
  2713.    explanation of how this is done.) Additionally, a FUNCTION returns a
  2714.    single value in its name, so the name of a FUNCTION must agree with the
  2715.    type it returns. For example, if a FUNCTION returns a string value, either
  2716.    its name must have the dollar sign ($) type-declaration character appended
  2717.    to it or it must be declared as having the string type in a preceding
  2718.    DEFSTR statement.
  2719.  
  2720.    Example
  2721.  
  2722.    The following program shows a FUNCTION that returns a string value. Note
  2723.    that the type-declaration suffix for strings ($) is part of the procedure
  2724.    name.
  2725.  
  2726.    Banner$ = GetInput$       ' Call the FUNCTION and assign the
  2727.                              ' return value to a string variable.
  2728.    PRINT Banner$             ' Print the string.
  2729.    END
  2730.  
  2731.    ' ======================= GETINPUT$ ========================
  2732.    '    The $ type-declaration character at the end of this
  2733.    '    FUNCTION name means that it returns a string value.
  2734.    ' ==========================================================
  2735.  
  2736.    FUNCTION GetInput$ STATIC
  2737.  
  2738.       ' Return a string of 10 characters read from the
  2739.       ' keyboard, echoing each character as it is typed:
  2740.       FOR I% = 1 TO 10
  2741.          Char$ = INPUT$(1)     ' Get the character.
  2742.          PRINT Char$;          ' Echo the character on the
  2743.                                ' screen.
  2744.          Temp$ = Temp$ + Char$ ' Add the character to the
  2745.                                ' string.
  2746.       NEXT
  2747.       PRINT
  2748.       GetInput$ = Temp$    ' Assign the string to the FUNCTION.
  2749.    END FUNCTION
  2750.  
  2751.    ──────────────────────────────────────────────────────────────────────────
  2752.    NOTE
  2753.      The program example above is written for use in the QB environment only.
  2754.      It cannot be compiled using the BC command from DOS.
  2755.    ──────────────────────────────────────────────────────────────────────────
  2756.  
  2757.  2.4.2  Calling a SUB Procedure
  2758.  
  2759.    A SUB procedure differs from a FUNCTION procedure in that a SUB cannot be
  2760.    called by using its name within an expression. A call to a SUB is a
  2761.    stand-alone statement, like BASIC's CIRCLE statement. Also, a SUB does not
  2762.    return a value in its name as does a FUNCTION. However, like a FUNCTION, a
  2763.    SUB can modify the values of any variables passed to it. (Section 2.5.5,
  2764.    "Passing Arguments by Reference," explains how this is done.)
  2765.  
  2766.    There are two ways to call a SUB procedure:
  2767.  
  2768.    1. Put its name in a CALL statement:
  2769.  
  2770.       CALL PrintMessage
  2771.  
  2772.    2. Use its name as a statement by itself:
  2773.  
  2774.       PrintMessage
  2775.  
  2776.    If you omit the CALL keyword, don't put parentheses around arguments
  2777.    passed to the SUB:
  2778.  
  2779.    ' Call the ProcessInput subprogram with CALL and pass the
  2780.    ' three arguments First$, Second$, and NumArgs% to it:
  2781.    CALL ProcessInput  (First$, Second$, NumArgs%)
  2782.  
  2783.  
  2784.  
  2785.    ' Call the ProcessInput subprogram without CALL and pass
  2786.    ' it the same arguments (note no parentheses around the
  2787.    ' argument list):
  2788.    ProcessInput  First$, Second$, NumArgs%
  2789.  
  2790.  
  2791.    See Section 2.5 for more information on passing arguments to procedures.
  2792.  
  2793.    If your program calls SUB procedures without using CALL, and if you are
  2794.    not using QuickBASIC to write the program, you must put the name of the
  2795.    SUB in a DECLARE statement before it is called:
  2796.  
  2797.    DECLARE SUB CheckForKey
  2798.    .
  2799.    .
  2800.    .
  2801.    CheckForKey
  2802.  
  2803.    You need to be concerned about this only if you are developing programs
  2804.    outside QuickBASIC, since QuickBASIC automatically inserts DECLARE
  2805.    statements wherever they are needed when it saves a program.
  2806.  
  2807.  
  2808.  2.5  Passing Arguments to Procedures
  2809.  
  2810.    Sections 2.5.1-2.5.4 explain how to tell the difference between
  2811.    parameters and arguments, how to pass arguments to procedures, and how to
  2812.    check arguments to make sure they are of the correct type and quantity.
  2813.  
  2814.  2.5.1  Parameters and Arguments
  2815.  
  2816.    The first step in learning about passing arguments to procedures is
  2817.    understanding the difference between the terms "parameter" and "argument":
  2818.  
  2819.    Parameter                Argument
  2820.    ──────────────────────────────────────────────────────────────────────────
  2821.    A variable name that     A constant, variable, or expression passed to a
  2822.    appears in a SUB,        SUB or FUNCTION when the SUB or FUNCTION is
  2823.    FUNCTION, or DECLARE     called
  2824.    statement
  2825.    ──────────────────────────────────────────────────────────────────────────
  2826.  
  2827.    In a procedure definition, parameters are placeholders for arguments. As
  2828.    shown in Figure 2.1, when a procedure is called, arguments are plugged
  2829.    into the variables in the parameter list, with the first parameter
  2830.    receiving the first argument, the second parameter receiving the second
  2831.    argument, and so on.
  2832.  
  2833.  
  2834.    ┌───────────────────────────────────────────────────────────────────┐
  2835.    │                                                                   │
  2836.    │                                            Arguments              │
  2837.    │                                       ┌────────┴─────────┐        │
  2838.    │ Procedure call───────── CALL TestSub   (A%,  B!,  "text")         │
  2839.    │                         ∙               │     │      │            │
  2840.    │                         ∙               │     │      │            │
  2841.    │                         ∙                                      │
  2842.    │ Procedure definition ── SUB TestSub    (P1%,  P2!,   P3$)  STATIC │
  2843.    │                                       └────────┬─────────┘        │
  2844.    │                                            Parameters             │
  2845.    │                                                                   │
  2846.    └───────────────────────────────────────────────────────────────────┘
  2847.  
  2848.    Figure 2.1  Parameters and Arguments
  2849.  
  2850.    Figure 2.1 also demonstrates another important rule: although the names
  2851.    of variables in an argument list and a parameter list do not have to be
  2852.    the same, the number of parameters and the number of arguments do.
  2853.    Furthermore, the type (string, integer numeric, single-precision numeric,
  2854.    and so on) should be the same for corresponding arguments and parameters.
  2855.    (See Section 2.5.4, "Checking Arguments with the DECLARE Statement," for
  2856.    more information on how to ensure that arguments and parameters agree in
  2857.    number and type.)
  2858.  
  2859.    A parameter list consists of any of the following, all separated by
  2860.    commas:
  2861.  
  2862.    ■ Valid variable names, except for fixed-length strings
  2863.  
  2864.      For example, x$ and x AS STRING are both legal in a parameter list,
  2865.      since they refer to variable-length strings. However, x AS STRING * 10
  2866.      refers to a fixed-length string 10 characters long and cannot appear in
  2867.      a parameter list. (Fixed-length strings are perfectly all right as
  2868.      arguments passed to procedures. See Chapter 4, "String Processing," for
  2869.      more information on fixed-length and variable-length strings.)
  2870.  
  2871.    ■ Array names followed by left and right parentheses
  2872.  
  2873.    An argument list consists of any of the following, all separated by
  2874.    commas:
  2875.  
  2876.    ■ Constants
  2877.  
  2878.    ■ Expressions
  2879.  
  2880.    ■ Valid variable names
  2881.  
  2882.    ■ Array names followed by left and right parentheses
  2883.  
  2884.    Examples
  2885.  
  2886.    The following example shows the first line of a subprogram definition with
  2887.    a parameter list:
  2888.  
  2889.    SUB TestSub (A%, Array(), RecVar AS RecType, Cs$)
  2890.  
  2891.    The first parameter, A%, is an integer; the second parameter, Array(), is
  2892.    a single-precision array, since untyped numeric variables are single
  2893.    precision by default; the third parameter, RecVar, is a record of type
  2894.    RecType; and the fourth parameter, Cs$, is a string.
  2895.  
  2896.    The CALL TestSub line in the next example calls the TestSub subprogram and
  2897.    passes it four arguments of the appropriate type:
  2898.  
  2899.    TYPE RecType
  2900.       Rank AS STRING * 12
  2901.       SerialNum AS LONG
  2902.    END TYPE
  2903.  
  2904.    DIM RecVar AS RecType
  2905.  
  2906.    CALL TestSub (X%, A(), RecVar, "Daphne")
  2907.  
  2908.  2.5.2  Passing Constants and Expressions
  2909.  
  2910.    Constants──whether string or numeric──can appear in the list of arguments
  2911.    passed to a procedure. Naturally, a string constant must be passed to a
  2912.    string parameter and a numeric constant to a numeric parameter, as shown
  2913.    in the next example:
  2914.  
  2915.    CONST SCREENWIDTH = 80
  2916.    CALL PrintBanner (SCREENWIDTH, "Monthly Status Report")
  2917.    .
  2918.    .
  2919.    .
  2920.    SUB PrintBanner (SW%, Title$)
  2921.       .
  2922.       .
  2923.       .
  2924.    END SUB
  2925.  
  2926.    If a numeric constant in an argument list does not have the same type as
  2927.    the corresponding parameter in the SUB or FUNCTION statement, then the
  2928.    constant is coerced to the type of the parameter, as you can see by the
  2929.    output from the next example:
  2930.  
  2931.    CALL test(4.6, 4.1)
  2932.    END
  2933.  
  2934.    SUB test (x%, y%)
  2935.       PRINT x%, y%
  2936.    END SUB
  2937.  
  2938.    Output
  2939.  
  2940.     5             4
  2941.  
  2942.    Expressions resulting from operations on variables and constants can also
  2943.    be passed to a procedure. As is the case with constants, numeric
  2944.    expressions that disagree in type with their parameters are coerced into
  2945.    agreement, as shown here:
  2946.  
  2947.    Checker A! + 25!, NOT BooleanVal%
  2948.  
  2949.    ' In the next call, putting parentheses around the
  2950.    ' long-integer variable Bval& makes it an expression.
  2951.    ' The (Bval&) expression is coerced to a short integer
  2952.    ' in the Checker SUB:
  2953.    Checker A! / 3.1, (Bval&)
  2954.    .
  2955.    .
  2956.    .
  2957.    END
  2958.  
  2959.    SUB Checker (Param1!, Param2%)
  2960.       .
  2961.       .
  2962.       .
  2963.    END SUB
  2964.  
  2965.  2.5.3  Passing Variables
  2966.  
  2967.    This section discusses how to pass simple variables, complete arrays,
  2968.    elements of arrays, records, and elements of records to procedures.
  2969.  
  2970.    2.5.3.1  Passing Simple Variables
  2971.  
  2972.    In both argument and parameter lists, you can declare the type for a
  2973.    simple variable in one of the following three ways:
  2974.  
  2975.    1. Append one of the following type-declaration suffixes to the variable
  2976.       name: %, &, !, #, or $.
  2977.  
  2978.    2. Declare the variable in a declare variablename AS type clause, where
  2979.       the placeholder declare can be either DIM, COMMON, REDIM, SHARED, or
  2980.       STATIC, and type can be either INTEGER, LONG, SINGLE, DOUBLE, STRING,
  2981.       or STRING * n. For example:
  2982.  
  2983.       DIM A AS LONG
  2984.  
  2985.    3. Use a DEFtype statement to set the default type.
  2986.  
  2987.    No matter which method you choose, corresponding variables must have the
  2988.    same type in both the argument and parameter lists, as shown in the
  2989.    following example.
  2990.  
  2991.    Example
  2992.  
  2993.    In this example, two arguments are passed to the FUNCTION procedure. The
  2994.    first is an integer giving the length of the string returned by the
  2995.    FUNCTION, while the second is a character that is repeated to make the
  2996.    string.
  2997.  
  2998.    FUNCTION CharString$(A AS INTEGER, B$) STATIC
  2999.       CharString$ = STRING$(A%, B$)
  3000.    END FUNCTION
  3001.  
  3002.    DIM X AS INTEGER
  3003.    INPUT "Enter a number (1 to 80): ", X
  3004.    INPUT "Enter a character: ", Y$
  3005.  
  3006.    ' Print a string consisting of the Y$ character, repeated
  3007.    ' X number of times:
  3008.    PRINT CharString$(X, Y$)
  3009.    END
  3010.  
  3011.    Output
  3012.  
  3013.    Enter a number (1 to 80): 21
  3014.    Enter a character: #
  3015.    #####################
  3016.  
  3017.    2.5.3.2  Passing an Entire Array
  3018.  
  3019.    To pass all the elements of an array to a procedure, put the array's name,
  3020.    followed by left and right parentheses, in both the argument and parameter
  3021.    lists.
  3022.  
  3023.    Example
  3024.  
  3025.    This example shows how to pass all the elements of an array to a
  3026.    procedure:
  3027.  
  3028.    DIM Values(1 TO 5) AS INTEGER
  3029.  
  3030.    ' Note empty parentheses after array name when calling
  3031.    ' procedure and passing array:
  3032.    CALL ChangeArray (1, 5, Values())
  3033.    CALL PrintArray (1, 5, Values())
  3034.    END
  3035.  
  3036.    ' Note empty parentheses after P parameter:
  3037.  
  3038.    SUB ChangeArray (Min%, Max%, P() AS INTEGER) STATIC
  3039.       FOR I% = Min% TO Max%
  3040.          P(I%) = I% ^ 3
  3041.       NEXT I%
  3042.    END SUB
  3043.  
  3044.    SUB PrintArray (Min%, Max%, P() AS INTEGER) STATIC
  3045.       FOR I% = Min% TO Max%
  3046.          PRINT P(I%)
  3047.       NEXT I%
  3048.       PRINT
  3049.    END SUB
  3050.  
  3051.    2.5.3.3  Passing Individual Array Elements
  3052.  
  3053.    If a procedure does not require an entire array, you can pass individual
  3054.    elements of the array instead. To pass an element of an array, use the
  3055.    array name followed by the appropriate subscripts inside parentheses.
  3056.  
  3057.    Example
  3058.  
  3059.    The SqrVal Array(4,2) statement in the following example passes the
  3060.    element in row 4, column 2 of the array to the SqrVal subprogram (note how
  3061.    the subprogram actually changes the value of this array element):
  3062.  
  3063.    DIM Array(1 TO 5,1 TO 3)
  3064.  
  3065.    Array(4,2) = -36
  3066.    PRINT Array(4,2)
  3067.    SqrVal Array(4,2)
  3068.    PRINT Array(4,2)     ' The call to SqrVal has changed
  3069.                         ' the value of Array(4,2).
  3070.    END
  3071.    SUB SqrVal(A) STATIC
  3072.       A = SQR(ABS(A))
  3073.    END SUB
  3074.  
  3075.    Output
  3076.  
  3077.    -36
  3078.     6
  3079.  
  3080.    2.5.3.4  Using Array-Bound Functions
  3081.  
  3082.    The LBOUND and UBOUND functions are a useful way to determine the size of
  3083.    an array passed to a procedure. The LBOUND function finds the smallest
  3084.    index value of an array subscript, while the UBOUND function finds the
  3085.    largest one. These functions save you the trouble of having to pass the
  3086.    upper and lower bounds of each array dimension to a procedure.
  3087.  
  3088.    Example
  3089.  
  3090.    The subprogram in the following example uses the LBOUND function to
  3091.    initialize the variables Row and Col to the lowest subscript values in
  3092.    each dimension of A. It also uses the UBOUND function to limit the number
  3093.    of times the FOR loop executes to the number of elements in the array.
  3094.  
  3095.    SUB PrintOut(A(2)) STATIC
  3096.       FOR Row = LBOUND(A,1) TO UBOUND(A,1)
  3097.          FOR Col = LBOUND(A,2) TO UBOUND(A,2)
  3098.             PRINT A(Row,Col)
  3099.          NEXT Col
  3100.       NEXT Row
  3101.    END SUB
  3102.  
  3103.    2.5.3.5  Passing an Entire Record
  3104.  
  3105.    To pass a complete record (a variable declared as having a user-defined
  3106.    type) to a procedure, complete the following steps:
  3107.  
  3108.    1. Define the type (StockItem in this example):
  3109.  
  3110.       TYPE StockItem
  3111.          PartNumber  AS STRING *  6
  3112.          Description AS STRING * 20
  3113.          UnitPrice   AS SINGLE
  3114.          Quantity    AS INTEGER
  3115.       END TYPE
  3116.  
  3117.    2. Declare a variable (StockRecord) with that type:
  3118.  
  3119.       DIM StockRecord AS StockItem
  3120.  
  3121.    3. Call a procedure (FindRecord) and pass it the variable you have
  3122.       declared:
  3123.  
  3124.       CALL FindRecord(StockRecord)
  3125.  
  3126.    4. In the procedure definition, give the parameter the same type as the
  3127.       variable:
  3128.  
  3129.       SUB FindRecord (RecordVar AS StockItem) STATIC
  3130.          .
  3131.          .
  3132.          .
  3133.       END SUB
  3134.  
  3135.    2.5.3.6  Passing Individual Elements of a Record
  3136.  
  3137.    To pass an individual element in a record to a procedure, put the name of
  3138.    the element (recordname.elementname) in the argument list. Be sure, as
  3139.    always, that the corresponding parameter in the procedure definition
  3140.    agrees with the type of that element.
  3141.  
  3142.    Example
  3143.  
  3144.    The following example shows how to pass the two elements in the record
  3145.    variable StockItem to the PrintTag SUB procedure. Note how each parameter
  3146.    in the SUB procedure agrees with the type of the individual record
  3147.    elements.
  3148.  
  3149.    TYPE StockType
  3150.       PartNumber AS STRING * 6
  3151.       Descrip AS STRING * 20
  3152.       UnitPrice AS SINGLE
  3153.       Quantity AS INTEGER
  3154.    END TYPE
  3155.  
  3156.    DIM StockItem AS StockType
  3157.  
  3158.    CALL PrintTag (StockItem.Descrip, StockItem.UnitPrice)
  3159.    .
  3160.    .
  3161.    .
  3162.    END
  3163.  
  3164.    SUB PrintTag (Desc$, Price AS SINGLE)
  3165.       .
  3166.       .
  3167.       .
  3168.    END SUB
  3169.  
  3170.  2.5.4  Checking Arguments with the DECLARE Statement
  3171.  
  3172.    If you are using QuickBASIC to write your program, you will notice that
  3173.    QuickBASIC automatically inserts a DECLARE statement for each procedure
  3174.    whenever you save the program. Each DECLARE statement consists of the word
  3175.    DECLARE, followed by the words SUB or FUNCTION, the name of the procedure,
  3176.    and a set of parentheses. If the procedure has no parameters, then the
  3177.    parentheses are empty. If the procedure has parameters, then the
  3178.    parentheses enclose a parameterlist that specifies the number and type of
  3179.    the arguments to be passed to the procedure. This parameterlist has the
  3180.    same format as the list in the definition line of the SUB or FUNCTION.
  3181.  
  3182.    The purpose of the parameterlist in a DECLARE statement is to turn on
  3183.    "type checking" of arguments passed to the procedure. That is, every time
  3184.    the procedure is called with variable arguments, those variables are
  3185.    checked to be sure they agree with the number and type of the parameters
  3186.    in the DECLARE statement.
  3187.  
  3188.    QuickBASIC puts all procedure definitions at the end of a module when it
  3189.    saves a program. Therefore, if there were no DECLARE statements, when you
  3190.    tried to compile this program with the BC command you would run into a
  3191.    problem known as "forward reference" (calling a procedure before it is
  3192.    defined). By generating a prototype of the procedure definition, DECLARE
  3193.    statements allow your program to call procedures that are defined later in
  3194.    a module, or in another module altogether.
  3195.  
  3196.    Examples
  3197.  
  3198.    The next example shows an empty parameter list in the DECLARE statement,
  3199.    since no arguments are passed to GetInput$:
  3200.  
  3201.    DECLARE FUNCTION GetInput$ ()
  3202.    X$ = GetInput$
  3203.  
  3204.    FUNCTION GetInput$ STATIC
  3205.       GetInput$ = INPUT$(10)
  3206.    END FUNCTION
  3207.  
  3208.    The next example shows a parameter list in the DECLARE statement, since an
  3209.    integer argument is passed to this version of GetInput$ :
  3210.  
  3211.    DECLARE FUNCTION GetInput$ (X%)
  3212.    X$ = GetInput$ (5)
  3213.  
  3214.    FUNCTION GetInput$ (X%) STATIC
  3215.       GetInput$ = INPUT$(X%)
  3216.    END FUNCTION
  3217.  
  3218.    2.5.4.1  When QuickBASIC Does Not Generate a DECLARE Statement
  3219.  
  3220.    In certain instances, QuickBASIC does not generate DECLARE statements in
  3221.    the module that calls a procedure.
  3222.  
  3223.    QuickBASIC cannot generate a DECLARE statement in one module for a
  3224.    FUNCTION procedure defined in another module if the module is not loaded.
  3225.    In such a case, you must type the DECLARE statement yourself at the
  3226.    beginning of the module where the FUNCTION is called; otherwise,
  3227.    QuickBASIC considers the call to the FUNCTION to be a variable name.
  3228.  
  3229.    QuickBASIC does not generate a DECLARE statement for a SUB procedure in
  3230.    another module, whether that module is loaded or not. The DECLARE
  3231.    statement is not needed unless you want to call the SUB procedure without
  3232.    using the keyword CALL, however.
  3233.  
  3234.    QuickBASIC also cannot generate a DECLARE statement for any procedure in a
  3235.    Quick library. You must add one to the program yourself.
  3236.  
  3237.    2.5.4.2  Developing Programs outside the QuickBASIC Environment
  3238.  
  3239.    If you are writing your programs with your own text editor and then
  3240.    compiling them outside the QuickBASIC environment with the BC and LINK
  3241.    commands, be sure to put DECLARE statements in the following three
  3242.    locations:
  3243.  
  3244.    1. At the beginning of any module that calls a FUNCTION procedure before
  3245.       it is defined:
  3246.  
  3247.       DECLARE FUNCTION Hypot (X!, Y!)
  3248.  
  3249.       INPUT X, Y
  3250.       PRINT Hypot(X, Y)
  3251.       END
  3252.  
  3253.       FUNCTION Hypot (A, B) STATIC
  3254.          Hypot = SQR(A ^ 2 + B ^ 2)
  3255.       END FUNCTION
  3256.  
  3257.    2. At the beginning of any module that calls a SUB procedure before it is
  3258.       defined and does not use CALL when calling the SUB:
  3259.  
  3260.       DECLARE SUB PrintString (X, Y)
  3261.       INPUT X, Y
  3262.  
  3263.       PrintString X, Y     ' Note: no parentheses around
  3264.                            ' arguments
  3265.       END
  3266.  
  3267.       SUB PrintString (A,B) STATIC
  3268.  
  3269.          ' Convert the numbers to strings, remove any leading
  3270.          ' blanks from the second number, and print:
  3271.          PRINT STR$(A) + LTRIM$(STR$(B))
  3272.       END SUB
  3273.  
  3274.       When you call a SUB procedure with CALL, you don't have to declare the
  3275.       SUB first:
  3276.  
  3277.       A$ = "466"
  3278.       B$ = "123"
  3279.       CALL PrintString(A$, B$)
  3280.       END
  3281.  
  3282.       SUB PrintString (X$, Y$) STATIC
  3283.          PRINT VAL(X$) + VAL(Y$)
  3284.       END SUB
  3285.  
  3286.    3. At the beginning of any module that calls a SUB or FUNCTION procedure
  3287.       defined in another module (an "external procedure")
  3288.  
  3289.    If your procedure has no parameters, remember to put empty parentheses
  3290.    after the name of the procedure in the DECLARE statement, as in the next
  3291.    example:
  3292.  
  3293.    DECLARE FUNCTION GetHour$ ()
  3294.    PRINT GetHour$
  3295.    END
  3296.  
  3297.    FUNCTION GetHour$ STATIC
  3298.       GetHour$ = LEFT$(TIME$,2)
  3299.    END FUNCTION
  3300.  
  3301.    Remember, a DECLARE statement can appear only at the module level, not the
  3302.    procedure level. A DECLARE statement affects the entire module in which it
  3303.    appears.
  3304.  
  3305.    2.5.4.3  Using Include Files for Declarations
  3306.  
  3307.    If you have created a separate procedure-definition module that defines
  3308.    one or more SUB or FUNCTION procedures, it is a good idea to make an
  3309.    include file to go along with this module. This include file should
  3310.    contain the following:
  3311.  
  3312.    ■ DECLARE statements for all the module's procedures.
  3313.  
  3314.    ■ TYPE...END TYPE record definitions for any record parameters in this
  3315.      module's SUB or FUNCTION procedures.
  3316.  
  3317.    ■ COMMON statements listing variables shared between this module and other
  3318.      modules in the program. (See Section 2.6.3, "Sharing Variables with
  3319.      Other Modules," for more information on using COMMON for this purpose.)
  3320.  
  3321.    Every time you use the definition module in one of your programs, insert a
  3322.    $INCLUDE metacommand at the beginning of any module that invokes
  3323.    procedures in the definition module. When your program is compiled, the
  3324.    actual contents of the include file are substituted for the $INCLUDE
  3325.    metacommand.
  3326.  
  3327.    A simple rule of thumb is to make an include file for every module and
  3328.    then use the module and the include file together as outlined above. The
  3329.    following list itemizes some of the benefits of this technique:
  3330.  
  3331.    ■ A module containing procedure definitions remains truly modular──that
  3332.      is, you don't have to copy all the DECLARE statements for its procedures
  3333.      every time you call them from another module; instead, you can just
  3334.      substitute one $INCLUDE metacommand.
  3335.  
  3336.    ■ In QuickBASIC, using an include file for procedure declarations
  3337.      suppresses automatic generation of DECLARE statements when you save a
  3338.      program.
  3339.  
  3340.    ■ Using an include file for declarations avoids problems with getting one
  3341.      module to recognize a FUNCTION in another module. (See Section 2.5.4.1,
  3342.      "When QuickBASIC Does Not Generate a DECLARE Statement," for more
  3343.      information.)
  3344.  
  3345.    You can take advantage of QuickBASIC's facility for generating DECLARE
  3346.    statements when creating your include file. The following steps show you
  3347.    how to do this:
  3348.  
  3349.    1. Create your module.
  3350.  
  3351.    2. Within that module, call any SUB or FUNCTION procedures you have
  3352.       defined.
  3353.  
  3354.    3. Save the module to get automatic DECLARE statements for all the
  3355.       procedures.
  3356.  
  3357.    4. Reedit the module, removing the procedure calls and moving the DECLARE
  3358.       statements to a separate include file.
  3359.  
  3360.    See Appendix F, "Metacommands," for more information on the syntax and
  3361.    usage of the $INCLUDE metacommand.
  3362.  
  3363.    Example
  3364.  
  3365.    The following fragments illustrate how to use a definition module and an
  3366.    include file together:
  3367.  
  3368.    ' =========================================================
  3369.    '                        MODDEF.BAS
  3370.    ' This module contains definitions for the PROMPTER and
  3371.    ' MAX! procedures.
  3372.    ' =========================================================
  3373.  
  3374.    FUNCTION Max! (X!, Y!) STATIC
  3375.       IF X! > Y! THEN Max! = X! ELSE Max! = Y!
  3376.    END FUNCTION
  3377.  
  3378.    SUB Prompter (Row%, Column%, RecVar AS RecType) STATIC
  3379.       LOCATE Row%, Column%
  3380.       INPUT "Description: ", RecVar.Description
  3381.       INPUT "Quantity:    ", RecVar.Quantity
  3382.    END SUB
  3383.  
  3384.    ' =========================================================
  3385.    '                        MODDEF.BI
  3386.    '  This is an include file that contains DECLARE statements
  3387.    '  for the PROMPTER and MAX! procedures (as well as a TYPE
  3388.    '  statement defining the RecType user type). Use this file
  3389.    '  whenever you use the MODDEF.BAS module.
  3390.    ' =========================================================
  3391.  
  3392.    TYPE RecType
  3393.       Description AS STRING * 15
  3394.       Quantity AS INTEGER
  3395.    END TYPE
  3396.  
  3397.    DECLARE FUNCTION Max! (X!, Y!)
  3398.    DECLARE SUB Prompter (Row%, Column%, RecVar AS RecType)
  3399.  
  3400.    ' ============================================================
  3401.    '                         SAMPLE.BAS
  3402.    '   This module is linked with the MODDEF.BAS module, and
  3403.    '   calls the PROMPTER and MAX! procedures in MODDEF.BAS.
  3404.    ' ============================================================
  3405.  
  3406.    ' The next line makes the contents of the MODDEF.BI include
  3407.    ' file part of this module as well:
  3408.    ' $INCLUDE: 'MODDEF.BI'
  3409.    .
  3410.    .
  3411.    .
  3412.    INPUT A, B
  3413.    PRINT Max!(A, B)        ' Call the Max! FUNCTION in MODDEF.BAS
  3414.    .
  3415.    .
  3416.    .
  3417.    Prompter 5, 5, RecVar   ' Call the Prompter SUB in MODDEF.BAS
  3418.    .
  3419.    .
  3420.    .
  3421.  
  3422.    ──────────────────────────────────────────────────────────────────────────
  3423.    IMPORTANT
  3424.      While it is good programming practice to put procedure declarations in
  3425.      an include file, do not put the procedures themselves (SUB...END SUB or
  3426.      FUNCTION...END FUNCTION blocks) in an include file. Procedure
  3427.      definitions are not allowed inside include files in QuickBASIC Version
  3428.      4.5. If you have used include files to define SUB procedures in programs
  3429.      written with QuickBASIC Versions 2.0 or 3.0, either put these
  3430.      definitions in a separate module or incorporate them into the module
  3431.      where they are called.
  3432.    ──────────────────────────────────────────────────────────────────────────
  3433.  
  3434.    2.5.4.4  Declaring Procedures in Quick Libraries
  3435.  
  3436.    A convenient programming practice is to put all the declarations for
  3437.    procedures in a Quick library into one include file. With the $INCLUDE
  3438.    metacommand you can then incorporate this include file into programs using
  3439.    the library. This saves you the trouble of copying all the relevant
  3440.    DECLARE statements every time you use the library.
  3441.  
  3442.  2.5.5  Passing Arguments by Reference
  3443.  
  3444.    By default, variables──whether simple scalar variables, arrays and array
  3445.    elements, or records──are passed "by reference" to FUNCTION and SUB
  3446.    procedures. Here is what is meant by passing variables by reference:
  3447.  
  3448.    ■ Each program variable has an address, or a location in memory where its
  3449.      value is stored.
  3450.  
  3451.    ■ Calling a procedure and passing variables to it by reference calls the
  3452.      procedure and passes it the address of each variable. Thus, the address
  3453.      of the variable and the address of its corresponding parameter in the
  3454.      procedure are one and the same.
  3455.  
  3456.    ■ Therefore, if the procedure modifies the value of the parameter, it also
  3457.      modifies the value of the variable that is passed.
  3458.  
  3459.    If you do not want a procedure to change the value of a variable, pass the
  3460.    procedure the value contained in the variable, not the address. This way,
  3461.    changes are made only to a copy of the variable, not the variable itself.
  3462.    See the next section for a discussion of this alternative way of passing
  3463.    variables.
  3464.  
  3465.    Example
  3466.  
  3467.    In the following program, changes made to the parameter A$ in the Replace
  3468.    procedure also change the argument Test$:
  3469.  
  3470.    Test$ = "a string with all lowercase letters."
  3471.    PRINT "Before subprogram call: "; Test$
  3472.    CALL Replace (Test$, "a")
  3473.    PRINT "After subprogram call: "; Test$
  3474.    END
  3475.  
  3476.    SUB Replace (A$, B$) STATIC
  3477.       Start = 1
  3478.       DO
  3479.  
  3480.          ' Look for B$ in A$, starting at the character
  3481.          ' with position "Start" in A$:
  3482.          Found = INSTR(Start, A$, B$)
  3483.          ' Make every occurrence of B$ in A$
  3484.          ' an uppercase letter:
  3485.          IF Found > 0 THEN
  3486.             MID$(A$,Found) = UCASE$(B$)
  3487.             Start = Start + 1
  3488.          END IF
  3489.       LOOP WHILE Found > 0
  3490.    END SUB
  3491.  
  3492.    Output
  3493.  
  3494.    Before subprogram call: a string with all lowercase letters.
  3495.    After subprogram call: A string with All lowercAse letters.
  3496.  
  3497.  2.5.6  Passing Arguments by Value
  3498.  
  3499.    Passing an argument "by value" means the value of the argument is passed,
  3500.    rather than its address. In BASIC procedures, passing a variable by value
  3501.    is simulated by copying the variable into a temporary location, then
  3502.    passing the address of this temporary location. Since the procedure does
  3503.    not have access to the address of the original variable, it cannot change
  3504.    the original variable; it makes all changes to the copy instead.
  3505.  
  3506.    You can pass expressions as arguments to procedures, as in the following:
  3507.  
  3508.    ' A + B is an expression; the values of A and B
  3509.    ' are not affected by this procedure call:
  3510.    CALL Mult(A + B, B)
  3511.  
  3512.    Expressions are always passed by value (see Section 2.5.2, "Passing
  3513.    Constants and Expressions," for more information).
  3514.  
  3515.    Example
  3516.  
  3517.    One way to pass a variable by value is to enclose it in parentheses, thus
  3518.    making it an expression. As you can see from the output that follows,
  3519.    changes to the SUB procedure's local variable Y are passed back to the
  3520.    module-level code as changes to the variable B. However, changes to X in
  3521.    the procedure do not affect the value of A, since A is passed by value.
  3522.  
  3523.    A = 1
  3524.    B = 1
  3525.    PRINT "Before subprogram call, A ="; A; ", B ="; B
  3526.  
  3527.    ' A is passed by value, and B is passed by reference:
  3528.    CALL Mult((A), B)
  3529.    PRINT "After subprogram call, A ="; A; ", B ="; B
  3530.    END
  3531.  
  3532.    SUB Mult (X, Y) STATIC
  3533.       X = 2 * X
  3534.       Y = 3 * Y
  3535.       PRINT "In subprogram, X ="; X; ", Y ="; Y
  3536.    END SUB
  3537.  
  3538.    Output
  3539.  
  3540.    Before subprogram call, A = 1 , B = 1
  3541.    In subprogram, X = 2 , Y = 3
  3542.    After subprogram call, A = 1 , B = 3
  3543.  
  3544.  
  3545.  2.6  Sharing Variables with SHARED
  3546.  
  3547.    In addition to passing variables through argument and parameter lists,
  3548.    procedures can also share variables with other procedures and with code at
  3549.    the module level (that is, code within a module but outside of any
  3550.    procedure) in one of the two ways listed below:
  3551.  
  3552.    1. Variables listed in a SHARED statement within a procedure are shared
  3553.       only between that procedure and the module-level code. Use this method
  3554.       when different procedures in the same module need different
  3555.       combinations of module-level variables.
  3556.  
  3557.    2. Variables listed in a module-level COMMON SHARED, DIM SHARED, or REDIM
  3558.       SHARED statement are shared between the module-level code and all
  3559.       procedures within that module. This method is most useful when all
  3560.       procedures in a module use a common set of variables.
  3561.  
  3562.    You can also use the COMMON or COMMON SHARED statement to share variables
  3563.    among two or more modules. Sections 2.6.1-2.6.3 discuss these three ways
  3564.    to share variables.
  3565.  
  3566.  2.6.1  Sharing Variables with Specific Procedures in a Module
  3567.  
  3568.    If different procedures within a module need to share different variables
  3569.    with the module-level code, use the SHARED statement within each
  3570.    procedure.
  3571.  
  3572.    Arrays in SHARED statements consist of the array name followed by a set of
  3573.    empty parentheses ( ):
  3574.  
  3575.    SUB JustAnotherSub STATIC
  3576.       SHARED ArrayName ()
  3577.       .
  3578.       .
  3579.       .
  3580.  
  3581.    If you give a variable its type in an AS type clause, then the variable
  3582.    must also be typed with the AS type clause in a SHARED statement:
  3583.  
  3584.    DIM Buffer AS STRING * 10
  3585.    .
  3586.    .
  3587.    .
  3588.    END
  3589.  
  3590.    SUB ReadRecords STATIC
  3591.       SHARED Buffer AS STRING * 10
  3592.       .
  3593.       .
  3594.       .
  3595.    END SUB
  3596.  
  3597.    Example
  3598.  
  3599.    In the next example, the SHARED statements in the GetRecords and
  3600.    InventoryTotal procedures show the format of a shared variable list:
  3601.  
  3602.    ' =========================================================
  3603.    '                   MODULE-LEVEL CODE
  3604.    ' =========================================================
  3605.    TYPE RecType
  3606.       Price AS SINGLE
  3607.       Desc AS STRING * 35
  3608.    END TYPE
  3609.  
  3610.    DIM RecVar(1 TO 100) AS RecType   ' Array of records
  3611.  
  3612.    INPUT "File name: ", FileSpec$
  3613.    CALL GetRecords
  3614.    PRINT InventoryTotal
  3615.    END
  3616.  
  3617.    ' =========================================================
  3618.    '                   PROCEDURE-LEVEL CODE
  3619.    ' =========================================================
  3620.    SUB GetRecords STATIC
  3621.  
  3622.    ' Both FileSpec$ and the RecVar array of records
  3623.    ' are shared with the module-level code above:
  3624.       SHARED FileSpec$, RecVar() AS RecType
  3625.       OPEN FileSpec$ FOR RANDOM AS #1
  3626.       .
  3627.       .
  3628.       .
  3629.    END SUB
  3630.  
  3631.    FUNCTION InventoryTotal STATIC
  3632.  
  3633.    ' Only the RecVar array is shared with the module-level
  3634.    ' code:
  3635.       SHARED RecVar() AS RecType
  3636.       .
  3637.       .
  3638.       .
  3639.    END FUNCTION
  3640.  
  3641.  2.6.2  Sharing Variables with All Procedures in a Module
  3642.  
  3643.    If variables are declared at the module level with the SHARED attribute in
  3644.    a COMMON, DIM, or REDIM statement (for example, by using a statement of
  3645.    the form COMMON SHARED variablelist), then all procedures within that
  3646.    module have access to those variables; in other words, the SHARED
  3647.    attribute makes variables global throughout a module.
  3648.  
  3649.    The SHARED attribute is convenient when you need to share large numbers of
  3650.    variables among all procedures in a module.
  3651.  
  3652.    Examples
  3653.  
  3654.    These statements declare variables shared among all procedures in one
  3655.    module:
  3656.  
  3657.    COMMON SHARED A, B, C
  3658.    DIM SHARED Array(1 TO 10, 1 TO 10) AS UserType
  3659.    REDIM SHARED Alpha(N%)
  3660.  
  3661.    In the following example, the module-level code shares the string
  3662.    arrayStrArray and the integer variables Min and Max with the two SUB
  3663.    procedures FillArray and PrintArray :
  3664.  
  3665.    ' =========================================================
  3666.    '                    MODULE-LEVEL CODE
  3667.    ' =========================================================
  3668.    DECLARE SUB FillArray ()
  3669.    DECLARE SUB PrintArray ()
  3670.  
  3671.    ' The following DIM statements share the Min and Max
  3672.    ' integer variables and the StrArray string array
  3673.    ' with any SUB or FUNCTION in this module:
  3674.    DIM SHARED StrArray (33 TO 126) AS STRING * 5
  3675.    DIM SHARED Min AS INTEGER, Max AS INTEGER
  3676.  
  3677.    Min = LBOUND(StrArray)
  3678.    Max = UBOUND(StrArray)
  3679.  
  3680.    FillArray               ' Note the absence of argument lists.
  3681.    PrintArray
  3682.    END
  3683.    ' =========================================================
  3684.    '                    PROCEDURE-LEVEL CODE
  3685.    ' =========================================================
  3686.    SUB FillArray STATIC
  3687.  
  3688.       ' Load each element of the array from 33 to 126
  3689.       ' with a 5-character string, each character of which
  3690.       ' has the ASCII code I%:
  3691.       FOR I% = Min TO Max
  3692.          StrArray(I%) = STRING$(5, I%)
  3693.       NEXT
  3694.  
  3695.    END SUB
  3696.  
  3697.    SUB PrintArray STATIC
  3698.       FOR I% = Min TO Max
  3699.          PRINT StrArray(I%)
  3700.       NEXT
  3701.    END SUB
  3702.  
  3703.    Partial output
  3704.  
  3705.    !!!!!
  3706.    """""
  3707.    #####
  3708.    $$$$$
  3709.    %%%%%
  3710.    &&&&&
  3711.    ""'
  3712.    {{{{{
  3713.    .
  3714.    .
  3715.    .
  3716.  
  3717.    If you are using your own text editor to write your programs and directly
  3718.    compiling those programs outside the QuickBASIC development environment,
  3719.    note that variable declarations with the SHARED attribute must precede the
  3720.    procedure definition. Otherwise, the value of any variable declared with
  3721.    SHARED is not available to the procedure, as shown by the output from the
  3722.    next example. (If you are using QuickBASIC to create your programs, this
  3723.    sequence is not required, since QuickBASIC automatically saves programs in
  3724.    the correct order.)
  3725.  
  3726.    DEFINT A-Z
  3727.  
  3728.    FUNCTION Adder (X, Y) STATIC
  3729.       Adder = X + Y + Z
  3730.    END FUNCTION
  3731.  
  3732.    DIM SHARED Z
  3733.    Z = 2
  3734.    PRINT Adder (1, 3)
  3735.    END
  3736.  
  3737.    Output
  3738.  
  3739.     4
  3740.  
  3741.    The next example shows how you should save the module shown above, with
  3742.    the definition of Adder following the DIM SHARED Z statement:
  3743.  
  3744.    DEFINT A-Z
  3745.  
  3746.    DECLARE FUNCTION Adder (X, Y)
  3747.  
  3748.    ' The variable Z is now shared with Adder:
  3749.    DIM SHARED Z
  3750.    Z = 2
  3751.    PRINT Adder (1, 3)
  3752.    END
  3753.  
  3754.    FUNCTION Adder (X, Y) STATIC
  3755.       Adder = X + Y + Z
  3756.    END FUNCTION
  3757.  
  3758.    Output
  3759.  
  3760.     6
  3761.  
  3762.  2.6.3  Sharing Variables with Other Modules
  3763.  
  3764.    If you want to share variables across modules in your program, list the
  3765.    variables in COMMON or COMMON SHARED statements at the module level in
  3766.    each module.
  3767.  
  3768.    Examples
  3769.  
  3770.    The following example shows how to share variables between modules by
  3771.    using a COMMON statement in the module that calls the SUB procedures, as
  3772.    well as a COMMON SHARED statement in the module that defines the
  3773.    procedures. With COMMON SHARED, all procedures in the second module have
  3774.    access to the common variables:
  3775.  
  3776.    ' =========================================================
  3777.    '                      MAIN MODULE
  3778.    ' =========================================================
  3779.  
  3780.    COMMON A, B
  3781.    A = 2.5
  3782.    B = 1.2
  3783.    CALL Square
  3784.    CALL Cube
  3785.    END
  3786.    ' =========================================================
  3787.    '           Module with Cube and Square Procedures
  3788.    ' =========================================================
  3789.  
  3790.    ' NOTE: The names of the variables (X, Y) do not have to be
  3791.    ' the same as in the other module (A, B). Only the types
  3792.    ' have to be the same.
  3793.  
  3794.    COMMON SHARED X, Y  ' This statement is at the module level.
  3795.                        ' Both X and Y are shared with the CUBE
  3796.                        ' and SQUARE procedures below.
  3797.    SUB Cube STATIC
  3798.       PRINT "A cubed   ="; X ^ 3
  3799.       PRINT "B cubed   ="; Y ^ 3
  3800.    END SUB
  3801.  
  3802.    SUB Square STATIC
  3803.       PRINT "A squared ="; X ^ 2
  3804.       PRINT "B squared ="; Y ^ 2
  3805.    END SUB
  3806.  
  3807.    The following example uses named COMMON blocks at the module levels and
  3808.    SHARED statements within procedures to share different sets of variables
  3809.    with each procedure:
  3810.  
  3811.    ' =========================================================
  3812.    '                        MAIN MODULE
  3813.    ' Prints the volume and density of a filled cylinder given
  3814.    ' the input values
  3815.    ' =========================================================
  3816.  
  3817.    COMMON /VolumeValues/ Height, Radius, Volume
  3818.    COMMON /DensityValues/ Weight, Density
  3819.  
  3820.    INPUT "Height of cylinder in centimeters: ", Height
  3821.    INPUT "Radius of cylinder in centimeters: ", Radius
  3822.    INPUT "Weight of filled cylinder in grams: ", Weight
  3823.  
  3824.    CALL VolumeCalc
  3825.    CALL DensityCalc
  3826.  
  3827.    PRINT "Volume is"; Volume; "cubic centimeters."
  3828.    PRINT "Density is"; Density; "grams/cubic centimeter."
  3829.    END
  3830.  
  3831.    ' =========================================================
  3832.    '     Module with DensityCalc and VolumeCalc Procedures
  3833.    ' =========================================================
  3834.  
  3835.    COMMON /VolumeValues/ H, R, V
  3836.    COMMON /DensityValues/ W, D
  3837.  
  3838.    SUB VolumeCalc STATIC
  3839.  
  3840.       ' Share the Height, Radius, and Volume variables
  3841.       ' with this procedure:
  3842.       SHARED H, R, V
  3843.       CONST PI = 3.141592653589#
  3844.       V = PI * H * (R ^ 2)
  3845.    END SUB
  3846.  
  3847.    SUB DensityCalc STATIC
  3848.  
  3849.       ' Share the Weight, Volume, and Density variables
  3850.       ' with this procedure:
  3851.       SHARED W, V, D
  3852.       D = W / V
  3853.    END SUB
  3854.  
  3855.    Output
  3856.  
  3857.    Height of cylinder in centimeters: 100
  3858.    Radius of cylinder in centimeters: 10
  3859.    Weight of filled cylinder in grams: 10000
  3860.    Volume is 31415.93 cubic centimeters.
  3861.    Density is .3183099 grams/cubic centimeter.
  3862.  
  3863.  2.6.4  The Problem of Variable Aliasing
  3864.  
  3865.    "Variable aliasing" is sometimes a problem in long programs containing
  3866.    many variables and procedures. Variable aliasing is the situation where
  3867.    two or more names refer to the same location in memory. It occurs:
  3868.  
  3869.    ■ When the same variable appears more than once in the list of arguments
  3870.      passed to a procedure.
  3871.  
  3872.    ■ When a variable passed in an argument list is also accessed by the
  3873.      procedure by means of the SHARED statement or the SHARED attribute.
  3874.  
  3875.    To avoid aliasing problems, double-check variables shared with a procedure
  3876.    to make sure they don't also appear in a procedure call's argument list.
  3877.    Also, don't pass the same variable twice, as in the next statement:
  3878.  
  3879.    ' X is passed twice; this will lead to aliasing problems
  3880.    ' in the Test procedure:
  3881.    CALL Test(X, X, Y)
  3882.  
  3883.    Example
  3884.  
  3885.    The following example illustrates how variable aliasing can occur. Here
  3886.    the variable A is shared between the module-level code and the SUB
  3887.    procedure with the DIM SHARED statement. However, A is also passed by
  3888.    reference to the SUB as an argument. Therefore, in the subprogram, A and X
  3889.    both refer to the same location in memory. Thus, when the subprogram
  3890.    modifies X, it is also modifying A, and vice versa.
  3891.  
  3892.    DIM SHARED A
  3893.    A = 4
  3894.    CALL PrintHalf(A)
  3895.    END
  3896.  
  3897.    SUB PrintHalf (X) STATIC
  3898.       PRINT "Half of"; X; "plus half of"; A; "equals";
  3899.       X = X / 2            ' X and A now both equal 2.
  3900.       A = A / 2            ' X and A now both equal 1.
  3901.       PRINT A + X
  3902.    END SUB
  3903.  
  3904.    Output
  3905.  
  3906.    Half of 4 plus half of 4 equals 2
  3907.  
  3908.  
  3909.  2.7  Automatic and STATIC Variables
  3910.  
  3911.    When the STATIC attribute appears on a procedure-definition line, it means
  3912.    that local variables within the procedure are STATIC; that is, their
  3913.    values are preserved between calls to the procedure.
  3914.  
  3915.    Leaving off the STATIC attribute makes local variables within the
  3916.    procedure "automatic" by default; that is, you get a fresh set of local
  3917.    variables each time the procedure is called.
  3918.  
  3919.    You can override the effect of leaving off the STATIC attribute by using
  3920.    the STATIC statement within the procedure, thus making some variables
  3921.    automatic and others STATIC (see Section 2.8 for more information).
  3922.  
  3923.    ──────────────────────────────────────────────────────────────────────────
  3924.    NOTE
  3925.      The SHARED statement also overrides the default for variables in a
  3926.      procedure (local STATIC or local automatic), since any variable
  3927.      appearing in a SHARED statement is known at the module level and thus is
  3928.      not local to the procedure.
  3929.    ──────────────────────────────────────────────────────────────────────────
  3930.  
  3931.  
  3932.  2.8  Preserving Values of Local Variables with the STATIC Statement
  3933.  
  3934.    Sometimes you may want to make some local variables in a procedure STATIC
  3935.    while keeping the rest automatic. List those variables in a STATIC
  3936.    statement within the procedure.
  3937.  
  3938.    Also, putting a variable name in a STATIC statement is a way of making
  3939.    absolutely sure that the variable is local, since a STATIC statement
  3940.    overrides the effect of a module-level SHARED statement.
  3941.  
  3942.    A STATIC statement can appear only within a procedure. An array name in a
  3943.    STATIC statement must be followed by a set of empty parentheses ( ). Also,
  3944.    you must dimension any array that appears in a STATIC statement before
  3945.    using the array, as shown in the next example:
  3946.  
  3947.    SUB SubProg2
  3948.       STATIC Array() AS INTEGER
  3949.       DIM Array(-5 TO 5, 1 TO 25) AS INTEGER
  3950.       .
  3951.       .
  3952.       .
  3953.    END SUB
  3954.  
  3955.    ──────────────────────────────────────────────────────────────────────────
  3956.    NOTE
  3957.      If you give a variable its type in an AS type clause, then the AS type
  3958.      clause must appear along with the variable's name in both the STATIC and
  3959.      DIM statements.
  3960.    ──────────────────────────────────────────────────────────────────────────
  3961.  
  3962.    Example
  3963.  
  3964.    The following example shows how a STATIC statement preserves the value of
  3965.    the string variable Y$ throughout successive calls to TestSub:
  3966.  
  3967.    DECLARE SUB TestSub ()
  3968.    FOR I% = 1 TO 5
  3969.       TestSub              ' Call TestSub five times.
  3970.    NEXT I%
  3971.    END
  3972.  
  3973.    SUB TestSub             ' Note: no STATIC attribute
  3974.  
  3975.      ' Both X$ and Y$ are local variables in TestSub (that is,
  3976.      ' their values are not shared with the module-level code).
  3977.      ' However since X$ is an automatic variable, it is
  3978.      ' reinitialized to a null string every time TestSub is
  3979.      ' called. In contrast, Y$ is STATIC, so it retains the
  3980.      ' value it had from the last call:
  3981.       STATIC Y$
  3982.       X$ = X$ + "*"
  3983.       Y$ = Y$ + "*"
  3984.       PRINT X$, Y$
  3985.    END SUB
  3986.  
  3987.    Output
  3988.  
  3989.    *             *
  3990.    *             **
  3991.    *             ***
  3992.    *             ****
  3993.    *             *****
  3994.  
  3995.  
  3996.  2.9  Recursive Procedures
  3997.  
  3998.    Procedures in BASIC can be recursive. A recursive procedure is one that
  3999.    can call itself or call other procedures that in turn call the first
  4000.    procedure.
  4001.  
  4002.  2.9.1  The Factorial Function
  4003.  
  4004.    A good way to illustrate recursive procedures is to consider the factorial
  4005.    function from mathematics. One way to define n! ("n factorial") is with
  4006.    the following formula:
  4007.  
  4008.    n! = n * (n-1) * (n-2) * ... * 2 * 1
  4009.  
  4010.    For example, 5 factorial is evaluated as follows:
  4011.  
  4012.    5! = 5 * 4 * 3 * 2 * 1 = 120
  4013.  
  4014.    ──────────────────────────────────────────────────────────────────────────
  4015.    NOTE
  4016.      Do not confuse the mathematical factorial symbol (!) used in this
  4017.      discussion with the single-precision type-declaration suffix used by
  4018.      BASIC.
  4019.    ──────────────────────────────────────────────────────────────────────────
  4020.  
  4021.    Factorials lend themselves to a recursive definition as well:
  4022.  
  4023.    n! = n * (n-1)!
  4024.  
  4025.    This leads to the following progression:
  4026.  
  4027.    5! = 5 * 4!
  4028.    4! = 4 * 3!
  4029.    3! = 3 * 2!
  4030.    2! = 2 * 1!
  4031.    1! = 1 * 0!
  4032.  
  4033.    Recursion must always have a terminating condition. With factorials this
  4034.    terminating condition occurs when 0! is evaluated──by definition, 0! is
  4035.    equal to 1.
  4036.  
  4037.    ──────────────────────────────────────────────────────────────────────────
  4038.    NOTE
  4039.      Although a recursive procedure can have STATIC variables by default (as
  4040.      in the next example), it is often preferable to let automatic variables
  4041.      be the default instead. In this way, recursive calls will not overwrite
  4042.      variable values from a preceding call.
  4043.    ──────────────────────────────────────────────────────────────────────────
  4044.  
  4045.    Example
  4046.  
  4047.    The following example uses a recursive FUNCTION procedure to calculate
  4048.    factorials:
  4049.  
  4050.    DECLARE FUNCTION Factorial# (N%)
  4051.    Format$ = "###_! = ###################"
  4052.    DO
  4053.       INPUT "Enter number from 0 - 20 (or -1 to end): ", Num%
  4054.       IF Num% >= 0 AND Num% <= 20 THEN
  4055.          PRINT USING Format$; Num%; Factorial#(Num%)
  4056.       END IF
  4057.    LOOP WHILE Num% >= 0
  4058.    END
  4059.  
  4060.    FUNCTION Factorial# (N%) STATIC
  4061.  
  4062.       IF N% > 0 THEN  ' Call Factorial# again
  4063.                        ' if N is greater than zero.
  4064.          Factorial# = N% * Factorial#(N% - 1)
  4065.  
  4066.       ELSE            ' Reached the end of recursive calls
  4067.                       ' (N% = 0), so "climb back up the ladder."
  4068.          Factorial# = 1
  4069.       END IF
  4070.    END FUNCTION
  4071.  
  4072.  2.9.2  Adjusting the Size of the Stack
  4073.  
  4074.    Recursion can eat up a lot of memory, since each set of automatic
  4075.    variables in a SUB or FUNCTION procedure is saved on the stack. (Saving
  4076.    variables this way allows a procedure to continue with the correct
  4077.    variable values after control returns from a recursive call.)
  4078.  
  4079.    If you have a recursive procedure with many automatic variables, or a
  4080.    deeply nested recursive procedure, you may need to adjust the size of the
  4081.    stack with a CLEAR , , stacksize statement, where stacksize is the number
  4082.    of bytes from the stack you want to reserve. Otherwise, while your program
  4083.    is running you may get the error message Out of stack space.
  4084.  
  4085.    The following steps outline one way to estimate the amount of memory a
  4086.    recursive procedure needs:
  4087.  
  4088.    1. Insert a single quotation mark to temporarily turn the recursive call
  4089.       into a comment line so that the procedure will be invoked only once
  4090.       when the program runs.
  4091.  
  4092.    2. Call the FRE(-2) function (which returns the total unused stack space)
  4093.       just before you call the recursive procedure. Also call the FRE(-2)
  4094.       function right at the end of the recursive procedure. Use PRINT
  4095.       statements to display the returned values.
  4096.  
  4097.    3. Run the program. The difference in values is the amount of stack space
  4098.       (in bytes) used by one call to the procedure.
  4099.  
  4100.    4. Estimate the maximum number of times the procedure is likely to be
  4101.       invoked, then multiply this value by the stack space consumed by one
  4102.       call to the procedure. The result is totalbytes.
  4103.  
  4104.    5. Reserve the amount of stack space calculated in step 4:
  4105.  
  4106.       CLEAR , , totalbytes
  4107.  
  4108.  
  4109.  2.10  Transferring Control to Another Program with CHAIN
  4110.  
  4111.    Unlike procedure calls, which occur within the same program, the CHAIN
  4112.    statement simply starts a new program. When a program chains to another
  4113.    program, the following sequence occurs:
  4114.  
  4115.    1. The first program stops running.
  4116.  
  4117.    2. The second program is loaded into memory.
  4118.  
  4119.    3. The second program starts running.
  4120.  
  4121.    The advantage of using CHAIN is that it enables you to split a program
  4122.    with large memory requirements into several smaller programs.
  4123.  
  4124.    The COMMON statement allows you to pass variables from one program to
  4125.    another program in a chain. A common programming practice is to put these
  4126.    COMMON statements in an include file, and then use the $INCLUDE
  4127.    metacommand at the beginning of each program in the chain.
  4128.  
  4129.    ──────────────────────────────────────────────────────────────────────────
  4130.    NOTE
  4131.      Don't use a COMMON /blockname /variablelist statement (a "named COMMON
  4132.      block") to pass variables to a chained program, since variables listed
  4133.      in named COMMON blocks are not preserved when chaining. Use a blank
  4134.      COMMON block (COMMON variablelist) instead.
  4135.    ──────────────────────────────────────────────────────────────────────────
  4136.  
  4137.    Example
  4138.  
  4139.    This example, which shows a chain connecting three separate programs, uses
  4140.    an include file to declare variables passed in common among the programs:
  4141.  
  4142.    ' ============ CONTENTS OF INCLUDE FILE COMMONS.BI ========
  4143.    DIM Values(10)
  4144.    COMMON Values(), NumValues
  4145.  
  4146.    ' ======================= MAIN.BAS ========================
  4147.  
  4148.    ' Read in the contents of the COMMONS.BI file:
  4149.    ' $INCLUDE: 'COMMONS.BI'
  4150.  
  4151.       ' Input the data:
  4152.       INPUT "Enter number of data values (<=10): ", NumValues
  4153.       FOR I = 1 TO NumValues
  4154.          Prompt$ = "Value ("+LTRIM$(STR$(I))+")? "
  4155.          PRINT Prompt$;
  4156.          INPUT "", Values(I)
  4157.       NEXT I
  4158.  
  4159.       ' Have the user specify the calculation to do:
  4160.       INPUT "Calculation (1=st. dev., 2=mean)? ", Choice
  4161.  
  4162.       ' Now, chain to the correct program:
  4163.       SELECT CASE Choice
  4164.  
  4165.          CASE 1:             ' Standard Deviation
  4166.             CHAIN "STDEV"
  4167.  
  4168.          CASE 2:             ' Mean
  4169.             CHAIN "MEAN"
  4170.       END SELECT
  4171.    END
  4172.  
  4173.    ' ======================= STDEV.BAS =======================
  4174.    ' Calculates the standard deviation of a set of data
  4175.    ' =========================================================
  4176.  
  4177.    ' $INCLUDE: 'COMMONS.BI'
  4178.  
  4179.       Sum   = 0   ' Normal sum
  4180.       SumSq = 0   ' Sum of values squared
  4181.  
  4182.       FOR I = 1 TO NumValues
  4183.          Sum   = Sum   + Values(I)
  4184.          SumSq = SumSq + Values(I) ^ 2
  4185.       NEXT I
  4186.  
  4187.       Stdev = SQR(SumSq / NumValues - (Sum / NumValues) ^ 2)
  4188.       PRINT "The Standard Deviation of the samples is: " Stdev
  4189.    END
  4190.  
  4191.    ' ======================== MEAN.BAS =======================
  4192.    ' Calculates the mean (average) of a set of data
  4193.    ' =========================================================
  4194.  
  4195.    ' $INCLUDE: 'COMMONS.BI'
  4196.  
  4197.       Sum = 0
  4198.  
  4199.       FOR I = 1 TO NumValues
  4200.          Sum = Sum + Values(I)
  4201.       NEXT
  4202.  
  4203.       Mean = Sum / NumValues
  4204.       PRINT "The mean of the samples is: " Mean
  4205.    END
  4206.  
  4207.  
  4208.  2.11  Sample Application: Recursive Directory Search (WHEREIS.BAS)
  4209.  
  4210.    The following program uses a recursive SUB procedure, ScanDir, to scan a
  4211.    disk for the file name input by the user. Each time this program finds the
  4212.    given file, it prints the complete directory path to the file.
  4213.  
  4214.    Statements and Functions Used
  4215.  
  4216.    This program demonstrates the following statements and keywords discussed
  4217.    in this chapter:
  4218.  
  4219.    ■ DECLARE
  4220.  
  4221.    ■ FUNCTION...END FUNCTION
  4222.  
  4223.    ■ STATIC
  4224.  
  4225.    ■ SUB...END SUB
  4226.  
  4227.  Program Listing
  4228.  
  4229.  DEFINT A-Z
  4230.  
  4231.  ' Declare symbolic constants used in program:
  4232.  CONST EOFTYPE = 0, FILETYPE = 1, DIRTYPE = 2, ROOT = "TWH"
  4233.  
  4234.  DECLARE SUB ScanDir (PathSpec$, Level, FileSpec$, Row)
  4235.  
  4236.  DECLARE FUNCTION MakeFileName$ (Num)
  4237.  DECLARE FUNCTION GetEntry$ (FileNum, EntryType)
  4238.  
  4239.  CLS
  4240.  INPUT "File to look for"; FileSpec$
  4241.  PRINT
  4242.  PRINT "Enter the directory where the search should start"
  4243.  PRINT "(optional drive + directories). Press <ENTER> to "
  4244.  PRINT "begin search in root directory of current drive."
  4245.  PRINT
  4246.  INPUT "Starting directory"; PathSpec$
  4247.  CLS
  4248.  
  4249.  RightCh$ = RIGHT$(PathSpec$, 1)
  4250.  
  4251.  IF PathSpec$ = "" OR RightCh$ = ":" OR RightCh$ <> "\" THEN
  4252.     PathSpec$ = PathSpec$ + "\"
  4253.  END IF
  4254.  
  4255.  FileSpec$ = UCASE$(FileSpec$)
  4256.  PathSpec$ = UCASE$(PathSpec$)
  4257.  Level = 1
  4258.  Row = 3
  4259.  
  4260.  ' Make the top level call (level 1) to begin the search:
  4261.  ScanDir PathSpec$, Level, FileSpec$, Row
  4262.  
  4263.  KILL ROOT + ".*"        ' Delete all temporary files created
  4264.                          ' by the program.
  4265.  
  4266.  LOCATE Row + 1, 1: PRINT "Search complete."
  4267.  END
  4268.  
  4269.  ' ======================= GETENTRY ========================
  4270.  '    This procedure processes entry lines in a DIR listing
  4271.  '    saved to a file.
  4272.  
  4273.  '    This procedure returns the following values:
  4274.  
  4275.  '       GetEntry$       A valid file or directory name
  4276.  '       EntryType       If equal to 1, then GetEntry$
  4277.  '                       is a file.
  4278.  '                       If equal to 2, then GetEntry$
  4279.  '                       is a directory.
  4280.  ' =========================================================
  4281.  
  4282.  FUNCTION GetEntry$ (FileNum, EntryType) STATIC
  4283.  
  4284.     ' Loop until a valid entry or end-of-file (EOF) is read:
  4285.     DO UNTIL EOF(FileNum)
  4286.        LINE INPUT #FileNum, EntryLine$
  4287.        IF EntryLine$ <> "" THEN
  4288.  
  4289.           ' Get first character from the line for test:
  4290.           TestCh$ = LEFT$(EntryLine$, 1)
  4291.           IF TestCh$ <> " " AND TestCh$ <> "." THEN EXIT DO
  4292.        END IF
  4293.     LOOP
  4294.  
  4295.     ' Entry or EOF found, decide which:
  4296.     IF EOF(FileNum) THEN         ' EOF, so return EOFTYPE
  4297.        EntryType = EOFTYPE       ' in EntryType.
  4298.        GetEntry$ = ""
  4299.  
  4300.     ELSE                         ' Not EOF, so it must be a
  4301.                                  ' file or a directory.
  4302.  
  4303.        ' Build and return the entry name:
  4304.        EntryName$ = RTRIM$(LEFT$(EntryLine$, 8))
  4305.  
  4306.        ' Test for extension and add to name if there is one:
  4307.        EntryExt$ = RTRIM$(MID$(EntryLine$, 10, 3))
  4308.        IF EntryExt$ <> "" THEN
  4309.           GetEntry$ = EntryName$ + "." + EntryExt$
  4310.        ELSE
  4311.           GetEntry$ = EntryName$
  4312.        END IF
  4313.  
  4314.        ' Determine the entry type, and return that value
  4315.        ' to the point where GetEntry$ was called:
  4316.        IF MID$(EntryLine$, 15, 3) = "DIR" THEN
  4317.           EntryType = DIRTYPE            ' Directory
  4318.        ELSE
  4319.           EntryType = FILETYPE           ' File
  4320.        END IF
  4321.  
  4322.     END IF
  4323.  
  4324.  END FUNCTION
  4325.  
  4326.  ' ===================== MAKEFILENAME$ =====================
  4327.  '    This procedure makes a file name from a root string
  4328.  '    ("TWH," defined as a symbolic constant at the module
  4329.  '    level) and a number passed to it as an argument (Num).
  4330.  ' =========================================================
  4331.  
  4332.  FUNCTION MakeFileName$ (Num) STATIC
  4333.  
  4334.     MakeFileName$ = ROOT + "." + LTRIM$(STR$(Num))
  4335.  
  4336.  END FUNCTION
  4337.  
  4338.  ' ======================= SCANDIR =========================
  4339.  '   This procedure recursively scans a directory for the
  4340.  '   file name entered by the user.
  4341.  
  4342.  '   NOTE: The SUB header doesn't use the STATIC keyword
  4343.  '         since this procedure needs a new set of variables
  4344.  '         each time it is invoked.
  4345.  ' =========================================================
  4346.  
  4347.  SUB ScanDir (PathSpec$, Level, FileSpec$, Row)
  4348.  
  4349.     LOCATE 1, 1: PRINT "Now searching"; SPACE$(50);
  4350.     LOCATE 1, 15: PRINT PathSpec$;
  4351.  
  4352.     ' Make a file specification for the temporary file:
  4353.     TempSpec$ = MakeFileName$(Level)
  4354.  
  4355.     ' Get a directory listing of the current directory,
  4356.     ' and save it in the temporary file:
  4357.     SHELL "DIR " + PathSpec$ + " > " + TempSpec$
  4358.  
  4359.     ' Get the next available file number:
  4360.     FileNum = FREEFILE
  4361.  
  4362.     ' Open the DIR listing file and scan it:
  4363.     OPEN TempSpec$ FOR INPUT AS #FileNu
  4364.  
  4365.  ' Process the file, one line at a time:
  4366.     DO
  4367.  
  4368.        ' Input an entry from the DIR listing file:
  4369.        DirEntry$ = GetEntry$(FileNum, EntryType)
  4370.  
  4371.        ' If entry is a file:
  4372.        IF EntryType = FILETYPE THEN
  4373.  
  4374.           ' If the FileSpec$ string matches,
  4375.           ' print entry and exit this loop:
  4376.           IF DirEntry$ = FileSpec$ THEN
  4377.             LOCATE Row, 1: PRINT PathSpec$; DirEntry$;
  4378.             Row = Row + 1
  4379.             EntryType = EOFTYPE
  4380.           END IF
  4381.  
  4382.        ' If the entry is a directory, then make a recursive
  4383.        ' call to ScanDir with the new directory:
  4384.        ELSEIF EntryType = DIRTYPE THEN
  4385.           NewPath$ = PathSpec$ + DirEntry$ + "\"
  4386.           ScanDir NewPath$, Level + 1, FileSpec$, Row
  4387.           LOCATE 1, 1: PRINT "Now searching"; SPACE$(50);
  4388.           LOCATE 1, 15: PRINT PathSpec$;
  4389.        END IF
  4390.  
  4391.     LOOP UNTIL EntryType = EOFTYPE
  4392.  
  4393.     ' Scan on this DIR listing file is finished, so close it:
  4394.     CLOSE FileNum
  4395.  END SUB
  4396.  
  4397.  
  4398.  
  4399.  ────────────────────────────────────────────────────────────────────────────
  4400.  Chapter 3  File and Device I/O
  4401.  
  4402.    This chapter shows you how to use BASIC input and output (I/O) functions
  4403.    and statements. These statements permit your programs to access data
  4404.    stored in files and to communicate with devices attached to your system.
  4405.  
  4406.    The chapter includes material on a variety of programming tasks related to
  4407.    retrieving, storing, and formatting information. The relationship between
  4408.    data files and physical devices such as screens and keyboards is also
  4409.    covered.
  4410.  
  4411.    When you are finished with this chapter, you will know how to perform the
  4412.    following programming tasks:
  4413.  
  4414.    ■ Print text on the screen
  4415.  
  4416.    ■ Get input from the keyboard for use in a program
  4417.  
  4418.    ■ Create data files on disk
  4419.  
  4420.    ■ Store records in data files
  4421.  
  4422.    ■ Read records from data files
  4423.  
  4424.    ■ Read or modify data in files that are not in American Standard Code for
  4425.      Information Interchange (ASCII) format
  4426.  
  4427.    ■ Communicate with other computers through the serial port
  4428.  
  4429.  
  4430.  3.1  Printing Text on the Screen
  4431.  
  4432.    This section explains how to accomplish the following tasks:
  4433.  
  4434.    ■ Display text on the screen with PRINT
  4435.  
  4436.    ■ Display formatted text on the screen with PRINT USING
  4437.  
  4438.    ■ Skip spaces in a row of printed text with SPC
  4439.  
  4440.    ■ Skip to a given column in a row of printed text with TAB
  4441.  
  4442.    ■ Change the number of rows or columns appearing on the screen with WIDTH
  4443.  
  4444.    ■ Open a text viewport with VIEW PRINT
  4445.  
  4446.    ──────────────────────────────────────────────────────────────────────────
  4447.    NOTE
  4448.      Output that appears on the screen is sometimes referred to as "standard
  4449.      output." You can redirect standard output by using the DOS command-line
  4450.      symbols > or >>, thus sending output that would have gone to the screen
  4451.      to a different output device (such as a printer) or to a disk file. (See
  4452.      your DOS documentation for more information on redirecting output.)
  4453.    ──────────────────────────────────────────────────────────────────────────
  4454.  
  4455.  3.1.1  Screen Rows and Columns
  4456.  
  4457.    To understand how text is printed on the screen, it helps to think of the
  4458.    screen as a grid of "rows" and "columns." The height of one row slightly
  4459.    exceeds the height of a line of printed output, while the width of one
  4460.    column is just wider than the width of one character. A standard screen
  4461.    configuration in text mode (nongraphics) is 80 columns wide by 25 rows
  4462.    high. Figure 3.1 shows how each character printed on the screen occupies a
  4463.    unique cell in the grid, a cell that can be identified by pairing a row
  4464.    argument with a column argument.
  4465.  
  4466.    The bottom row of the screen is not usually used for output, unless you
  4467.    use a LOCATE statement to display text there. (See Section 3.3,
  4468.    "Controlling the Text Cursor," for more information on LOCATE.)
  4469.  
  4470.  3.1.2  Displaying Text and Numbers with PRINT
  4471.  
  4472.  
  4473.  ┌───────────────────────────────────────────────────────────────────┐
  4474.  │                                                                   │
  4475.  │                                                                   │
  4476.  │        ──────────────── Columns ──────────────                  │
  4477.  │     ┌────────────────────────                                     │
  4478.  │     │     1   2   3   4   5   6   7   8   9                       │
  4479.  │    │   ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬─                    │
  4480.  │  │  │ 1 │   │   │   │   │   │   │   │   │   │                     │
  4481.  │  │  │   ├───┼───┼───┼───┼───┼───┼───┼───┼───┼─                    │
  4482.  │  │  │ 2 │   │   │   │ H │ E │ L │ L │ O │   │                     │
  4483.  │Rows │   ├───┼───┼───┼──\┼───┼───┼───┼───┼───┼─                    │
  4484.  │  │  │ 3 │   │   │   │   │\──┼───┼───┼───┼───┼── This output starts│
  4485.  │  │  │   ├───┼───┼───┼───┼───┼───┼───┼───┼───┼─  in row 2, column 4│
  4486.  │  │    4 │   │   │   │   │   │   │   │   │   │                     │
  4487.  │  │      ├───┼───┼───┼───┼───┼───┼───┼───┼───┼─                    │
  4488.  │        │   │   │   │   │   │   │   │   │   │                     │
  4489.  │                                                                   │
  4490.  └───────────────────────────────────────────────────────────────────┘
  4491.  
  4492.  Figure 3.1  Text Output on Screen
  4493.  
  4494.    By far the most commonly used statement for output to the screen is the
  4495.    PRINT statement. With PRINT, you can display numeric or string values, or
  4496.    a mixture of the two. In addition, PRINT with no arguments prints a blank
  4497.    line.
  4498.  
  4499.    The following are some general comments about PRINT:
  4500.  
  4501.    ■ PRINT always prints numbers with a trailing blank space. If the number
  4502.      is positive, the number is also preceded by a space; if the number is
  4503.      negative, the number is preceded by a minus sign.
  4504.  
  4505.    ■ The PRINT statement can be used to print lists of expressions.
  4506.      Expressions in the list can be separated from other expressions by
  4507.      commas, semicolons, one or more blank spaces, or one or more tab
  4508.      characters. A comma causes PRINT to skip to the beginning of the next
  4509.      "print zone," or block of 14 columns, on the screen. A semicolon (or any
  4510.      combination of spaces and/or tabs) between two expressions prints the
  4511.      expressions on the screen next to each other, with no spaces in between
  4512.      (except for the built-in spaces for numbers).
  4513.  
  4514.    ■ Ordinarily, PRINT ends each line of output with a new-line sequence (a
  4515.      carriage-return and line-feed). However, a comma or semicolon at the end
  4516.      of the list of expressions suppresses this; the next printed output from
  4517.      the program appears on the same line unless it is too long to fit on
  4518.      that line.
  4519.  
  4520.    ■ PRINT wraps an output line that exceeds the width of the screen onto the
  4521.      next line. For example, if you try to print a line that is 100
  4522.      characters long on an 80-column screen, the first 80 characters of the
  4523.      line show up on one row, followed by the next 20 characters on the next
  4524.      row. If the 100-character line didn't start at the left edge of the
  4525.      screen (for example, if it followed a PRINT statement ending in a comma
  4526.      or semicolon), then the line would print until it reached the 80th
  4527.      column of one row and continue in the first column of the next row.
  4528.  
  4529.    Example
  4530.  
  4531.    The output from the following program shows some of the different ways you
  4532.    can use PRINT:
  4533.  
  4534.    A = 2
  4535.    B = -1
  4536.    C = 3
  4537.    X$ = "over"
  4538.    Y$ = "there"
  4539.  
  4540.    PRINT A, B, C
  4541.    PRINT B, A, C
  4542.    PRINT A; B; C
  4543.    PRINT X$; Y$
  4544.    PRINT X$, Y$;
  4545.    PRINT A, B
  4546.    PRINT
  4547.    FOR I = 1 TO 8
  4548.       PRINT X$,
  4549.    NEXT
  4550.  
  4551.    Output
  4552.  
  4553.     2            -1             3
  4554.    -1             2             3
  4555.     2 -1  3
  4556.    overthere
  4557.    over          there 2       -1
  4558.  
  4559.    over          over          over          over          over
  4560.    over          over          over
  4561.  
  4562.  3.1.3  Displaying Formatted Output with PRINT USING
  4563.  
  4564.    The PRINT USING statement gives greater control than PRINT over the
  4565.    appearance of printed data, especially numeric data. Through the use of
  4566.    special characters embedded in a format string, PRINT USING allows you to
  4567.    specify information such as how many digits from a number (or how many
  4568.    characters from a string) are displayed, whether or not a plus (+) sign or
  4569.    a dollar sign ($) appears in front of a number, and so forth.
  4570.  
  4571.    Example
  4572.  
  4573.    The example that follows gives you a sample of what can be done with PRINT
  4574.    USING. You can list more than one expression after the PRINT USING format
  4575.    string. As is the case with PRINT, the expressions in the list can be
  4576.    separated from one another by commas, semicolons, spaces, or tab
  4577.    characters.
  4578.  
  4579.    X = 441.2318
  4580.  
  4581.    PRINT USING "The number with 3 decimal places ###.###";X
  4582.    PRINT USING "The number with a dollar sign $$##.##";X
  4583.    PRINT USING "The number in exponential format #.###^^^^";X
  4584.    PRINT USING "Numbers with plus signs +###  "; X; 99.9
  4585.  
  4586.    Output
  4587.  
  4588.    The number with 3 decimal places 441.232
  4589.    The number with a dollar sign $441.23
  4590.    The number in exponential format 0.441E+03
  4591.    Numbers with plus signs +441  Numbers with plus signs +100
  4592.  
  4593.    Consult the QB Advisor for more on PRINT USING.
  4594.  
  4595.  3.1.4  Skipping Spaces and Advancing to a Specific Column
  4596.  
  4597.    By using the SPC(n) statement in a PRINT statement, you can skip n spaces
  4598.    in a row of printed output, as shown by the output from the next example:
  4599.  
  4600.    PRINT "         1         2         3"
  4601.    PRINT "123456789012345678901234567890"
  4602.    PRINT "First Name"; SPC(10); "Last Name"
  4603.  
  4604.    Output
  4605.  
  4606.    1         2         3
  4607.    123456789012345678901234567890
  4608.    First Name          Last Name
  4609.  
  4610.    By using the TAB(n) statement in a PRINT statement, you can skip to the
  4611.    nth column (counting from the left side of the screen) in a row of printed
  4612.    output. The following example uses TAB to produce the same output as that
  4613.    shown above:
  4614.  
  4615.    PRINT "         1         2         3"
  4616.    PRINT "123456789012345678901234567890"
  4617.    PRINT "First Name"; TAB(21); "Last Name"
  4618.  
  4619.    Neither SPC nor TAB can be used by itself to position printed output on
  4620.    the screen; they can only appear in PRINT statements.
  4621.  
  4622.  3.1.5  Changing the Number of Columns or Rows
  4623.  
  4624.    You can control the maximum number of characters that appear in a single
  4625.    row of output by using the WIDTH columns statement. The WIDTH columns
  4626.    statement actually changes the size of characters that are printed on the
  4627.    screen, so that more or fewer characters can fit on a row. For example,
  4628.    WIDTH 40 makes characters wider, so the maximum row length is 40
  4629.    characters. WIDTH 80 makes characters narrower, so the maximum row length
  4630.    is 80 characters. The numbers 40 and 80 are the only valid values for the
  4631.    columns argument.
  4632.  
  4633.    On machines equipped with an Enhanced Graphics Adapter (EGA) or Video
  4634.    Graphics Adapter (VGA), the WIDTH statement can also control the number of
  4635.    rows that appear on the screen as follows:
  4636.  
  4637.    WIDTH[[columns]] [[,rows]]
  4638.  
  4639.    The value for rows may be 25, 30, 43, 50, or 60, depending on the type of
  4640.    display adapter you use and the screen mode set in a preceding SCREEN
  4641.    statement.
  4642.  
  4643.  3.1.6  Creating a Text Viewport
  4644.  
  4645.    So far, the entire screen has been used for text output. However, with the
  4646.    VIEW PRINT statement, you can restrict printed output to a "text
  4647.    viewport," a horizontal slice of the screen. The syntax of the VIEW PRINT
  4648.    statement is:
  4649.  
  4650.    VIEW PRINT[[topline TO bottomline]]
  4651.  
  4652.    The values for topline and bottomline specify the locations where the
  4653.    viewport will begin and end.
  4654.  
  4655.    A text viewport also gives you control over on-screen scrolling. Without a
  4656.    viewport, once printed output reaches the bottom of the screen, text or
  4657.    graphics output that was at the top of the screen scrolls off and is lost.
  4658.    However, after a VIEW PRINT statement, scrolling takes place only between
  4659.    the top and bottom lines of the viewport. This means you can label the
  4660.    displayed output at the top and/or bottom of the screen without having to
  4661.    worry that the labeling will scroll it off if too many lines of data
  4662.    appear. You can also use the CLS 2 statement to clear just the text
  4663.    viewport, leaving the contents of the rest of the screen intact. See
  4664.    Section 5.5, "Defining a Graphics Viewport," to learn how to create a
  4665.    viewport for graphics output on the screen.
  4666.  
  4667.    Example
  4668.  
  4669.    You can see the effects of a VIEW PRINT statement by examining the output
  4670.    from the next example:
  4671.  
  4672.    CLS
  4673.    LOCATE 3, 1
  4674.    PRINT "This is above the text viewport; it doesn't scroll."
  4675.  
  4676.    LOCATE 4, 1
  4677.    PRINT STRING$(60, "_")       ' Print horizontal lines above
  4678.    LOCATE 11, 1
  4679.    PRINT STRING$(60, "_")       ' and below the text viewport.
  4680.  
  4681.    PRINT "This is below the text viewport."
  4682.  
  4683.    VIEW PRINT 5 TO 10             ' Text viewport extends from
  4684.                                   ' lines 5 to 10.
  4685.  
  4686.    FOR I = 1 TO 20                ' Print numbers and text in
  4687.       PRINT I; "a line of text"   ' the viewport.
  4688.    NEXT
  4689.  
  4690.    DO: LOOP WHILE INKEY$ = ""     ' Wait for a key press.
  4691.    CLS 2                          ' Clear just the viewport.
  4692.    END
  4693.  
  4694.    Output (Before User Presses Key)
  4695.  
  4696.    ┌───────────────────────────────────────────────────────────────────┐
  4697.    │                                                                   │
  4698.    │                                                                   │
  4699.    │  This is above the text viewport: it doesn't scroll.              │
  4700.    │  ───────────────────────────────────────────────────────────────  │
  4701.    │  16 a line of text                                                │
  4702.    │  17 a line of text                                                │
  4703.    │  18 a line of text                                                │
  4704.    │  19 a line of text                                                │
  4705.    │  20 a line of text                                                │
  4706.    │                                                                   │
  4707.    │                                                                   │
  4708.    │  ───────────────────────────────────────────────────────────────  │
  4709.    │  This is below the text viewport.                                 │
  4710.    │                                                                   │
  4711.    │                                                                   │
  4712.    │                                                                   │
  4713.    │                                                                   │
  4714.    └───────────────────────────────────────────────────────────────────┘
  4715.  
  4716.    Output (After User Presses Key)
  4717.  
  4718.    ┌───────────────────────────────────────────────────────────────────┐
  4719.    │                                                                   │
  4720.    │                                                                   │
  4721.    │   This is above the text viewport: it doesn't scroll.             │
  4722.    │   ───────────────────────────────────────────────────────────     │
  4723.    │                                                                   │
  4724.    │                                                                   │
  4725.    │                                                                   │
  4726.    │   ───────────────────────────────────────────────────────────     │
  4727.    │   This is below the text viewport.                                │
  4728.    │                                                                   │
  4729.    │                                                                   │
  4730.    │                                                                   │
  4731.    │                                                                   │
  4732.    │                                                                   │
  4733.    │                                                                   │
  4734.    │                                                                   │
  4735.    │                                                                   │
  4736.    │                                                                   │
  4737.    └───────────────────────────────────────────────────────────────────┘
  4738.  
  4739.  
  4740.  3.2  Getting Input from the Keyboard
  4741.  
  4742.    This section shows you how to use the following statements and functions
  4743.    to enable your BASIC programs to accept input entered from the keyboard:
  4744.  
  4745.    ■ INPUT
  4746.  
  4747.    ■ LINE INPUT
  4748.  
  4749.    ■ INPUT$
  4750.  
  4751.    ■ INKEY$
  4752.  
  4753.    ──────────────────────────────────────────────────────────────────────────
  4754.    NOTE
  4755.      Input typed at the keyboard is often referred to as "standard input."
  4756.      You can use the DOS symbol < to direct standard input to your program
  4757.      from a file or other input device instead of from the keyboard. (See
  4758.      your DOS documentation for more information on redirecting input.)
  4759.    ──────────────────────────────────────────────────────────────────────────
  4760.  
  4761.  3.2.1  The INPUT Statement
  4762.  
  4763.    The INPUT statement takes information typed by the user and stores it in a
  4764.    list of variables, as shown in the following example:
  4765.  
  4766.    INPUT A%, B, C$
  4767.    INPUT D$
  4768.    PRINT A%, B, C$, D$
  4769.  
  4770.    Output
  4771.  
  4772.    ? 6.6,45,a string
  4773.    ? "two, three"
  4774.     7             45           a string      two, three
  4775.  
  4776.    Here are some general comments about INPUT:
  4777.  
  4778.    ■ An INPUT statement by itself prompts the user with a question mark (?)
  4779.      followed by a blinking cursor.
  4780.  
  4781.    ■ The INPUT statement is followed by one or more variable names. If there
  4782.      are more than one variable, they are separated by commas.
  4783.  
  4784.    ■ The number of constants entered by the user after the INPUT prompt must
  4785.      be the same as the number of variables in the INPUT statement itself.
  4786.  
  4787.    ■ The values the user enters must agree in type with the variables in the
  4788.      list following INPUT. In other words, enter a number if the variable is
  4789.      designated as having the type integer, long integer, single precision,
  4790.      or double precision. Enter a string if the variable is designated as
  4791.      having the type string.
  4792.  
  4793.    ■ Since constants in an input list must be separated by commas, an input
  4794.      string constant containing one or more commas should be enclosed in
  4795.      double quotes. The double quotes ensure that the string is treated as a
  4796.      unit and not broken into two or more parts.
  4797.  
  4798.    If the user breaks any of the last three rules, BASIC prints the error
  4799.    message Redo from start. This message reappears until the input agrees in
  4800.    number and type with the variable list.
  4801.  
  4802.    If you want your input prompt to be more informative than a simple
  4803.    question mark, you can make a prompt appear, as in the following example:
  4804.  
  4805.    INPUT "What is the correct time (hour, min)"; Hr$, Min$
  4806.  
  4807.    This prints the following prompt:
  4808.  
  4809.    What is the correct time (hour, min)?
  4810.  
  4811.    Note the semicolon between the prompt and the input variables. This
  4812.    semicolon causes a question mark to appear as part of the prompt.
  4813.    Sometimes you may want to eliminate the question mark altogether; in this
  4814.    case, put a comma between the prompt and the variable list:
  4815.  
  4816.    INPUT "Enter the time (hour, min): ", Hr$, Min$
  4817.  
  4818.    This prints the following prompt:
  4819.  
  4820.    Enter the time (hour, min):
  4821.  
  4822.  3.2.2  The LINE INPUT Statement
  4823.  
  4824.    If you want your program to accept lines of text with embedded commas,
  4825.    leading blanks, or trailing blanks, yet you do not want to have to remind
  4826.    the user to enclose the input in double quotes, use the LINE INPUT
  4827.    statement. The LINE INPUT statement, as its name implies, accepts a line
  4828.    of input (terminated by pressing the ENTER key) from the keyboard and
  4829.    stores it in a single string variable. Unlike INPUT, the LINE INPUT
  4830.    statement does not print a question mark by default to prompt for input;
  4831.    it does, however, allow you to display a prompt string.
  4832.  
  4833.    The following example shows the difference between INPUT and LINE INPUT:
  4834.  
  4835.    ' Assign the input to three separate variables:
  4836.    INPUT "Enter three values separated by commas: ", A$, B$, C$
  4837.  
  4838.    ' Assign the input to one variable (commas not treated
  4839.    ' as delimiters between input):
  4840.    LINE INPUT "Enter the same three values: ", D$
  4841.  
  4842.    PRINT "A$ = "; A$
  4843.    PRINT "B$ = "; B$
  4844.    PRINT "C$ = "; C$
  4845.    PRINT "D$ = "; D$
  4846.  
  4847.    Output
  4848.  
  4849.    Enter 3 values separated by commas: by land, air, and sea
  4850.    Enter the same three values: by land, air, and sea
  4851.    A$ = by land
  4852.    B$ = air
  4853.    C$ = and sea
  4854.    D$ = by land, air, and sea
  4855.  
  4856.    With both INPUT and LINE INPUT, input is terminated when the user presses
  4857.    the ENTER key, which also advances the cursor to the next line. As the
  4858.    next example shows, a semicolon between the INPUT keyword and the prompt
  4859.    string keeps the cursor on the same line:
  4860.  
  4861.    INPUT "First value: ", A
  4862.    INPUT; "Second value: ", B
  4863.    INPUT "    Third value: ", C
  4864.  
  4865.    The following shows some sample input to the preceding program and the
  4866.    positions of the prompts:
  4867.  
  4868.    First value: 5
  4869.    Second value: 4     Third value: 3
  4870.  
  4871.  3.2.3  The INPUT$ Function
  4872.  
  4873.    Both INPUT and LINE INPUT wait for the user to press the ENTER key before
  4874.    they store what is typed; that is, they read a line of input, then assign
  4875.    it to program variables. In contrast, the INPUT$(number) function doesn't
  4876.    wait for the enter key to be pressed; it just reads a specified number of
  4877.    characters. For example, the following line in a program reads three
  4878.    characters typed by the user, then stores the three-character string in
  4879.    the variable Test$:
  4880.  
  4881.    Test$ = INPUT$(3)
  4882.  
  4883.    Unlike the INPUT statement, the INPUT$ function does not prompt the user
  4884.    for data, nor does it echo input characters on the screen. Also, since
  4885.    INPUT$ is a function, it cannot stand by itself as a complete statement.
  4886.    INPUT$ must appear in an expression, as in the following:
  4887.  
  4888.    INPUT x              ' INPUT is a statement.
  4889.  
  4890.    PRINT INPUT$(1)      ' INPUT$ is a function, so it must
  4891.    Y$ = INPUT$(1)       ' appear in an expression.
  4892.  
  4893.    The INPUT$ function reads input from the keyboard as an unformatted stream
  4894.    of characters. Unlike INPUT or LINE INPUT, INPUT$ accepts any key pressed,
  4895.    including control keys like ESC or BACKSPACE. For example, pressing the
  4896.    ENTER key five times assigns five carriage-return characters to the Test$
  4897.    variable in the next line:
  4898.  
  4899.    Test$ = INPUT$(5)
  4900.  
  4901.  3.2.4  The INKEY$ Function
  4902.  
  4903.    The INKEY$ function completes the list of BASIC's keyboard-input functions
  4904.    and statements. When BASIC encounters an expression containing the INKEY$
  4905.    function, it checks to see if the user has pressed a key since one of the
  4906.    following:
  4907.  
  4908.    ■ The last time it found an expression with INKEY$
  4909.  
  4910.    ■ The beginning of the program, if this is the first time INKEY$ appears
  4911.  
  4912.    If no key has been pressed since the last time the program checked, INKEY$
  4913.    returns a null string (""). If a key has been pressed, INKEY$ returns the
  4914.    character corresponding to that key.
  4915.  
  4916.    Example
  4917.  
  4918.    The most important difference between INKEY$ and the other statements and
  4919.    functions discussed in this section is that INKEY$ lets your program
  4920.    continue doing other things while it checks for input. In contrast, LINE
  4921.    INPUT, INPUT$, and INPUT suspend program execution until there is input,
  4922.    as show in this example:
  4923.  
  4924.    PRINT "Press any key to start. Press any key to end."
  4925.  
  4926.    ' Don't do anything else until the user presses a key:
  4927.    Begin$ = INPUT$(1)
  4928.  
  4929.    I = 1
  4930.  
  4931.    ' Print the numbers from one to one million.
  4932.    ' Check for a key press while the loop is executing:
  4933.    DO
  4934.       PRINT I
  4935.       I = I + 1
  4936.  
  4937.    ' Continue looping until the value of the variable I is
  4938.    ' greater than one million or until a key is pressed:
  4939.    LOOP UNTIL I > 1000000 OR INKEY$ <> ""
  4940.  
  4941.  
  4942.  3.3  Controlling the Text Cursor
  4943.  
  4944.    When you display printed text on the screen, the text cursor marks the
  4945.    place on the screen where output from the program──or input typed by the
  4946.    user──will appear next. In the next example, after the INPUT statement
  4947.    displays its 12-letter prompt, First name:, the cursor waits for input in
  4948.    row 1 at column 13:
  4949.  
  4950.    ' Clear the screen; start printing in row one, column one:
  4951.    CLS
  4952.    INPUT "First name: ", FirstName$
  4953.  
  4954.    In the next example, the semicolon at the end of the second PRINT
  4955.    statement leaves the cursor in row 2 at column 27:
  4956.  
  4957.    CLS
  4958.    PRINT
  4959.  
  4960.    ' Twenty-six characters are in the next line:
  4961.    PRINT "Press any key to continue.";
  4962.    PRINT INPUT$(1)
  4963.  
  4964.    Sections 3.3.1-3.3.3 show how to control the location of the text cursor,
  4965.    change its shape, and get information about its location.
  4966.  
  4967.  3.3.1  Positioning the Cursor
  4968.  
  4969.    The input and output statements and functions discussed so far do not
  4970.    allow much control over where output is displayed or where the cursor is
  4971.    located after the output is displayed. Input prompts or output always
  4972.    start in the far left column of the screen and descend one row at a time
  4973.    from top to bottom unless a semicolon is used in the PRINT or INPUT
  4974.    statements to suppress the carriage-return and line-feed sequence.
  4975.  
  4976.    The SPC and TAB statements, discussed in Section 3.1.4, "Skipping Spaces
  4977.    and Advancing to a Specific Column," give some control over the location
  4978.    of the cursor by allowing you to move it to any column within a given row.
  4979.  
  4980.    The LOCATE statement extends this control one step further. The syntax for
  4981.    LOCATE is
  4982.  
  4983.    LOCATE[[row]][[,[[column]][[,[[cursor]][[,[[start]][[,stop]]]]]]]]
  4984.  
  4985.    Using the LOCATE statement allows you to position the cursor in any row or
  4986.    column on the screen, as shown by the output from the next example:
  4987.  
  4988.    CLS
  4989.    FOR Row = 9 TO 1 STEP -2
  4990.       Column = 2 * Row
  4991.       LOCATE Row, Column
  4992.       PRINT "12345678901234567890";
  4993.    NEXT
  4994.  
  4995.    Output
  4996.  
  4997.    12345678901234567890
  4998.  
  4999.        12345678901234567890
  5000.  
  5001.            12345678901234567890
  5002.  
  5003.                12345678901234567890
  5004.  
  5005.                    12345678901234567890
  5006.  
  5007.  3.3.2  Changing the Cursor's Shape
  5008.  
  5009.    The optional cursor, start, and stop arguments shown in the syntax for the
  5010.    LOCATE statement also allow you to change the shape of the cursor and make
  5011.    it visible or invisible. A value of 1 for cursor makes the cursor visible,
  5012.    while a value of 0 makes the cursor invisible. The start and stop
  5013.    arguments control the height of the cursor, if it is on, by specifying the
  5014.    top and bottom "pixel" lines, respectively, for the cursor. (Any character
  5015.    on the screen is composed of lines of pixels, which are dots of light on
  5016.    the screen.) If a cursor spans the height of one row of text, then the
  5017.    line of pixels at the top of the cursor has the value 0, while the line of
  5018.    pixels at the bottom has a value of 7 or 13, depending on the type of
  5019.    display adapter you have. (For monochrome the value is 13; for color it is
  5020.    7.)
  5021.  
  5022.    You can turn the cursor on and change its shape without specifying a new
  5023.    location for it. For example, the following statement keeps the cursor
  5024.    wherever it is at the completion of the next PRINT or INPUT statement,
  5025.    then makes it half a character high:
  5026.  
  5027.    LOCATE , , 1, 2, 5    ' Row and column arguments both optional
  5028.  
  5029.    The following examples show different cursor shapes produced using
  5030.    different start and stop values on a color display. Each LOCATE statement
  5031.    shown in the left column is followed by the statement
  5032.  
  5033.    INPUT "PROMPT:", X$
  5034.  
  5035.    Statement                            Input Prompt and Cursor Shape
  5036.    ──────────────────────────────────────────────────────────────────────────
  5037.    LOCATE, , 1, 0, 7                    PROMPT:█
  5038.  
  5039.    LOCATE, , 1, 0, 3                    PROMPT:▀
  5040.  
  5041.    LOCATE, , 1, 4, 7                    PROMPT:
  5042.  
  5043.    LOCATE, , 1, 6, 2                    PROMPT:(see page 94 of printed
  5044.                                         manual)
  5045.    ──────────────────────────────────────────────────────────────────────────
  5046.  
  5047.    In the preceding examples, note that making the start argument bigger than
  5048.    the stop argument results in a two-piece cursor.
  5049.  
  5050.  3.3.3  Getting Information about the Cursor's Location
  5051.  
  5052.    You can think of the functions CSRLIN and POS(n) as the inverses of the
  5053.    LOCATE statement: whereas LOCATE tells the cursor where to go, CSRLIN and
  5054.    POS(n) tell your program where the cursor is. The CSRLIN function returns
  5055.    the current row and the POS(n) function returns the current column of the
  5056.    cursor's position.
  5057.  
  5058.    The argument n for POS(n) is what is known as a "dummy" argument; that is,
  5059.    n is a placeholder that can be any numeric expression. For example, POS(0)
  5060.    and POS(1) both return the same value.
  5061.  
  5062.    Example
  5063.  
  5064.    The following example uses the POS(n) function to print 50 asterisks in
  5065.    rows of 13 asterisks:
  5066.  
  5067.    FOR I% = 1 TO 50
  5068.       PRINT "*";                  ' Print an asterisk and keep
  5069.                                   ' the cursor on the same line.
  5070.       IF POS(1) > 13 THEN PRINT   ' If the cursor's position
  5071.                                   ' is past column 13, advance
  5072.                                   ' to the next line.
  5073.    NEXT
  5074.  
  5075.    Output
  5076.  
  5077.    *************
  5078.    *************
  5079.    *************
  5080.    ***********
  5081.  
  5082.  
  5083.  3.4  Working with Data Files
  5084.  
  5085.    Data files are physical locations on your disk where information is
  5086.    permanently stored. The following three tasks are greatly simplified by
  5087.    using data files in your BASIC programs:
  5088.  
  5089.    1. Creating, manipulating, and storing large amounts of data
  5090.  
  5091.    2. Accessing several sets of data with one program
  5092.  
  5093.    3. Using the same set of data in several different programs
  5094.  
  5095.    The sections that follow introduce the concepts of records and fields and
  5096.    contrast different ways to access data files from BASIC. When you have
  5097.    completed Sections 3.4.1-3.4.7, you should know how to do the following:
  5098.  
  5099.    ■ Create new data files
  5100.  
  5101.    ■ Open existing files and read their contents
  5102.  
  5103.    ■ Add new information to an existing data file
  5104.  
  5105.    ■ Change the contents of an existing data file
  5106.  
  5107.  3.4.1  How Data Files Are Organized
  5108.  
  5109.    A data file is a collection of related blocks of information, or
  5110.    "records." Each record in a data file is further subdivided into "fields"
  5111.    or regularly recurring items of information within each record. If you
  5112.    compare a data file with a more old-fashioned way of storing information──
  5113.    for example, a folder containing application forms filled out by job
  5114.    applicants at a particular company──then a record is analogous to one
  5115.    application form in that folder. To carry the comparison one step further,
  5116.    a field is analogous to an item of information included on every
  5117.    application form, such as a Social Security number.
  5118.  
  5119.    ──────────────────────────────────────────────────────────────────────────
  5120.    NOTE
  5121.      If you do not want to access a file using records but instead want to
  5122.      treat it as an unformatted sequence of bytes, then read Section 3.4.7,
  5123.      "Binary File I/O."
  5124.    ──────────────────────────────────────────────────────────────────────────
  5125.  
  5126.  3.4.2  Sequential and Random-Access Files
  5127.  
  5128.    The terms "sequential file" and "random-access file" refer to two
  5129.    different ways to store and access data on disk from your BASIC programs.
  5130.    A simplified way to think of these two kinds of files is with the
  5131.    following analogy: a sequential file is like a cassette tape, while a
  5132.    random-access file is like an LP record. To find a song on a cassette
  5133.    tape, you have to start at the beginning and fast-forward through the tape
  5134.    sequentially until you find the song you are looking for──there is no way
  5135.    to jump right to the song you want. This is similar to the way you have to
  5136.    find information in a sequential file: to get to the 500th record, you
  5137.    first have to read records 1 through 499.
  5138.  
  5139.    In contrast, if you want to play a certain song on an LP, all you have to
  5140.    do is lift the tone arm of the record player and put the needle down right
  5141.    on the song: you can randomly access anything on the LP without having to
  5142.    play all the songs before the one you want. Similarly, you can call up any
  5143.    record in a random-access file just by specifying its number, greatly
  5144.    reducing access time.
  5145.  
  5146.    ──────────────────────────────────────────────────────────────────────────
  5147.    NOTE
  5148.      Although there is no way to jump directly to a specific record in a
  5149.      sequential file, the SEEK statement lets you jump directly to a specific
  5150.      byte in the file (to "fast forward" or "rewind" the tape, to extend the
  5151.      preceding analogy). See Section 3.4.7, "Binary File I/O," for more
  5152.      information on how to do this.
  5153.    ──────────────────────────────────────────────────────────────────────────
  5154.  
  5155.  3.4.3  Opening a Data File
  5156.  
  5157.    Before your program can read, modify, or add to a data file, it must first
  5158.    open the file. BASIC does this with the OPEN statement. The OPEN statement
  5159.    can be used to create a new file. The following list describes the various
  5160.    uses of the OPEN statement:
  5161.  
  5162.    ■ Create a new data file and open it so records can be added to it
  5163.  
  5164.      ' No file named PRICE.DAT is in the current directory:
  5165.      OPEN "Price.Dat" FOR OUTPUT AS #1
  5166.  
  5167.    ■ Open an existing data file so new records overwrite any data already in
  5168.      the file
  5169.  
  5170.      ' A file named PRICE.DAT is already in the current
  5171.      ' directory; new records can be written to it, but all
  5172.      ' old records are lost:
  5173.      OPEN "Price.Dat" FOR OUTPUT AS #1
  5174.  
  5175.    ■ Open an existing data file so new records are added to the end of the
  5176.      file, preserving data already in the file
  5177.  
  5178.      OPEN "Price.Dat" FOR APPEND AS #1
  5179.  
  5180.      The APPEND mode will also create a new file if a file with the given
  5181.      name does not already appear in the current directory.
  5182.  
  5183.    ■ Open an existing data file so old records can be read from it
  5184.  
  5185.      OPEN "Price.Dat" FOR INPUT AS #1
  5186.  
  5187.      See Section 3.4.5, "Using Sequential Files," for more information about
  5188.      the INPUT, OUTPUT, and APPEND modes.
  5189.  
  5190.    ■ Open an existing data file (or create a new one if a file with that name
  5191.      doesn't exist), then read or write fixed-length records to and from the
  5192.      file
  5193.  
  5194.      OPEN "Price.Dat" FOR RANDOM AS #1
  5195.  
  5196.      See Section 3.4.6, "Using Random-Access Files," for more information
  5197.      about this mode.
  5198.  
  5199.    ■ Open an existing data file (or create a new one if a file with that name
  5200.      doesn't exist), then read data from the file or add new data to the
  5201.      file, starting at any byte position in the file
  5202.  
  5203.      OPEN "Price.Dat" FOR BINARY AS #1
  5204.  
  5205.      See Section 3.4.7, "Binary File I/O," for more information about this
  5206.      mode.
  5207.  
  5208.      3.4.3.1  File Numbers in BASIC
  5209.  
  5210.    The OPEN statement does more than just specify a mode for data I/O for a
  5211.    particular file (OUTPUT, INPUT, APPEND, RANDOM, or BINARY); it also
  5212.    associates a unique file number with that file. This file number, which
  5213.    can be any integer from 1 to 255, is then used by subsequent file I/O
  5214.    statements in the program as a shorthand way to refer to the file. As long
  5215.    as the file is open, this number remains associated with the file. When
  5216.    the file is closed, the file number is freed for use with another file.
  5217.    (See Section 3.4.4 for information on how files are closed.) Your BASIC
  5218.    programs can open more than one file at a time.
  5219.  
  5220.    The FREEFILE function can help you find an unused file number. This
  5221.    function returns the next available number that can be associated with a
  5222.    file in an OPEN statement. For example, FREEFILE might return the value 3
  5223.    after the following OPEN statements:
  5224.  
  5225.    OPEN "Test1.Dat" FOR RANDOM AS #1
  5226.    OPEN "Test2.Dat" FOR RANDOM AS #2
  5227.    FileNum = FREEFILE
  5228.    OPEN "Test3.Dat" FOR RANDOM AS #FileNum
  5229.  
  5230.    The FREEFILE function is particularly useful when you create your own
  5231.    library procedures that open files. With FREEFILE, you don't have to pass
  5232.    information about the number of open files to these procedures.
  5233.  
  5234.    3.4.3.2  File Names in BASIC
  5235.  
  5236.    File names in OPEN statements can be any string expression, composed of
  5237.    any combination of the following characters:
  5238.  
  5239.    ■ The letters a-z and A-Z
  5240.  
  5241.    ■ The numbers 0-9
  5242.  
  5243.    ■ The following special characters:
  5244.  
  5245.      ( ) { } @ # $ % ^ & ! - _ ' ~
  5246.  
  5247.    The string expression can also contain an optional drive specification, as
  5248.    well as a complete or partial path specification. This means your BASIC
  5249.    program can work with data files on another drive or in a directory other
  5250.    than the one where the program is running. For example, the following OPEN
  5251.    statements are all valid:
  5252.  
  5253.    OPEN "..\Grades.Qtr" FOR INPUT AS #1
  5254.  
  5255.    OPEN "a:\salaries\1987.man" FOR INPUT AS #2
  5256.  
  5257.    FileName$ = "TempFile"
  5258.    OPEN FileName$ FOR OUTPUT AS #3
  5259.  
  5260.    BaseName$ = "Invent"
  5261.    OPEN BaseName$ + ".DAT" FOR OUTPUT AS #4
  5262.  
  5263.    DOS also imposes its own restrictions on file names: you can use no more
  5264.    than eight characters for the base name (everything to the left of an
  5265.    optional period) and no more than three characters for the extension
  5266.    (everything to the right of an optional period). Long file names in BASIC
  5267.    programs are truncated in the following fashion:
  5268.  
  5269.    File Name in Program     Resulting File Name in DOS
  5270.    ──────────────────────────────────────────────────────────────────────────
  5271.    Prog@Data@File           PROG@DAT.A@F
  5272.                             The BASIC name is more than 11 characters long,
  5273.                             so BASIC takes the first 8 letters for the base
  5274.                             name, inserts a period (.), and uses the next 3
  5275.                             letters as the extension. Everything else is
  5276.                             discarded.
  5277.  
  5278.    Mail#.Version1           MAIL#.VER
  5279.                             The base name (Mail#) is shorter than eight
  5280.                             characters, but the extension (Version1) is
  5281.                             longer than three, so the extension is shortened
  5282.                             to three characters.
  5283.  
  5284.    RELEASE_NOTES.BAK        Gives the run-time error message Bad file name.
  5285.                             The base name must be shorter than eight
  5286.                             characters if you are going to include an
  5287.                             explicit extension (.BAK in this case).
  5288.    ──────────────────────────────────────────────────────────────────────────
  5289.  
  5290.    DOS is not case sensitive, so lowercase letters in file names are
  5291.    converted to all uppercase (capital) letters. Therefore, you should not
  5292.    rely on the mixing of lowercase and uppercase to distinguish between
  5293.    files. For example, if you already had a file on the disk named
  5294.    INVESTOR.DAT, the following OPEN statement would overwrite that file,
  5295.    destroying any information already stored in it:
  5296.  
  5297.    OPEN "Investor.Dat" FOR OUTPUT AS #1
  5298.  
  5299.  3.4.4  Closing a Data File
  5300.  
  5301.    Closing a data file has two important results: first, it writes any data
  5302.    currently in the file's buffer (a temporary holding area in memory) to the
  5303.    file; second, it frees the file number associated with that file for use
  5304.    by another OPEN statement.
  5305.  
  5306.    Use the CLOSE statement within a program to close a file. For example, if
  5307.    the file Price.Dat is opened with the statement
  5308.  
  5309.    OPEN "Price.Dat" FOR OUTPUT AS #1
  5310.  
  5311.    then the statement CLOSE #1 ends output to Price.Dat. If Price.Dat is
  5312.    opened with
  5313.  
  5314.    OPEN "Price.Dat" FOR OUTPUT AS #2
  5315.  
  5316.    then the appropriate statement for ending output is CLOSE #2. A CLOSE
  5317.    statement with no file-number arguments closes all open files.
  5318.  
  5319.    A data file is also closed when either of the following occurs:
  5320.  
  5321.    ■ The BASIC program performing I/O ends (program termination always closes
  5322.      all open data files).
  5323.  
  5324.    ■ The program performing I/O transfers control to another program with the
  5325.      RUN statement.
  5326.  
  5327.  3.4.5  Using Sequential Files
  5328.  
  5329.    This section discusses how records are organized in sequential data files
  5330.    and then shows how to read data from, or write data to, an open sequential
  5331.    file.
  5332.  
  5333.    3.4.5.1  Records in Sequential Files
  5334.  
  5335.    Sequential files are ASCII (text) files. This means you can use any word
  5336.    processor to view or modify a sequential file. Records are stored in
  5337.    sequential files as a single line of text, terminated by a carriage-return
  5338.    and line-feed (CR-LF) sequence. Each record is divided into fields, or
  5339.    repeated chunks of data that occur in the same order in every record.
  5340.    Figure 3.2 shows how three records might appear in a sequential file.
  5341.  
  5342.  
  5343.    ┌──────────────────────────────────────────────────────────────────┐
  5344.    │  Record 1                                                        │
  5345.    │  ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐                     │
  5346.    │  │"│M│c│G│u│i│r│e│"│,│"│M│a│n│a│g│e│r│"│,│5│                     │
  5347.    │  └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴───┘                     │
  5348.    │  └────────┬────────┘ └────────┬────────┘ └┬┘                     │
  5349.    │        Field 1             Field 2     Field 3                   │
  5350.    │                                                                  │
  5351.    │  Record 2                                                        │
  5352.    │  ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐                             │
  5353.    │  │"│R│o│s│s│"│,│"│E│d│i│t│o│r│"│,│7│                             │
  5354.    │  └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘                             │
  5355.    │  └─────┬─────┘ └───────┬───────┘ └┬┘                             │
  5356.    │     Field 1         Field 2     Field 3                          │
  5357.    │                                                                  │
  5358.    │  Record 3                                                        │
  5359.    │  ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐           │
  5360.    │  │"│S│h│o│s│t│a│k│o│v│i│c│h│"│,│"│W│r│i│t│e│r│"│,│1│2│           │
  5361.    │  └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘           │
  5362.    │  └─────────────┬─────────────┘ └───────┬───────┘ └─┬─┘           │
  5363.    │             Field 1                 Field 2     Field 3          │
  5364.    └──────────────────────────────────────────────────────────────────┘
  5365.  
  5366.    Figure 3.2  Records in Sequential Files
  5367.  
  5368.    Note that each record in a sequential file can be a different length;
  5369.    moreover, fields can be different lengths in different records.
  5370.  
  5371.    The kind of variable in which a field is stored determines where that
  5372.    field begins and ends. (See Sections 3.4.5.2-3.4.5.6 for examples of
  5373.    reading and storing fields from records.) For example, if your program
  5374.    reads a field into a string variable, then any of the following can signal
  5375.    the end of that field:
  5376.  
  5377.    ■ Double quotes (") if the string begins with double quotes
  5378.  
  5379.    ■ Comma (,) if the string does not begin with double quotes
  5380.  
  5381.    ■ CR-LF if the field is at the end of the record
  5382.  
  5383.    On the other hand, if your program reads a field into a numeric variable,
  5384.    then any of the following can signal the end of that field:
  5385.  
  5386.    ■ Comma
  5387.  
  5388.    ■ One or more spaces
  5389.  
  5390.    ■ CR-LF
  5391.  
  5392.      3.4.5.2  Putting Data in a New Sequential File
  5393.  
  5394.    You can add data to a new sequential file after first opening it to
  5395.    receive records with an OPEN filename FOR OUTPUT statement. Use the WRITE
  5396.    # statement to write records to the file.
  5397.  
  5398.    You can open sequential files for reading or for writing but not for both
  5399.    at the same time. If you are writing to a sequential file and want to read
  5400.    back the data you stored, you must first close the file, then reopen it
  5401.    for input.
  5402.  
  5403.    Example
  5404.  
  5405.    The following short program creates a sequential file named Price.Dat,
  5406.    then adds data entered at the keyboard to the file. The OPEN statement in
  5407.    this program both creates the file and readies it to receive records. The
  5408.    WRITE # then writes each record to the file. Note that the number used in
  5409.    the WRITE # statement is the same number given to the file name Price.Dat
  5410.    in the OPEN statement.
  5411.  
  5412.    ' Create a file named Price.Dat
  5413.    ' and open it to receive new data:
  5414.  
  5415.    OPEN "Price.Dat" FOR OUTPUT AS #1
  5416.  
  5417.    DO
  5418.       ' Continue putting new records in Price.Dat until the
  5419.       ' user presses ENTER without entering a company name:
  5420.       INPUT "Company (press <ENTER> to quit): ", Company$
  5421.  
  5422.       IF Company$ <> "" THEN
  5423.  
  5424.          ' Enter the other fields of the record:
  5425.          INPUT "Style: ", Style$
  5426.          INPUT "Size: ", Size$
  5427.          INPUT "Color: ", Clr$
  5428.          INPUT "Quantity: ", Qty
  5429.  
  5430.          ' Put the new record in the file
  5431.          ' with the WRITE # statement:
  5432.          WRITE #1, Company$, Style$, Size$, Clr$, Qty
  5433.       END IF
  5434.    LOOP UNTIL Company$ = ""
  5435.  
  5436.    ' Close Price.Dat (this ends output to the file):
  5437.    CLOSE #1
  5438.    END
  5439.  
  5440.    ──────────────────────────────────────────────────────────────────────────
  5441.    WARNING
  5442.      If, in the preceding example, you already had a file named Price.Dat on
  5443.      the disk, the OUTPUT mode given in the OPEN statement would erase the
  5444.      existing contents of Price.Dat before writing any new data to it. If you
  5445.      want to add new data to the end of an existing file without erasing what
  5446.      is already in it, use the APPEND mode of OPEN. See Section 3.4.5.4,
  5447.      "Adding Data to a Sequential File," for more information on this mode.
  5448.    ──────────────────────────────────────────────────────────────────────────
  5449.  
  5450.    3.4.5.3  Reading Data from a Sequential File
  5451.  
  5452.    You can read data from a sequential file after first opening it with the
  5453.    statement OPEN filename FOR INPUT. Use the INPUT # statement to read
  5454.    records from the file one field at a time. (See Section 3.4.5.6, "Other
  5455.    Ways to Read Data from a Sequential File," for information on other
  5456.    file-input statements and functions you can use with a sequential file.)
  5457.  
  5458.    Example
  5459.  
  5460.    The following program opens the Price.Dat data file created in the
  5461.    previous example and reads the records from the file, displaying the
  5462.    complete record on the screen if the quantity for the item is less than
  5463.    the input amount.
  5464.  
  5465.    The INPUT #1 statement reads one record at a time from Price.Dat,
  5466.    assigning the fields in the record to the variables Company$, Style$,
  5467.    Size$, Clr$, and Qty. Since this is a sequential file, the records are
  5468.    read in order from the first one entered to the last one entered.
  5469.  
  5470.    The EOF (end-of-file) function tests whether the last record has been read
  5471.    by INPUT #. If the last record has been read, EOF returns the value -1
  5472.    (true), and the loop for getting data ends; if the last record has not
  5473.    been read, EOF returns the value 0 (false), and the next record is read
  5474.    from the file.
  5475.  
  5476.    OPEN "Price.Dat" FOR INPUT AS #1
  5477.  
  5478.    INPUT "Display all items below what level"; Reorder
  5479.  
  5480.    DO UNTIL EOF(1)
  5481.       INPUT #1, Company$, Style$, Size$, Clr$, Qty
  5482.       IF Qty < Reorder THEN
  5483.          PRINT  Company$, Style$, Size$, Clr$, Qty
  5484.       END IF
  5485.    LOOP
  5486.    CLOSE #1
  5487.    END
  5488.  
  5489.    3.4.5.4  Adding Data to a Sequential File
  5490.  
  5491.    As mentioned earlier, if you have a sequential file on disk and want to
  5492.    add more data to the end of it, you cannot simply open the file in output
  5493.    mode and start writing data. As soon as you open a sequential file in
  5494.    output mode, you destroy its current contents. You must use the append
  5495.    mode instead, as shown in the next example:
  5496.  
  5497.    OPEN "Price.Dat" FOR APPEND AS #1
  5498.  
  5499.    In fact, APPEND is always a safe alternative to OUTPUT, since the append
  5500.    mode creates a new file if one with the name specified doesn't already
  5501.    exist. For example, if a file named Price.Dat did not reside on disk, the
  5502.    example statement above would make a new file with that name.
  5503.  
  5504.    3.4.5.5  Other Ways to Write Data to a Sequential File
  5505.  
  5506.    The preceding examples all use the WRITE # statement to write records to a
  5507.    sequential file. There is, however, another statement you can use to write
  5508.    sequential file records: PRINT #.
  5509.  
  5510.    The best way to show the difference between these two data-storage
  5511.    statements is to examine the contents of a file created with both. The
  5512.    following short fragment opens a file named Test.Dat then places the same
  5513.    record in it twice, once with WRITE # and once with PRINT #. After running
  5514.    this program you can examine the contents of Test.Dat with the DOS TYPE
  5515.    commands:
  5516.  
  5517.    OPEN "Test.Dat" FOR OUTPUT AS #1
  5518.    Nm$ = "Penn, Will"
  5519.    Dept$ = "User Education"
  5520.    Level = 4
  5521.    Age = 25
  5522.    WRITE #1, Nm$, Dept$, Level, Age
  5523.    PRINT #1, Nm$, Dept$, Level, Age
  5524.    CLOSE #1
  5525.  
  5526.    Output
  5527.  
  5528.    "Penn, Will","User Education",4,25
  5529.    Penn, Will    User Education               4             25
  5530.  
  5531.    The record stored with WRITE # has commas that explicitly separate each
  5532.    field of the record, as well as quotes enclosing each string expression.
  5533.    On the other hand, PRINT # has written an image of the record to the file
  5534.    exactly as it would appear on screen with a simple PRINT statement. The
  5535.    commas in the PRINT # statement are interpreted as meaning "advance to the
  5536.    next print zone" (a new print zone occurs every 14 spaces, starting at the
  5537.    beginning of a line), and quotes are not placed around the string
  5538.    expressions.
  5539.  
  5540.    At this point, you may be wondering what difference these output
  5541.    statements make, except in the appearance of the data within the file. The
  5542.    answer lies in what happens when your program reads the data back from the
  5543.    file with an INPUT # statement. In the following example, the program
  5544.    reads the record stored with WRITE # and prints the values of its fields
  5545.    without any problem:
  5546.  
  5547.    OPEN "Test.Dat" FOR INPUT AS #1
  5548.  
  5549.    ' Input the first record,
  5550.    ' and display the contents of each field:
  5551.    INPUT #1, Nm$, Dept$, Level, Age
  5552.    PRINT Nm$, Dept$, Level, Age
  5553.  
  5554.    ' Input the second record,
  5555.    ' and display the contents of each field:
  5556.    INPUT #1, Nm$, Dept$, Level, Age
  5557.    PRINT Nm$, Dept$, Level, Age
  5558.  
  5559.    CLOSE #1
  5560.  
  5561.    Output
  5562.  
  5563.    Penn, Will    User Education               4             25
  5564.  
  5565.    However, when the program tries to input the next record stored with PRINT
  5566.    #, it produces the error message Input past end of file. Without double
  5567.    quotes enclosing the first field, the INPUT # statement sees the comma
  5568.    between Penn and Will as a field delimiter, so it assigns only the last
  5569.    name Penn to the variable Nm$. INPUT # then reads the rest of the line
  5570.    into the variable Dept$. Since all of the record has now been read, there
  5571.    is nothing left to put in the variables level and age. The result is the
  5572.    error message Input past end of file.
  5573.  
  5574.    If you are storing records that have string expressions and you want to
  5575.    read these records later with the INPUT # statement, follow one of these
  5576.    two rules of thumb:
  5577.  
  5578.    1. Use the WRITE # statement to store the records.
  5579.  
  5580.    2. If you want to use the PRINT # statement, remember it does not put
  5581.       commas in the record to separate fields, nor does it put quotes around
  5582.       strings. You have to put these field separators in the PRINT #
  5583.       statement yourself.
  5584.  
  5585.    For example, you can avoid the problems shown in the preceding example by
  5586.    using PRINT # with quotation marks surrounding each field containing a
  5587.    string expression, as in the example below.
  5588.  
  5589.    Example
  5590.  
  5591.    ' 34 is ASCII value for double-quote character:
  5592.  
  5593.    Q$ = CHR$(34)
  5594.  
  5595.    ' The next four statements all write the record to the
  5596.    ' file with double quotes around each string field:
  5597.  
  5598.    PRINT #1, Q$ Nm$ Q$ Q$ Dept$ Q$ Level Age
  5599.    PRINT #1, Q$ Nm$ Q$;Q$ Dept$ Q$;Level;Age
  5600.    PRINT #1, Q$ Nm$ Q$,Q$ Dept$ Q$,Level,Age
  5601.    WRITE #1, Nm$, Dept$, Level, Age
  5602.  
  5603.    Output to File
  5604.  
  5605.    "Penn, Will""User Education" 4  25
  5606.    "Penn, Will""User Education" 4  25
  5607.    "Penn, Will"  "User Education"      4             25
  5608.    "Penn, Will","User Education",4,25
  5609.  
  5610.    3.4.5.6  Other Ways to Read Data from a Sequential File
  5611.  
  5612.    In the preceding sections, INPUT # is used to read a record (one line of
  5613.    data from a file), assigning different fields in the record to the
  5614.    variables listed after INPUT #. This section explores alternative ways to
  5615.    read data from sequential files, both as records (LINE INPUT #) and as
  5616.    unformatted sequences of bytes (INPUT$).
  5617.  
  5618.  The LINE INPUT # Statement
  5619.  
  5620.    With the LINE INPUT # statement, your program can read a line of text
  5621.    exactly as it appears in a file without interpreting commas or quotes as
  5622.    field delimiters. This is particularly useful in programs that work with
  5623.    ASCII text files.
  5624.  
  5625.    The LINE INPUT # statement reads an entire line from a sequential file (up
  5626.    to a carriage-return and line-feed sequence) into a single string
  5627.    variable.
  5628.  
  5629.    Examples
  5630.  
  5631.    The following short program reads each line from the file Chap1.Txt and
  5632.    then echoes that line to the screen:
  5633.  
  5634.    ' Open Chap1.Txt for sequential input:
  5635.    OPEN "Chap1.Txt" FOR INPUT AS #1
  5636.  
  5637.    ' Keep reading lines sequentially from the file until
  5638.    ' there are none left in the file:
  5639.  
  5640.    DO UNTIL EOF(1)
  5641.  
  5642.       ' Read a line from the file and store it
  5643.       ' in the variable LineBuffer$:
  5644.       LINE INPUT #1, LineBuffer$
  5645.  
  5646.       ' Print the line on the screen:
  5647.       PRINT LineBuffer$
  5648.    LOOP
  5649.  
  5650.    The preceding program is easily modified to a file-copying utility that
  5651.    prints each line read from the specified input file to another file,
  5652.    instead of to the screen:
  5653.  
  5654.    ' Input names of input and output files:
  5655.  
  5656.    INPUT "File to copy: ", FileName1$
  5657.    IF FileName1$ = "" THEN END
  5658.    INPUT "Name of new file: ", FileName2$
  5659.    IF FileName2$ = "" THEN END
  5660.  
  5661.    ' Open first file for sequential input:
  5662.    OPEN FileName1$ FOR INPUT AS #1
  5663.  
  5664.    ' Open second file for sequential output:
  5665.    OPEN FileName2$ FOR OUTPUT AS #2
  5666.  
  5667.    ' Keep reading lines sequentially from first file
  5668.    ' until there are none left in the file:
  5669.    DO UNTIL EOF(1)
  5670.  
  5671.       ' Read a line from first file and store it in the
  5672.       ' variable LineBuffer$:
  5673.       LINE INPUT #1, LineBuffer$
  5674.  
  5675.       ' Write LineBuffer$ to the second file:
  5676.       PRINT #2, LineBuffer$
  5677.  
  5678.    LOOP
  5679.  
  5680.  The INPUT$ Function
  5681.  
  5682.    Yet another way to read data from sequential files (and, in fact, from any
  5683.    file) is to use the INPUT$ function. Whereas INPUT # and LINE INPUT # read
  5684.    a line at a time from a sequential file, INPUT$ reads a specified number
  5685.    of characters from a file, as shown in the following examples:
  5686.  
  5687.    Statement                Action
  5688.    ──────────────────────────────────────────────────────────────────────────
  5689.    X$ = INPUT$(100, #1)     Reads 100 characters from file number 1 and
  5690.                             assigns all of them to the string variable X$
  5691.  
  5692.    Test$ = INPUT$(1, #2)    Reads one character from file number 2 and
  5693.                             assigns it to the string variable Test$
  5694.  
  5695.    ──────────────────────────────────────────────────────────────────────────
  5696.  
  5697.    The INPUT$ function without a file number always reads input from standard
  5698.    input (usually the keyboard).
  5699.  
  5700.    The INPUT$ function does what is known as "binary input"; that is, it
  5701.    reads a file as an unformatted stream of characters. For example, it does
  5702.    not see a carriage-return and line-feed sequence as signaling the end of
  5703.    an input operation. Therefore, INPUT$ is the best choice when you want
  5704.    your program to read every single character from a file or when you want
  5705.    it to read a binary, or non-ASCII, file.
  5706.  
  5707.    Example
  5708.  
  5709.    The following program copies the named binary file to the screen, printing
  5710.    only alphanumeric and punctuation characters in the ASCII range 32 to 126,
  5711.    as well as tabs, carriage returns, and line feeds:
  5712.  
  5713.    ' 9 is ASCII value for horizontal tab, 10 is ASCII
  5714.    value
  5715.    ' for line feed, and 13 is ASCII value for carriage return:
  5716.    CONST LINEFEED = 10, CARRETURN = 13, TABCHAR = 9
  5717.  
  5718.    INPUT "Print which file: ", FileName$
  5719.    IF FileName$ = "" THEN END
  5720.  
  5721.    OPEN FileName$ FOR INPUT AS #1
  5722.  
  5723.    DO UNTIL EOF(1)
  5724.       Character$ = INPUT$(1, #1)
  5725.       CharVal = ASC(Character$)
  5726.       SELECT CASE CharVal
  5727.          CASE 32 TO 126
  5728.             PRINT Character$;
  5729.          CASE TABCHAR, CARRETURN
  5730.             PRINT Character$;
  5731.          CASE LINEFEED
  5732.             IF OldCharVal <> CARRETURN THEN PRINT Character$;
  5733.          CASE ELSE
  5734.             ' This is not one of the characters this program
  5735.             ' is interested in, so don't print anything.
  5736.       END SELECT
  5737.       OldCharVal = CharVal
  5738.    LOOP
  5739.  
  5740.  3.4.6  Using Random-Access Files
  5741.  
  5742.    This section discusses how records are organized in random-access data
  5743.    files, then shows you how to read data from and write data to a file
  5744.    opened for random access.
  5745.  
  5746.    3.4.6.1  Records in Random-Access Files
  5747.  
  5748.    Random-access records are stored quite differently from sequential
  5749.    records. Each random-access record is defined with a fixed length, as is
  5750.    each field within the record. These fixed lengths determine where a record
  5751.    or field begins and ends, as there are no commas separating fields, and no
  5752.    carriage-return and line-feed sequences between records. Figure 3.3 shows
  5753.    how three records might appear in a random-access file.
  5754.  
  5755.  
  5756.                   Record 1                               Record 2
  5757.    ┌──────────────────┴──────────────────┐┌─────────────────┴─────────────────
  5758.    ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬
  5759.    │M│c│G│u│i│r│e│ │ │ │M│a│n│a│g│e│r│5│ │R│o│s│s│ │ │ │ │ │ │E│d│i│t│o│r│ │3│
  5760.    └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴
  5761.    └─────────┬─────────┘└─────┬──────┘└─┬┘└────────┬─────────┘└─────┬──────┘└─
  5762.           Field 1          Field 2   Field 3     Field 1         Field 2   Fie
  5763.  
  5764.    Figure 3.3  Records in a Random-Access File
  5765.  
  5766.    If you are storing records containing numbers, using random-access files
  5767.    saves disk space when compared with using sequential files. This is
  5768.    because sequential files save numbers as a sequence of ASCII characters
  5769.    representing each digit, whereas random-access files save numbers in a
  5770.    compressed binary format.
  5771.  
  5772.    For example, the number 17,000 is represented in a sequential file using
  5773.    five bytes, one for each digit. However, if 17,000 is stored in an integer
  5774.    field of a random-access record, it takes only two bytes of disk space.
  5775.  
  5776.    In general, integers in random-access files take two bytes, long integers
  5777.    and single-precision numbers take four bytes, and double-precision numbers
  5778.    take eight bytes.
  5779.  
  5780.    3.4.6.2  Adding Data to a Random-Access File
  5781.  
  5782.    To write a program that adds data to a random-access file, follow these
  5783.    steps:
  5784.  
  5785.    1. Define the fields of each record.
  5786.  
  5787.    2. Open the file in random-access mode and specify the length of each
  5788.       record.
  5789.  
  5790.    3. Get input for a new record and store the record in the file.
  5791.  
  5792.    Each of these steps is now considerably easier than it was in BASICA, as
  5793.    you can see from the examples that follow.
  5794.  
  5795.  Defining Fields
  5796.  
  5797.    You can define your own record with a TYPE...END TYPE statement, which
  5798.    allows you to create a composite data type that mixes string and numeric
  5799.    elements. This is a big advantage over the earlier method of setting up
  5800.    records with a FIELD statement, which required that each field be defined
  5801.    as a string. By defining a record with TYPE...END TYPE, you eliminate the
  5802.    need to use the functions that convert numeric data to strings (MKtype$,
  5803.    MKSMBF$, and MKDMBF$) and strings to numeric data (CVtype, CVSMBF, and
  5804.    CVDMBF).
  5805.  
  5806.    The following fragments contrast these two methods of defining records:
  5807.  
  5808.    ■ Record defined with TYPE...END TYPE
  5809.  
  5810.      ' Define the RecordType structure:
  5811.      TYPE RecordType
  5812.         Name AS STRING * 30
  5813.         Age AS INTEGER
  5814.         Salary AS SINGLE
  5815.      END TYPE
  5816.  
  5817.      ' Declare the variable RecordVar
  5818.      ' as having the type RecordType:
  5819.      DIM RecordVar AS RecordType
  5820.  
  5821.      .
  5822.      .
  5823.      .
  5824.  
  5825.    ■ Record defined with FIELD
  5826.  
  5827.      ' Define the lengths of the fields
  5828.      ' in the temporary storage buffer:
  5829.      FIELD #1,30 AS Name$,2 AS Age$,4 AS Salary$
  5830.      .
  5831.      .
  5832.      .
  5833.  
  5834.  Opening the File and Specifying Record Length
  5835.  
  5836.    Since the length of a random-access record is fixed, you should let your
  5837.    program know how long you want each record to be; otherwise, record length
  5838.    defaults to 128 bytes.
  5839.  
  5840.    To specify record length, use the LEN = clause in the OPEN statement. The
  5841.    next two fragments, which continue the contrasting examples started above,
  5842.    show how to use LEN =.
  5843.  
  5844.    ■ Specifying the record length for a record that is defined with the
  5845.      statement TYPE...END TYPE
  5846.  
  5847.      .
  5848.      .
  5849.      .
  5850.      ' Open the random-access file and specify the length
  5851.      ' of one record as being equal to the length of the
  5852.      ' RecordVar variable:
  5853.      OPEN "EMPLOYEE.DAT" FOR RANDOM AS #1 LEN = LEN(RecordVar)
  5854.      .
  5855.      .
  5856.      .
  5857.  
  5858.    ■ Specifying record length for a record defined with FIELD
  5859.  
  5860.      .
  5861.      .
  5862.      .
  5863.      ' Open the random-access file and specify the length
  5864.      ' of a record:
  5865.      OPEN "EMPLOYEE.DAT" FOR RANDOM AS #1 LEN = 31
  5866.      .
  5867.      .
  5868.      .
  5869.  
  5870.    As you can see, when you use FIELD, you have to add the lengths of each
  5871.    field yourself (FirstName$ is 10 bytes, LastName$ is 15 bytes, Age$ is 2
  5872.    bytes, Salary$ is 4 bytes, so the record is 10+15+2+4 or 31 bytes long).
  5873.    With TYPE...END TYPE, you no longer have to do these calculations.
  5874.    Instead, just use the LEN function to calculate the length of the variable
  5875.    you have created to hold your records (RecordVar, in this case).
  5876.  
  5877.  Inputting Data and Storing the Record
  5878.  
  5879.    You can input data directly into the elements of a user-defined record
  5880.    without having to worry about left- or right-justification of input within
  5881.    a field with LSET or RSET. Compare the following two fragments, which
  5882.    continue the examples started above, to see the amount of code this
  5883.    approach saves you.
  5884.  
  5885.    ■ Entering data for a random-access record and storing the record using
  5886.      TYPE...END TYPE.
  5887.  
  5888.      .
  5889.      .
  5890.      .
  5891.  
  5892.      ' Enter the data:
  5893.      INPUT "First name"; RecordVar.FirstName
  5894.      INPUT "Last name"; RecordVar.LastName
  5895.      INPUT "Age"; RecordVar.Age
  5896.      INPUT "Salary"; RecordVar.Salary
  5897.      ' Store the record:
  5898.      PUT #1, , RecordVar
  5899.  
  5900.      .
  5901.      .
  5902.      .
  5903.  
  5904.    ■ Entering data for a random-access record and storing the record using
  5905.      FIELD
  5906.  
  5907.      .
  5908.      .
  5909.      .
  5910.  
  5911.      ' Enter the data:
  5912.      INPUT "First name"; FirstNm$
  5913.      INPUT "Last name"; LastNm$
  5914.      INPUT "Age"; AgeVal%
  5915.      INPUT "Salary"; SalaryVal!
  5916.  
  5917.      ' Left justify the data in the storage-buffer fields,
  5918.      ' using the MKI$ and MKS$ functions to convert numbers
  5919.      ' to file strings:
  5920.      LSET FirstName$ = FirstNm$
  5921.      LSET LastName$ = LastNm$
  5922.      LSET Age$ = MKI$(AgeVal%)
  5923.      LSET Salary$ = MKS$(SalaryVal!)
  5924.  
  5925.      ' Store the record:
  5926.      PUT #1
  5927.  
  5928.      .
  5929.      .
  5930.      .
  5931.  
  5932.  Putting It All Together
  5933.  
  5934.    The following program puts together all the steps outlined above──defining
  5935.    fields, specifying record length, inputting data, and storing the input
  5936.    data──to open a random-access data file named STOCK.DAT and add records to
  5937.    it:
  5938.  
  5939.    DEFINT A-Z
  5940.  
  5941.    ' Define structure of a single record in the random-access
  5942.    ' file. Each record will consist of four fixed-length fields
  5943.    ' ("PartNumber", "Description", "UnitPrice", "Quantity"):
  5944.    TYPE StockItem
  5945.       PartNumber AS STRING *  6
  5946.       Description AS STRING * 20
  5947.       UnitPrice AS SINGLE
  5948.       Quantity AS INTEGER
  5949.    END TYPE
  5950.  
  5951.    ' Declare a variable (StockRecord) using the above type:
  5952.    DIM StockRecord AS StockItem
  5953.  
  5954.    ' Open the random-access file, specifying the length of one
  5955.    ' record as the length of the StockRecord variable:
  5956.    OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN=LEN(StockRecord)
  5957.  
  5958.    ' Use LOF() to calculate the number of records already in
  5959.    ' the file, so new records will be added after them:
  5960.    RecordNumber = LOF(1) \ LEN(StockRecord)
  5961.  
  5962.    ' Now, add new records:
  5963.    DO
  5964.  
  5965.       ' Input data for a stock record from keyboard and store
  5966.       ' in the different elements of the StockRecord variable:
  5967.       INPUT "Part Number? ", StockRecord.PartNumber
  5968.       INPUT "Description? ", StockRecord.Description
  5969.       INPUT "Unit Price ? ", StockRecord.UnitPrice
  5970.       INPUT "Quantity   ? ", StockRecord.Quantity
  5971.  
  5972.       RecordNumber = RecordNumber + 1
  5973.  
  5974.       ' Write data in StockRecord to a new record in the file:
  5975.       PUT #1, RecordNumber, StockRecord
  5976.  
  5977.  
  5978.  
  5979.       ' Check to see if more data are to be read:
  5980.       INPUT "More (Y/N)? ", Resp$
  5981.    LOOP UNTIL UCASE$(Resp$) = "N"
  5982.  
  5983.    ' All done; close the file and end:
  5984.    CLOSE  #1
  5985.    END
  5986.  
  5987.    If the STOCK.DAT file already existed, this program would add more records
  5988.    to the file without overwriting any that were already in the file. The
  5989.    following key statement makes this work:
  5990.  
  5991.    RecordNumber = LOF(1) \ LEN(StockRecord)
  5992.  
  5993.    Here is what happens:
  5994.  
  5995.    1. The LOF(1) function calculates the total number of bytes in the file
  5996.       STOCK.DAT. If STOCK.DAT is new or has no records in it, LOF(1) returns
  5997.       the value 0.
  5998.  
  5999.    2. The LEN(StockRecord) function calculates the number of bytes in one
  6000.       record. (StockRecord is defined as having the same structure as the
  6001.       user-defined type StockItem.)
  6002.  
  6003.    3. Therefore, the number of records is equal to the total bytes in the
  6004.       file divided by the bytes in one record.
  6005.  
  6006.    This is another advantage of having a fixed-length record. Since each
  6007.    record is the same size, you can always use the above formula to calculate
  6008.    the number of records in the file. Obviously, this would not work with a
  6009.    sequential file, since sequential records can have different lengths.
  6010.  
  6011.    3.4.6.7  Reading Data Sequentially
  6012.  
  6013.    Using the technique outlined in the preceding section for calculating the
  6014.    number of records in a random-access file, you can write a program that
  6015.    reads all the records in that file.
  6016.  
  6017.    Example
  6018.  
  6019.    The following program reads records sequentially (from the first record
  6020.    stored to the last) from the STOCK.DAT file created in the previous
  6021.    section:
  6022.  
  6023.    ' Define a record structure (type) for random-access
  6024.    ' file records:
  6025.    TYPE StockItem
  6026.       PartNumber AS STRING *  6
  6027.       Description AS STRING * 20
  6028.       UnitPrice AS SINGLE
  6029.       Quantity AS INTEGER
  6030.    END TYPE
  6031.  
  6032.    ' Declare a variable (StockRecord) using the above type:
  6033.    DIM StockRecord AS StockItem
  6034.  
  6035.    ' Open the random-access file:
  6036.    OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN = LEN(StockRecord)
  6037.  
  6038.    ' Calculate number of records in the file:
  6039.    NumberOfRecords = LOF(1) \ LEN(StockRecord)
  6040.  
  6041.    ' Read the records and write the data to the screen:
  6042.    FOR RecordNumber = 1 TO NumberOfRecords
  6043.  
  6044.       ' Read the data from a new record in the file:
  6045.       GET #1, RecordNumber, StockRecord
  6046.  
  6047.  
  6048.  
  6049.       ' Print the data to the screen:
  6050.       PRINT "Part Number: ", StockRecord.PartNumber
  6051.       PRINT "Description: ", StockRecord.Description
  6052.       PRINT "Unit Price : ", StockRecord.UnitPrice
  6053.       PRINT "Quantity   : ", StockRecord.Quantity
  6054.  
  6055.    NEXT
  6056.  
  6057.    ' All done; close the file and end:
  6058.    CLOSE #1
  6059.    END
  6060.  
  6061.    It is not necessary to close STOCK.DAT before reading from it. Opening a
  6062.    file for random access lets you write to or read from the file with a
  6063.    single OPEN statement.
  6064.  
  6065.    3.4.6.8  Using Record Numbers to Retrieve Records
  6066.  
  6067.    You can read any record from a random-access file by specifying the
  6068.    record's number in a GET statement. You can write to any record in a
  6069.    random-access file by specifying the record's number in a PUT statement.
  6070.    This is one of the major advantages that random-access files have over
  6071.    sequential files, since sequential files do not permit direct access to a
  6072.    specific record.
  6073.  
  6074.    The sample-application program INDEX.BAS, listed in Section 3.6.2, shows
  6075.    a technique that quickly finds a particular record by searching an index
  6076.    of record numbers.
  6077.  
  6078.    Example
  6079.  
  6080.    The following fragment shows how to use GET with a record number:
  6081.  
  6082.    DEFINT A-Z           ' Default variable type is integer.
  6083.    CONST FALSE = 0, TRUE = NOT FALSE
  6084.  
  6085.    TYPE StockItem
  6086.       PartNumber AS STRING *  6
  6087.       Description AS STRING * 20
  6088.       UnitPrice AS SINGLE
  6089.       Quantity AS INTEGER
  6090.    END TYPE
  6091.  
  6092.    DIM StockRecord AS StockItem
  6093.  
  6094.    OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN=LEN(StockRecord)
  6095.  
  6096.    NumberOfRecords = LOF(1) \ LEN(StockRecord)
  6097.    GetMoreRecords = TRUE
  6098.  
  6099.    DO
  6100.       PRINT "Enter record number for part you want to see ";
  6101.       PRINT "(0 to end): ";
  6102.       INPUT "", RecordNumber
  6103.  
  6104.       IF RecordNumber > 0 AND RecordNumber < NumberOfRecords THEN
  6105.  
  6106.          ' Get the record whose number was entered and store
  6107.          ' it in StockRecord:
  6108.          GET #1, RecordNumber, StockRecord
  6109.  
  6110.          ' Display the record:
  6111.          .
  6112.          .
  6113.          .
  6114.          ELSEIF RecordNumber = 0 THEN
  6115.          GetMoreRecords = FALSE
  6116.       ELSE
  6117.          PRINT "Input value out of range."
  6118.       END IF
  6119.    LOOP WHILE GetMoreRecords
  6120.    END
  6121.  
  6122.  3.4.7  Binary File I/O
  6123.  
  6124.    Binary access is a third way──in addition to random access and sequential
  6125.    access──to read or write a file's data. Use the following statement to
  6126.    open a file for binary I/O:
  6127.  
  6128.    OPEN file FOR BINARY AS #filenum
  6129.  
  6130.    Binary access is a way to get at the raw bytes of any file, not just an
  6131.    ASCII file. This makes it very useful for reading or modifying files saved
  6132.    in a non-ASCII format, such as Microsoft Word files or executable (.EXE)
  6133.    files.
  6134.  
  6135.    Files opened for binary access are treated as an unformatted sequence of
  6136.    bytes. Although you can read or write a record (a variable declared as
  6137.    having a user-defined type) to a file opened in the binary mode, the file
  6138.    itself does not have to be organized into fixed-length records. In fact,
  6139.    binary I/O does not have to deal with records at all, unless you consider
  6140.    each byte in a file as a separate record.
  6141.  
  6142.    3.4.7.1  Comparing Binary Access and Random Access
  6143.  
  6144.    The binary-access mode is similar to the random-access mode in that you
  6145.    can both read from and write to a file after a single OPEN statement.
  6146.    (Binary thus differs from sequential access, where you must first close a
  6147.    file and then reopen it if you want to switch between reading and
  6148.    writing.) Also, like random access, binary access lets you move backwards
  6149.    and forwards within an open file. Binary access even supports the same
  6150.    statements used for reading and writing random-access files:
  6151.  
  6152.    {GET| PUT} [[#]]filenumber, [[position]], variable
  6153.  
  6154.    Here, variable can have any type, including a variable-length string or a
  6155.    user-defined type, and position points to the place in the file where the
  6156.    next GET or PUT operation will take place. (The position is relative to
  6157.    the beginning of the file; that is, the first byte in the file has
  6158.    position one, the second byte has position two, and so on.) If you leave
  6159.    off the position argument, successive GET and PUT operations move the file
  6160.    pointer sequentially through the file from the first byte to the last.
  6161.  
  6162.    The GET statement reads a number of bytes from the file equal to the
  6163.    length of variable. Similarly, the PUT statement writes a number of bytes
  6164.    to the file equal to the length of variable. For example, if variable has
  6165.    integer type, then GET reads two bytes into variable; if variable has
  6166.    single-precision type, GET reads four bytes. Therefore, if you don't
  6167.    specify a position argument in a GET or PUT statement, the file pointer is
  6168.    moved a distance equal to the length of variable.
  6169.  
  6170.    The GET statement and INPUT$ function are the only ways to read data from
  6171.    a file opened in binary mode. The PUT statement is the only way to write
  6172.    data to a file opened in binary mode.
  6173.  
  6174.    Binary access, unlike random access, enables you to move to any byte
  6175.    position in a file and then read or write any number of bytes you want. In
  6176.    contrast, random access can only move to a record boundary and read a
  6177.    fixed number of bytes (the length of a record) each time.
  6178.  
  6179.    3.4.7.2  Positioning the File Pointer with SEEK
  6180.  
  6181.    If you want to move the file pointer to a certain place in a file without
  6182.    actually performing any I/O, use the SEEK statement. Its syntax is
  6183.  
  6184.    SEEK filenumber, position
  6185.  
  6186.    After a SEEK statement, the next read or write operation in the file
  6187.    opened with filenumber begins at the byte noted in position.
  6188.  
  6189.    The counterpart to the SEEK statement is the SEEK function, with this
  6190.    syntax:
  6191.  
  6192.    SEEK(filenumber)
  6193.  
  6194.    The SEEK function tells you the byte position where the very next read or
  6195.    write operation begins. (If you are using binary I/O to access a file, the
  6196.    LOC and SEEK functions give similar results, but LOC returns the position
  6197.    of the last byte read or written, while SEEK returns the position of the
  6198.    next byte to be read or written.)
  6199.  
  6200.    The SEEK statement and function also work on files opened for sequential
  6201.    or random access. With sequential access, both the statement and the
  6202.    function behave the same as they do with binary access; that is, the SEEK
  6203.    statement moves the file pointer to specific byte positions, and the SEEK
  6204.    function returns information about the next byte to read or write.
  6205.  
  6206.    However, if a file is opened for random access, the SEEK statement can
  6207.    move the file pointer only to the beginning of a record, not to a byte
  6208.    within a record. Also, when used with random-access files, the SEEK
  6209.    function returns the number of the next record rather than the position of
  6210.    the next byte.
  6211.  
  6212.    Example
  6213.  
  6214.    The following program opens a QuickBASIC Quick library, then reads and
  6215.    prints the names of BASIC procedures and other external symbols contained
  6216.    in the library. This program is in the file named QLBDUMP.BAS on the
  6217.    QuickBASIC distribution disks.
  6218.  
  6219.    ' This program prints the names of Quick library procedures.
  6220.    DECLARE SUB DumpSym (SymStart AS INTEGER, QHdrPos AS LONG)
  6221.  
  6222.    TYPE ExeHdr                     ' Part of DOS .EXE header
  6223.        other1    AS STRING * 8     ' Other header information
  6224.        CParHdr   AS INTEGER        ' Size of header in paragraphs
  6225.        other2    AS STRING * 10    ' Other header information
  6226.        IP          AS INTEGER      ' Initial IP value
  6227.        CS          AS INTEGER      ' Initial (relative) CS value
  6228.    END TYPE
  6229.  
  6230.    TYPE QBHdr                      ' QLB header
  6231.        QBHead    AS STRING * 6     ' QB specific heading
  6232.        Magic     AS INTEGER        ' Magic word: identifies file as a Quick li
  6233.        SymStart  AS INTEGER        ' Offset from header to first code symbol
  6234.        DatStart  AS INTEGER        ' Offset from header to first data symbol
  6235.    END TYPE
  6236.  
  6237.    TYPE QbSym                      ' QuickLib symbol entry
  6238.        Flags     AS INTEGER        ' Symbol flags
  6239.        NameStart AS INTEGER        ' Offset into name table
  6240.        other     AS STRING * 4     ' Other header information
  6241.    END TYPE
  6242.  
  6243.    DIM EHdr AS ExeHdr, Qhdr AS QBHdr, QHdrPos AS LONG
  6244.  
  6245.    INPUT "Enter Quick library file name: ", FileName$
  6246.    FileName$ = UCASE$(FileName$)
  6247.    IF INSTR(FileName$,".QLB") = 0 THEN FileName$ = FileName$ + ".QLB"
  6248.    INPUT "Enter output file name or press ENTER for screen: ", OutFile$
  6249.    OutFile$ = UCASE$(OutFile$)
  6250.    IF OutFile$ = "" THEN OutFile$ = "CON"
  6251.    OPEN FileName$ FOR BINARY AS #1
  6252.    OPEN OutFile$ FOR OUTPUT AS #2
  6253.  
  6254.    GET #1, , EHdr                    ' Read the EXE format header.
  6255.    QHdrPos = (EHdr.CParHdr + EHdr.CS) * 16 + EHdr.IP + 1
  6256.  
  6257.    GET #1, QHdrPos, Qhdr             ' Read the QuickLib format header.
  6258.    IF Qhdr.Magic <> &H6C75 THEN PRINT "Not a QB UserLibrary": END
  6259.  
  6260.    PRINT #2, "Code Symbols:": PRINT #2,
  6261.    DumpSym Qhdr.SymStart, QHdrPos    ' dump code symbols
  6262.    PRINT #2,
  6263.    PRINT #2, "Data Symbols:": PRINT #2, ""
  6264.    DumpSym Qhdr.DatStart, QHdrPos    ' dump data symbols
  6265.    PRINT #2,
  6266.  
  6267.    END
  6268.  
  6269.    SUB DumpSym (SymStart AS INTEGER, QHdrPos AS LONG)
  6270.       DIM QlbSym AS QbSym
  6271.       DIM NextSym AS LONG, CurrentSym AS LONG
  6272.  
  6273.       ' Calculate the location of the first symbol entry,
  6274.       ' then read that entry:
  6275.       NextSym = QHdrPos + Qhdr.SymStart
  6276.       GET #1, NextSym, QlbSym
  6277.  
  6278.    DO
  6279.          NextSym = SEEK(1)           ' Save the location of the next symbol.
  6280.          CurrentSym = QHdrPos + QlbSym.NameStart
  6281.          SEEK #1, CurrentSym         ' Use SEEK to move to the name
  6282.                                      ' for the current symbol entry.
  6283.          Prospect$ = INPUT$(40, 1)   ' Read the longest legal string,
  6284.                                      ' plus one additional byte for
  6285.                                      ' the final null character (CHR$(0)).
  6286.  
  6287.          ' Extract the null-terminated name:
  6288.          SName$ = LEFT$(Prospect$, INSTR(Prospect$, CHR$(0)))
  6289.  
  6290.          ' Print only those names that do not begin with "__", "$", or "b$"
  6291.          ' as these names are usually considered reserved:
  6292.          T$ = LEFT$(SName$, 2)
  6293.          IF T$ <> "__" AND LEFT$(SName$, 1) <> "$" AND UCASE$(T$) <> "B$" THEN
  6294.             PRINT #2, "  " + SName$
  6295.          END IF
  6296.  
  6297.          GET #1, NextSym, QlbSym     ' Read a symbol entry.
  6298.       LOOP WHILE QlbSym.Flags        ' Flags=0 (false) means end of table.
  6299.  
  6300.    END SUB
  6301.  
  6302.  
  6303.  3.5  Working with Devices
  6304.  
  6305.    Microsoft BASIC supports device I/O. This means certain computer
  6306.    peripherals can be opened for I/O just like data files on disk. Input from
  6307.    or output to these devices can be done with the statements and functions
  6308.    listed in Table 9.4, "Statements and Functions Used for Data-File I/O,"
  6309.    with the exceptions noted in Section 3.5.1, "Differences between Device
  6310.    I/O and File I/O." Table 3.1 lists the devices supported by BASIC.
  6311.  
  6312.    Table 3.1  Devices Supported by BASIC for I/O
  6313.    Name                     Device                  I/O Mode Supported
  6314.    ──────────────────────────────────────────────────────────────────────────
  6315.    COM1:                    First serial port       Input and output
  6316.  
  6317.    COM2:                    Second serial port      Input and output
  6318.  
  6319.    CONS:                    Screen                  Output only
  6320.  
  6321.    KYBD:                    Keyboard                Input only
  6322.  
  6323.    LPT1:                    First printer           Output only
  6324.  
  6325.    LPT2:                    Second printer          Output only
  6326.  
  6327.    LPT3:                    Third printer           Output only
  6328.  
  6329.    SCRN:                    Screen                  Output only
  6330.  
  6331.    ──────────────────────────────────────────────────────────────────────────
  6332.  
  6333.  3.5.1  Differences between Device I/O and File I/O
  6334.  
  6335.    Certain functions and statements used for file I/O are not allowed for
  6336.    device I/O, while other statements and functions behave differently. These
  6337.    are some of the differences:
  6338.  
  6339.    ■ The CONS:, SCRN:, and LPTn: devices cannot be opened in the input or
  6340.      append modes.
  6341.  
  6342.    ■ The KYBD: device cannot be opened in the output or append modes.
  6343.  
  6344.    ■ The EOF, LOC, and LOF functions cannot be used with the CONS:, KYBD:,
  6345.      LPTn:, or SCRN: devices.
  6346.  
  6347.    ■ The EOF, LOC, and LOF functions can be used with the COMn: serial
  6348.      device; however, the values these functions return have a different
  6349.      meaning than the values they return when used with data files. (See
  6350.      Section 3.5.2 for an explanation of what these functions do when used
  6351.      with COMn:.)
  6352.  
  6353.    Example
  6354.  
  6355.    The following program shows how the devices LPT1: or SCRN: can be opened
  6356.    for output using the same syntax as that for data files. This program
  6357.    reads all the lines from the file chosen by the user and then prints the
  6358.    lines on the screen or the printer according to the user's choice.
  6359.  
  6360.    CLS
  6361.    ' Input the name of the file to look at:
  6362.    INPUT "Name of file to display: ", FileNam$
  6363.  
  6364.    ' If no name is entered, end the program;
  6365.    ' otherwise, open the given file for reading (INPUT):
  6366.    IF FileNam$ = "" THEN END ELSE OPEN FileNam$ FOR INPUT AS #1
  6367.  
  6368.    ' Input choice for displaying file (Screen or Printer);
  6369.    ' continue prompting for input until either the "S" or "P"
  6370.    ' keys are pressed:
  6371.    DO
  6372.       ' Go to row 2, column 1 on the screen and print prompt:
  6373.       LOCATE 2, 1, 1
  6374.       PRINT "Send output to screen (S), or to printer (P): ";
  6375.  
  6376.       ' Print over anything after the prompt:
  6377.       PRINT SPACE$(2);
  6378.  
  6379.       ' Relocate cursor after the prompt, and make it visible:
  6380.       LOCATE 2, 47, 1
  6381.       Choice$ = UCASE$(INPUT$(1))     ' Get input.
  6382.       PRINT Choice$
  6383.    LOOP WHILE Choice$ <> "S" AND Choice$ <> "P"
  6384.  
  6385.    ' Depending on the key pressed, open either the printer
  6386.    ' or the screen for output:
  6387.    SELECT CASE Choice$
  6388.       CASE "P"
  6389.          OPEN "LPT1:" FOR OUTPUT AS #2
  6390.          PRINT "Printing file on printer."
  6391.       CASE "S"
  6392.          CLS
  6393.          OPEN "SCRN:" FOR OUTPUT AS #2
  6394.    END SELECT
  6395.  
  6396.    ' Set the width of the chosen output device to 80 columns:
  6397.    WIDTH #2, 80
  6398.  
  6399.    ' As long as there are lines in the file, read a line
  6400.    ' from the file and print it on the chosen device:
  6401.    DO UNTIL EOF(1)
  6402.       LINE INPUT #1, LineBuffer$
  6403.       PRINT #2, LineBuffer$
  6404.    LOOP
  6405.  
  6406.    CLOSE        ' End input from the file and output to the device.
  6407.    END
  6408.  
  6409.  3.5.2  Communications through the Serial Port
  6410.  
  6411.    The OPEN "COMn:" statement (where n can be 1 or, if you have two serial
  6412.    ports, 2) allows you to open your computer's serial port(s) for serial
  6413.    (bit-by-bit) communication with other computers or with peripheral devices
  6414.    such as modems or serial printers. The following are some of the
  6415.    parameters you can specify:
  6416.  
  6417.    ■ Rate of data transmission, measured in "baud" (bits per second)
  6418.  
  6419.    ■ Whether or not to detect transmission errors and how those errors will
  6420.      be detected
  6421.  
  6422.    ■ How many stop bits (1, 1.5, or 2) are to be used to signal the end of a
  6423.      transmitted byte
  6424.  
  6425.    ■ How many bits in each byte of data transmitted or received constitute
  6426.      actual data
  6427.  
  6428.    When the serial port is opened for communication, an input buffer is set
  6429.    aside to hold the bytes being read from other device. This is because, at
  6430.    high baud rates, characters arrive faster than they can be processed. The
  6431.    default size for this buffer is 512 bytes, and it can be modified with the
  6432.    LEN = numbytes option of the OPEN "COMn:" statement. The values returned
  6433.    by the EOF, LOC, and LOF functions when used with a communications device
  6434.    return information about the size of this buffer, as shown in the
  6435.    following list:
  6436.  
  6437.    Function                 Information Returned
  6438.    ──────────────────────────────────────────────────────────────────────────
  6439.    EOF                      Whether or not any characters are waiting to be
  6440.                             read from the input buffer
  6441.  
  6442.    LOC                      The number of characters waiting in the input
  6443.                             buffer
  6444.  
  6445.    LOF                      The amount of space remaining (in bytes) in the
  6446.                             output buffer
  6447.  
  6448.    ──────────────────────────────────────────────────────────────────────────
  6449.  
  6450.    Since every character is potentially significant data, both INPUT # and
  6451.    LINE INPUT # have serious drawbacks for getting input from another device.
  6452.    This is because INPUT # stops reading data into a variable when it
  6453.    encounters a comma or new line (and, sometimes, a space or double quote),
  6454.    and LINE INPUT # stops reading data when it encounters a new line. This
  6455.    makes INPUT$ the best function to use for input from a communications
  6456.    device, since it reads all characters.
  6457.  
  6458.    The following line uses the LOC function to check the input buffer for the
  6459.    number of characters waiting there from the communications device opened
  6460.    as file #1; it then uses the INPUT$ function to read those characters,
  6461.    assigning them to a string variable named ModemInput$:
  6462.  
  6463.    ModemInput$ = INPUT$(LOC(1), #1)
  6464.  
  6465.  
  6466.  3.6  Sample Applications
  6467.  
  6468.    The sample applications listed in this section include a screen-handling
  6469.    program that prints a calendar for any month in any year from 1899 to
  6470.    2099, a file I/O program that builds and searches an index of record
  6471.    numbers from a random-access file, and a communications program that makes
  6472.    your PC behave like a terminal when connected to a modem.
  6473.  
  6474.  3.6.1  Perpetual Calendar (CAL.BAS)
  6475.  
  6476.    After prompting the user to input a month from 1 to 12 and a year from
  6477.    1899 to 2099, the following program prints the calendar for the given
  6478.    month and year. The IsLeapYear procedure makes appropriate adjustments to
  6479.    the calendar for months in a leap year.
  6480.  
  6481.    Statements and Functions Used
  6482.  
  6483.    This program demonstrates the following screen-handling functions and
  6484.    statements discussed in Sections 3.1-3.3:
  6485.  
  6486.    ■ INPUT
  6487.  
  6488.    ■ INPUT$
  6489.  
  6490.    ■ LOCATE
  6491.  
  6492.    ■ POS(0)
  6493.  
  6494.    ■ PRINT
  6495.  
  6496.    ■ PRINT USING
  6497.  
  6498.    ■ TAB
  6499.  
  6500.    Program Listing
  6501.  
  6502.    The perpetual calendar program CAL.BAS is listed below.
  6503.  
  6504.    DEFINT A-Z              ' Default variable type is integer.
  6505.  
  6506.    ' Define a data type for the names of the months and the
  6507.    ' number of days in each:
  6508.    TYPE MonthType
  6509.       Number AS INTEGER       ' Number of days in the month
  6510.       MName AS STRING * 9     ' Name of the month
  6511.    END TYPE
  6512.  
  6513.    ' Declare procedures used:
  6514.    DECLARE FUNCTION IsLeapYear% (N%)
  6515.    DECLARE FUNCTION GetInput% (Prompt$, Row%, LowVal%, HighVal%)
  6516.  
  6517.    DECLARE SUB PrintCalendar (Year%, Month%)
  6518.    DECLARE SUB ComputeMonth (Year%, Month%, StartDay%, TotalDays%)
  6519.  
  6520.    DIM MonthData(1 TO 12) AS MonthType
  6521.  
  6522.    ' Initialize month definitions from DATA statements below:
  6523.    FOR I = 1 TO 12
  6524.       READ MonthData(I).MName, MonthData(I).Number
  6525.    NEXT
  6526.  
  6527.    ' Main loop, repeat for as many months as desired:
  6528.    DO
  6529.       CLS
  6530.  
  6531.       ' Get year and month as input:
  6532.       Year = GetInput("Year (1899 to 2099): ", 1, 1899, 2099)
  6533.       Month = GetInput("Month (1 to 12): ", 2, 1, 12)
  6534.  
  6535.       ' Print the calendar:
  6536.       PrintCalendar Year, Month
  6537.    ' Another Date?
  6538.       LOCATE 13, 1           ' Locate in 13th row, 1st column.
  6539.       PRINT "New Date? ";    ' Keep cursor on same line.
  6540.       LOCATE , , 1, 0, 13    ' Turn cursor on and make it one
  6541.                              ' character high.
  6542.       Resp$ = INPUT$(1)      ' Wait for a key press.
  6543.       PRINT Resp$            ' Print the key pressed.
  6544.  
  6545.    LOOP WHILE UCASE$(Resp$) = "Y"
  6546.    END
  6547.  
  6548.    ' Data for the months of a year:
  6549.    DATA January, 31, February, 28, March, 31
  6550.    DATA April, 30, May, 31, June, 30, July, 31, August, 31
  6551.    DATA September, 30, October, 31, November, 30, December, 31
  6552.  
  6553.    ' ====================== COMPUTEMONTH =====================
  6554.    '  Computes the first day and the total days in a month
  6555.    ' =========================================================
  6556.  
  6557.    SUB ComputeMonth (Year, Month, StartDay, TotalDays) STATIC
  6558.       SHARED MonthData() AS MonthType
  6559.  
  6560.       CONST LEAP   = 366 MOD 7
  6561.       CONST NORMAL = 365 MOD 7
  6562.  
  6563.       ' Calculate total number of days (NumDays) since 1/1/1899:
  6564.  
  6565.       ' Start with whole years:
  6566.       NumDays = 0
  6567.       FOR I = 1899 TO Year - 1
  6568.          IF IsLeapYear(I) THEN         ' If leap year,
  6569.             NumDays = NumDays + LEAP   ' add 366 MOD 7.
  6570.          ELSE                          ' If normal year,
  6571.             NumDays = NumDays + NORMAL ' add 365 MOD 7.
  6572.          END IF
  6573.       NEXT
  6574.  
  6575.       ' Next, add in days from whole months:
  6576.       FOR I = 1 TO Month - 1
  6577.          NumDays = NumDays + MonthData(I).Number
  6578.       NEXT
  6579.  
  6580.       ' Set the number of days in the requested month:
  6581.       TotalDays = MonthData(Month).Number
  6582.  
  6583.       ' Compensate if requested year is a leap year:
  6584.       IF IsLeapYear(Year) THEN
  6585.  
  6586.          ' If after February, add one to total days:
  6587.          IF Month > 2 THEN
  6588.             NumDays = NumDays + 1
  6589.  
  6590.          ' If February, add one to the month's days:
  6591.          ELSEIF Month = 2 THEN
  6592.             TotalDays = TotalDays + 1
  6593.          END IF
  6594.       END IF
  6595.  
  6596.       ' 1/1/1899 was a Sunday, so calculating "NumDays MOD 7"
  6597.       ' gives the day of week (Sunday = 0, Monday = 1, Tuesday
  6598.       ' = 2, and so on) for the first day of the input month:
  6599.       StartDay = NumDays MOD 7
  6600.    END SUB
  6601.  
  6602.    ' ======================== GETINPUT =======================
  6603.    '    Prompts for input, then tests for a valid range
  6604.    ' =========================================================
  6605.  
  6606.    FUNCTION GetInput (Prompt$, Row, LowVal, HighVal) STATIC
  6607.  
  6608.       ' Locate prompt at specified row, turn cursor on and
  6609.       ' make it one character high:
  6610.       LOCATE Row, 1, 1, 0, 13
  6611.       PRINT Prompt$;
  6612.  
  6613.       ' Save column position:
  6614.       Column = POS(0)
  6615.  
  6616.       ' Input value until it's within range:
  6617.       DO
  6618.          LOCATE Row, Column   ' Locate cursor at end of prompt.
  6619.          PRINT SPACE$(10)     ' Erase anything already there.
  6620.          LOCATE Row, Column   ' Relocate cursor at end of prompt.
  6621.          INPUT "", Value      ' Input value with no prompt.
  6622.       LOOP WHILE (Value < LowVal OR Value > HighVal
  6623.  
  6624.       ' Return valid input as value of function:
  6625.       GetInput = Value
  6626.  
  6627.    END FUNCTION
  6628.  
  6629.    ' ====================== ISLEAPYEAR =======================
  6630.    '   Determines if a year is a leap year or not
  6631.    ' =========================================================
  6632.  
  6633.    FUNCTION IsLeapYear (N) STATIC
  6634.  
  6635.       ' If the year is evenly divisible by 4 and not divisible
  6636.       ' by 100, or if the year is evenly divisible by 400,
  6637.       ' then it's a leap year:
  6638.       IsLeapYear = (N MOD 4=0 AND N MOD 100<>0) OR (N MOD 400=0)
  6639.    END FUNCTION
  6640.  
  6641.    ' ===================== PRINTCALENDAR =====================
  6642.    '   Prints a formatted calendar given the year and month
  6643.    ' =========================================================
  6644.  
  6645.    SUB PrintCalendar (Year, Month) STATIC
  6646.    SHARED MonthData() AS MonthType
  6647.  
  6648.       ' Compute starting day (Su M Tu ...)
  6649.       ' and total days for the month:
  6650.       ComputeMonth Year, Month, StartDay, TotalDays
  6651.       CLS
  6652.       Header$ = RTRIM$(MonthData(Month).MName) + "," + STR$(Year)
  6653.  
  6654.       ' Calculate location for centering month and year:
  6655.       LeftMargin = (35 - LEN(Header$)) \ 2
  6656.  
  6657.    ' Print header:
  6658.       PRINT TAB(LeftMargin); Header$
  6659.       PRINT
  6660.       PRINT "Su   M   Tu   W   Th    F   Sa"
  6661.       PRINT
  6662.  
  6663.       ' Recalculate and print tab
  6664.       ' to the first day of the month (Su M Tu ...):
  6665.       LeftMargin = 5 * StartDay + 1
  6666.       PRINT TAB(LeftMargin);
  6667.  
  6668.       ' Print out the days of the month:
  6669.       FOR I = 1 TO TotalDays
  6670.          PRINT USING "##"; I;
  6671.  
  6672.          ' Advance to the next line
  6673.          ' when the cursor is past column 32:
  6674.          IF POS(0) > 32 THEN PRINT
  6675.       NEXT
  6676.  
  6677.    END SUB
  6678.  
  6679.    Output
  6680.  
  6681.    ┌───────────────────────────────────────────────────────────────────┐
  6682.    │                                                                   │
  6683.    │                June, 1988                                         │
  6684.    │                                                                   │
  6685.    │     Su    M    Tu    W   Th     F    Sa                           │
  6686.    │                                                                   │
  6687.    │                      1    2     3     4                           │
  6688.    │      5    6     7    8    9    10    11                           │
  6689.    │     12   13    14   15   16    17    18                           │
  6690.    │     19   20    21   22   23    24    25                           │
  6691.    │     26   27    28   29   30                                       │
  6692.    │                                                                   │
  6693.    │                                                                   │
  6694.    │     New Date?                                                     │
  6695.    │                                                                   │
  6696.    └───────────────────────────────────────────────────────────────────┘
  6697.  
  6698.  3.6.2  Indexing a Random-Access File (INDEX.BAS)
  6699.  
  6700.    The following program uses an indexing technique to store and retrieve
  6701.    records in a random-access file. Each element of the Index array has two
  6702.    parts: a string field (PartNumber) and an integer field (RecordNumber).
  6703.    This array is sorted alphabetically on the PartNumber field, which allows
  6704.    the array to be rapidly searched for a specific part number using a binary
  6705.    search.
  6706.  
  6707.    The Index array functions much like the index to a book. When you want to
  6708.    find the pages in a book that deal with a particular topic, you look up an
  6709.    entry for that topic in the index. The entry then points to a page number
  6710.    in the book. Similarly, this program looks up a part number in the
  6711.    alphabetically sorted Index array. Once it finds the part number, the
  6712.    associated record number in the RecordNumber field points to the record
  6713.    containing all the information for that part.
  6714.  
  6715.    Statements and Functions Used
  6716.  
  6717.    This program demonstrates the following functions and statements used in
  6718.    accessing random-access files:
  6719.  
  6720.    ■ TYPE...END TYPE
  6721.  
  6722.    ■ OPEN...FOR RANDOM
  6723.  
  6724.    ■ GET #
  6725.  
  6726.    ■ PUT #
  6727.  
  6728.    ■ LOF
  6729.  
  6730.    Program Listing
  6731.  
  6732.    The random-access file indexing program INDEX.BAS is listed below.
  6733.  
  6734.    DEFINT A-Z
  6735.  
  6736.    ' Define the symbolic constants used globally in the program:
  6737.    CONST FALSE = 0, TRUE = NOT FALSE
  6738.  
  6739.    ' Define a record structure for random-file records:
  6740.    TYPE StockItem
  6741.       PartNumber AS STRING * 6
  6742.       Description AS STRING * 20
  6743.       UnitPrice AS SINGLE
  6744.       Quantity AS INTEGER
  6745.    END TYPE
  6746.  
  6747.    ' Define a record structure for each element of the index:
  6748.    TYPE IndexType
  6749.       RecordNumber AS INTEGER
  6750.       PartNumber AS STRING * 6
  6751.    END TYPE
  6752.  
  6753.    ' Declare procedures that will be called:
  6754.    DECLARE FUNCTION Filter$ (Prompt$)
  6755.    DECLARE FUNCTION FindRecord% (PartNumber$, RecordVar AS StockItem)
  6756.  
  6757.    DECLARE SUB AddRecord (RecordVar AS StockItem)
  6758.    DECLARE SUB InputRecord (RecordVar AS StockItem)
  6759.    DECLARE SUB PrintRecord (RecordVar AS StockItem)
  6760.    DECLARE SUB SortIndex ()
  6761.    DECLARE SUB ShowPartNumbers ()
  6762.    ' Define a buffer (using the StockItem type)
  6763.    ' and define and dimension the index array:
  6764.    DIM StockRecord AS StockItem, Index(1 TO 100) AS IndexType
  6765.  
  6766.    ' Open the random-access file:
  6767.    OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN = LEN(StockRecord)
  6768.  
  6769.    ' Calculate number of records in the file:
  6770.    NumberOfRecords = LOF(1) \ LEN(StockRecord)
  6771.  
  6772.    ' If there are records, read them and build the index:
  6773.    IF NumberOfRecords <> 0 THEN
  6774.       FOR RecordNumber = 1 TO NumberOfRecords
  6775.  
  6776.          ' Read the data from a new record in the file:
  6777.          GET #1, RecordNumber, StockRecord
  6778.  
  6779.          ' Place part number and record number in index:
  6780.          Index(RecordNumber).RecordNumber = RecordNumber
  6781.          Index(RecordNumber).PartNumber = StockRecord.PartNumber
  6782.       NEXT
  6783.  
  6784.       SortIndex            ' Sort index in part-number order.
  6785.    END IF
  6786.  
  6787.    DO                      ' Main-menu loop.
  6788.       CLS
  6789.       PRINT "(A)dd records."
  6790.       PRINT "(L)ook up records."
  6791.       PRINT "(Q)uit program."
  6792.       PRINT
  6793.       LOCATE , , 1
  6794.       PRINT "Type your choice (A, L, or Q) here: ";
  6795.  
  6796.       ' Loop until user presses, A, L, or Q:
  6797.       DO
  6798.          Choice$ = UCASE$(INPUT$(1))
  6799.       LOOP WHILE INSTR("ALQ", Choice$) = 0
  6800.  
  6801.       ' Branch according to choice:
  6802.       SELECT CASE Choice$
  6803.          CASE "A"
  6804.         AddRecord StockRecord
  6805.          CASE "L"
  6806.         IF NumberOfRecords = 0 THEN
  6807.            PRINT : PRINT "No records in file yet. ";
  6808.            PRINT "Press any key to continue.";
  6809.            Pause$ = INPUT$(1)
  6810.         ELSE
  6811.            InputRecord StockRecord
  6812.         END IF
  6813.          CASE "Q"          ' End program.
  6814.       END SELECT
  6815.    LOOP UNTIL Choice$ = "Q"
  6816.  
  6817.    CLOSE #1                ' All done, close file and end.
  6818.    END
  6819.  
  6820.    ' ======================== ADDRECORD ======================
  6821.    ' Adds records to the file from input typed at the keyboard
  6822.    ' =========================================================
  6823.  
  6824.    SUB AddRecord (RecordVar AS StockItem) STATIC
  6825.       SHARED Index() AS IndexType, NumberOfRecords
  6826.       DO
  6827.          CLS
  6828.          INPUT "Part Number: ", RecordVar.PartNumber
  6829.          INPUT "Description: ", RecordVar.Description
  6830.  
  6831.          ' Call the Filter$ FUNCTION to input price & quantity:
  6832.          RecordVar.UnitPrice = VAL(Filter$("Unit Price : "))
  6833.          RecordVar.Quantity = VAL(Filter$("Quantity   : "))
  6834.  
  6835.          NumberOfRecords = NumberOfRecords + 1
  6836.  
  6837.          PUT #1, NumberOfRecords, RecordVar
  6838.  
  6839.          Index(NumberOfRecords).RecordNumber = NumberOfRecords
  6840.          Index(NumberOfRecords).PartNumber = RecordVar.PartNumber
  6841.          PRINT : PRINT "Add another? ";
  6842.          OK$ = UCASE$(INPUT$(1))
  6843.       LOOP WHILE OK$ = "Y"
  6844.  
  6845.       SortIndex            ' Sort index file again.
  6846.    END SUB
  6847.  
  6848.    ' ========================= FILTER ========================
  6849.    '       Filters all non-numeric characters from a string
  6850.    '       and returns the filtered string
  6851.    ' =========================================================
  6852.  
  6853.    FUNCTION Filter$ (Prompt$) STATIC
  6854.       ValTemp2$ = ""
  6855.       PRINT Prompt$;                    ' Print the prompt passed.
  6856.       INPUT "", ValTemp1$               ' Input a number as
  6857.                                         ' a string.
  6858.       StringLength = LEN(ValTemp1$)     ' Get the string's length.
  6859.       FOR I% = 1 TO StringLength        ' Go through the string,
  6860.          Char$ = MID$(ValTemp1$, I%, 1) ' one character at a time.
  6861.  
  6862.          ' Is the character a valid part of a number (i.e.,
  6863.          ' a digit or a decimal point)?  If yes, add it to
  6864.          ' the end of a new string:
  6865.          IF INSTR(".0123456789", Char$) > 0 THEN
  6866.             ValTemp2$ = ValTemp2$ + Char$
  6867.  
  6868.          ' Otherwise, check to see if it's a lowercase "l",
  6869.          ' since typewriter users may enter a one that way:
  6870.          ELSEIF Char$ = "l" THEN
  6871.             ValTemp2$ = ValTemp2$ + "1" ' Change the "l" to a "1".
  6872.          END IF
  6873.       NEXT I%
  6874.  
  6875.       Filter$ = ValTemp2$               ' Return filtered string.
  6876.  
  6877.    END FUNCTION
  6878.  
  6879.    ' ======================= FINDRECORD ===================
  6880.    '  Uses a binary search to locate a record in the index
  6881.    ' ======================================================
  6882.  
  6883.    FUNCTION FindRecord% (Part$, RecordVar AS StockItem) STATIC
  6884.       SHARED Index() AS IndexType, NumberOfRecords
  6885.  
  6886.       ' Set top and bottom bounds of search:
  6887.       TopRecord = NumberOfRecords
  6888.       BottomRecord = 1
  6889.  
  6890.       ' Search until top of range is less than bottom:
  6891.       DO UNTIL (TopRecord < BottomRecord)
  6892.  
  6893.          ' Choose midpoint:
  6894.          Midpoint = (TopRecord + BottomRecord) \ 2
  6895.  
  6896.          ' Test to see if it's the one wanted (RTRIM$()
  6897.          ' trims trailing blanks from a fixed string):
  6898.          Test$ = RTRIM$(Index(Midpoint).PartNumber)
  6899.  
  6900.          ' If it is, exit loop:
  6901.          IF Test$ = Part$ THEN
  6902.         EXIT DO
  6903.  
  6904.          ' Otherwise, if what we're looking for is greater,
  6905.          ' move bottom up:
  6906.          ELSEIF Part$ > Test$ THEN
  6907.         BottomRecord = Midpoint + 1
  6908.  
  6909.          ' Otherwise, move the top down:
  6910.          ELSE
  6911.         TopRecord = Midpoint - 1
  6912.          END IF
  6913.       LOOP
  6914.  
  6915.       ' If part was found, input record from file using
  6916.       ' pointer in index and set FindRecord% to TRUE:
  6917.       IF Test$ = Part$ THEN
  6918.          GET #1, Index(Midpoint).RecordNumber, RecordVar
  6919.          FindRecord% = TRUE
  6920.  
  6921.       ' Otherwise, if part was not found, set FindRecord%
  6922.       ' to FALSE:
  6923.       ELSE
  6924.          FindRecord% = FALSE
  6925.       END IF
  6926.    END FUNCTION
  6927.  
  6928.    ' ======================= INPUTRECORD =====================
  6929.    '    First, INPUTRECORD calls SHOWPARTNUMBERS, which prints
  6930.    '    a menu of part numbers on the top of the screen. Next,
  6931.    '    INPUTRECORD prompts the user to enter a part number.
  6932.    '    Finally, it calls the FINDRECORD and PRINTRECORD
  6933.    '    procedures to find and print the given record.
  6934.    ' =========================================================
  6935.  
  6936.    SUB InputRecord (RecordVar AS StockItem) STATIC
  6937.       CLS
  6938.       ShowPartNumbers      ' Call the ShowPartNumbers SUB.
  6939.  
  6940.       ' Print data from specified records
  6941.       ' on the bottom part of the screen:
  6942.       DO
  6943.          PRINT "Type a part number listed above ";
  6944.          INPUT "(or Q to quit) and press <ENTER>: ", Part$
  6945.          IF UCASE$(Part$) <> "Q" THEN
  6946.             IF FindRecord(Part$, RecordVar) THEN
  6947.                PrintRecord RecordVar
  6948.             ELSE
  6949.                PRINT "Part not found."
  6950.             END IF
  6951.          END IF
  6952.          PRINT STRING$(40, "_")
  6953.       LOOP WHILE UCASE$(Part$) <> "Q"
  6954.  
  6955.       VIEW PRINT   ' Restore the text viewport to entire screen.
  6956.    END SUB
  6957.  
  6958.    ' ======================= PRINTRECORD =====================
  6959.    '                Prints a record on the screen
  6960.    ' =========================================================
  6961.  
  6962.    SUB PrintRecord (RecordVar AS StockItem) STATIC
  6963.       PRINT "Part Number: "; RecordVar.PartNumber
  6964.       PRINT "Description: "; RecordVar.Description
  6965.       PRINT USING "Unit Price :$$###.##"; RecordVar.UnitPrice
  6966.       PRINT "Quantity   :"; RecordVar.Quantity
  6967.    END SUB
  6968.  
  6969.    ' ===================== SHOWPARTNUMBERS ===================
  6970.    ' Prints an index of all the part numbers in the upper part
  6971.    ' of the screen
  6972.    ' =========================================================
  6973.  
  6974.    SUB ShowPartNumbers STATIC
  6975.       SHARED Index() AS IndexType, NumberOfRecords
  6976.  
  6977.       CONST NUMCOLS = 8, COLWIDTH = 80 \ NUMCOLS
  6978.  
  6979.       ' At the top of the screen, print a menu indexing all
  6980.       ' the part numbers for records in the file. This menu is
  6981.       ' printed in columns of equal length (except possibly the
  6982.       ' last column, which may be shorter than the others):
  6983.       ColumnLength = NumberOfRecords
  6984.       DO WHILE ColumnLength MOD NUMCOLS
  6985.          ColumnLength = ColumnLength + 1
  6986.       LOOP
  6987.       ColumnLength = ColumnLength \ NUMCOLS
  6988.       Column = 1
  6989.       RecordNumber = 1
  6990.  
  6991.    DO UNTIL RecordNumber > NumberOfRecords
  6992.          FOR Row = 1 TO ColumnLength
  6993.             LOCATE Row, Column
  6994.             PRINT Index(RecordNumber).PartNumber
  6995.             RecordNumber = RecordNumber + 1
  6996.             IF RecordNumber > NumberOfRecords THEN EXIT FOR
  6997.          NEXT Row
  6998.          Column = Column + COLWIDTH
  6999.       LOOP
  7000.  
  7001.       LOCATE ColumnLength + 1, 1
  7002.       PRINT STRING$(80, "_")       ' Print separator line.
  7003.  
  7004.       ' Scroll information about records below the part-number
  7005.       ' menu (this way, the part numbers are not erased):
  7006.       VIEW PRINT ColumnLength + 2 TO 24
  7007.    END SUB
  7008.  
  7009.    ' ========================= SORTINDEX =====================
  7010.    '                Sorts the index by part number
  7011.    ' =========================================================
  7012.  
  7013.    SUB SortIndex STATIC
  7014.  
  7015.  
  7016.       SHARED Index() AS IndexType, NumberOfRecords
  7017.  
  7018.       ' Set comparison offset to half the number of records
  7019.       ' in index:
  7020.       Offset = NumberOfRecords \ 2
  7021.  
  7022.       ' Loop until offset gets to zero:
  7023.       DO WHILE Offset > 0
  7024.          Limit = NumberOfRecords - Offset
  7025.          DO
  7026.  
  7027.             ' Assume no switches at this offset:
  7028.             Switch = FALSE
  7029.  
  7030.             ' Compare elements and switch ones out of order:
  7031.             FOR I = 1 TO Limit
  7032.                IF Index(I).PartNumber > Index(I + Offset).PartNumber THEN
  7033.                   SWAP Index(I), Index(I + Offset)
  7034.                   Switch = I
  7035.                END IF
  7036.             NEXT I
  7037.  
  7038.             ' Sort on next pass only to where
  7039.             ' last switch was made:
  7040.             Limit = Switch
  7041.          LOOP WHILE Switch
  7042.  
  7043.          ' No switches at last offset, try one half as big:
  7044.          Offset = Offset \ 2
  7045.       LOOP
  7046.    END SUB
  7047.  
  7048.    Output
  7049.  
  7050.    ┌────────────────────────────────────────────────────────────────────────┐
  7051.    │                                                                        │
  7052.    │ 0235         0417       0583        8721                               │
  7053.    │                                                                        │
  7054.    │ ────────────────────────────────────────────────────────────────────── │
  7055.    │ Type a part number listed above <or Q to quit> and press <ENTER>: 0417 │
  7056.    │ Part Number: 0417                                                      │
  7057.    │ Description: oil filter                                                │
  7058.    │ Unit Price :   $5.99                                                   │
  7059.    │ Quantity   : 12                                                        │
  7060.    │                                                                        │
  7061.    │ ────────────────────────────────────────                               │
  7062.    │ Type a part number listed above <or Q to quit> and press <ENTER>: 8721 │
  7063.    │ Part Number: 8721                                                      │
  7064.    │ Description: chamois cloth                                             │
  7065.    │ Unit Price :   $8.99                                                   │
  7066.    │ Quantity   : 23                                                        │
  7067.    │                                                                        │
  7068.    │ ────────────────────────────────────────                               │
  7069.    │ Type a part number listed above <or Q to quit> and press <ENTER>:      │
  7070.    │                                                                        │
  7071.    └────────────────────────────────────────────────────────────────────────┘
  7072.  
  7073.  3.6.3  Terminal Emulator (TERMINAL.BAS)
  7074.  
  7075.    The following simple program turns your computer into a "dumb" terminal;
  7076.    that is, it makes your computer function solely as an I/O device in tandem
  7077.    with a modem. This program uses the OPEN "COM1:" statement and associated
  7078.    device I/O functions to do the following two things:
  7079.  
  7080.    1. Send the characters you type to the modem
  7081.  
  7082.    2. Print characters returned by the modem on the screen
  7083.  
  7084.    Note that typed characters displayed on the screen are first sent to the
  7085.    modem and then returned to your computer through the open communications
  7086.    channel. You can verify this if you have a modem with Receive Detect (RD)
  7087.    and Send Detect (SD) lights──they will flash in sequence as you type.
  7088.  
  7089.    To dial a number, you would have to enter the Attention Dial Touch-Tone
  7090.    (ATDT) or Attention Dial Pulse (ATDP) commands at the keyboard (assuming
  7091.    you have a Hayes(R)-compatible modem).
  7092.  
  7093.    Any other commands sent to the modem would also have to be entered at the
  7094.    keyboard.
  7095.  
  7096.    Statements and Functions Used
  7097.  
  7098.    This program demonstrates the following functions and statements used in
  7099.    communicating with a modem through your computer's serial port:
  7100.  
  7101.    ■ OPEN "COM1:"
  7102.  
  7103.    ■ EOF
  7104.  
  7105.    ■ INPUT$
  7106.  
  7107.    ■ LOC
  7108.  
  7109.    Program Listing
  7110.  
  7111.    DEFINT A-Z
  7112.  
  7113.    DECLARE SUB Filter (InString$)
  7114.  
  7115.    COLOR 7, 1                    ' Set screen color.
  7116.    CLS
  7117.  
  7118.    Quit$ = CHR$(0) + CHR$(16)    ' Value returned by INKEY$
  7119.                                  ' when ALT+q is pressed.
  7120.  
  7121.    ' Set up prompt on bottom line of screen and turn cursor on:
  7122.    LOCATE 24, 1, 1
  7123.    PRINT STRING$(80, "_");
  7124.    LOCATE 25, 1
  7125.    PRINT TAB(30); "Press ALT+q to quit";
  7126.  
  7127.    VIEW PRINT 1 TO    23           ' Print between lines 1 & 23.
  7128.  
  7129.    ' Open communications (1200 baud, no parity, 8-bit data,
  7130.    ' 1 stop bit, 256-byte input buffer):
  7131.    OPEN "COM1:1200,N,8,1" FOR RANDOM AS #1    LEN = 256
  7132.  
  7133.    DO                              ' Main communications loop.
  7134.  
  7135.       KeyInput$ = INKEY$           ' Check the keyboard.
  7136.  
  7137.       IF KeyInput$ = Quit$ THEN    ' Exit the loop if the user
  7138.          EXIT DO                   ' pressed ALT+q.
  7139.  
  7140.       ELSEIF KeyInput$ <> "" THEN  ' Otherwise, if the user has
  7141.          PRINT #1, KeyInput$;      ' pressed a key, send the
  7142.       END IF                       ' character typed to modem.
  7143.  
  7144.       ' Check the modem. If characters are waiting (EOF(1) is
  7145.       ' true), get them and print them to the screen:
  7146.       IF NOT EOF(1) THEN
  7147.  
  7148.          ' LOC(1) gives the number of characters waiting:
  7149.          ModemInput$ = INPUT$(LOC(1), #1)
  7150.  
  7151.          Filter ModemInput$        ' Filter out line feeds and
  7152.          PRINT ModemInput$;        ' backspaces, then print.
  7153.       END IF
  7154.    LOOP
  7155.  
  7156.    CLOSE                           ' End communications.
  7157.    CLS
  7158.    END
  7159.  
  7160.    '
  7161.    ' ========================= FILTER ========================
  7162.    '               Filters characters in an input string
  7163.    ' =========================================================
  7164.    '
  7165.    SUB Filter (InString$) STATIC
  7166.  
  7167.       ' Look for backspace characters and recode
  7168.       ' them to CHR$(29) (the LEFT cursor key):
  7169.       DO
  7170.          BackSpace = INSTR(InString$, CHR$(8))
  7171.          IF BackSpace THEN
  7172.          MID$(InString$, BackSpace) = CHR$(29)
  7173.          END IF
  7174.       LOOP WHILE BackSpace
  7175.  
  7176.       ' Look for line-feed characters and
  7177.       ' remove any found:
  7178.       DO
  7179.          LnFd = INSTR(InString$, CHR$(10))
  7180.          IF LnFd THEN
  7181.       InString$=LEFT$(InString$,LnFd-1)+MID$(InString$,LnFd+1)
  7182.          END IF
  7183.       LOOP WHILE LnFd
  7184.  
  7185.    END SUB
  7186.  
  7187.  
  7188.  
  7189.  ────────────────────────────────────────────────────────────────────────────
  7190.  Chapter 4  String Processing
  7191.  
  7192.    This chapter shows you how to manipulate sequences of ASCII characters,
  7193.    known as strings. String manipulation is indispensable when you are
  7194.    processing text files, sorting data, or modifying string-data input.
  7195.  
  7196.    When you are finished with this chapter, you will know how to perform the
  7197.    following string-processing tasks:
  7198.  
  7199.    ■ Declare fixed-length strings
  7200.  
  7201.    ■ Compare strings and sort them alphabetically
  7202.  
  7203.    ■ Search for one string inside another
  7204.  
  7205.    ■ Get part of a string
  7206.  
  7207.    ■ Trim spaces from the beginning or end of a string
  7208.  
  7209.    ■ Generate a string by repeating a single character
  7210.  
  7211.    ■ Change uppercase letters in a string to lowercase and vice versa
  7212.  
  7213.    ■ Convert numeric expressions to string representations and vice versa
  7214.  
  7215.  
  7216.  4.1  Strings Defined
  7217.  
  7218.    A string is a sequence of contiguous characters. Examples of characters
  7219.    are the letters of the alphabet (a-z and A-Z), punctuation symbols such as
  7220.    commas (,) or question marks (?), and other symbols from the fields of
  7221.    math and finance such as plus (+) or percent (%) signs.
  7222.  
  7223.    In this chapter, the term "string" can refer to any of the following:
  7224.  
  7225.    ■ A string constant
  7226.  
  7227.    ■ A string variable
  7228.  
  7229.    ■ A string expression
  7230.  
  7231.    String constants are declared in one of two ways:
  7232.  
  7233.    1. By enclosing a sequence of characters between double quotes, as in the
  7234.       following PRINT statement:
  7235.  
  7236.       PRINT "Processing the file. Please wait."
  7237.  
  7238.       This is known as a "literal string constant."
  7239.  
  7240.    2. By setting a name equal to a literal string in a CONST statement, as in
  7241.       the following:
  7242.  
  7243.       ' Define the string constant MESSAGE:
  7244.       CONST MESSAGE = "Drive door open."
  7245.  
  7246.       This is known as a "symbolic string constant."
  7247.  
  7248.    String variables can be declared in one of three ways:
  7249.  
  7250.    1. By appending the string-type suffix ($) to the variable name:
  7251.  
  7252.       LINE INPUT "Enter your name: "; Buffer$
  7253.  
  7254.    2. By using the DEFSTR statement:
  7255.  
  7256.       ' All variables beginning with the letter "B"
  7257.       ' are strings, unless they end with one of the
  7258.       ' numeric-type suffixes (%, &, !, or #):
  7259.       DEFSTR B
  7260.       .
  7261.       .
  7262.       .
  7263.       Buffer = "Your name here"  ' Buffer is a string variable
  7264.  
  7265.    3. By declaring the string name in an AS STRING statement:
  7266.  
  7267.       DIM Buffer1 AS STRING      ' Buffer1 is a variable-
  7268.                                  ' length string.
  7269.       DIM Buffer2 AS STRING*10   ' Buffer2 is a fixed-length
  7270.                                  ' string 10 bytes long.
  7271.  
  7272.    A string expression is a combination of string variables, constants,
  7273.    and/or string functions.
  7274.  
  7275.    Of course, the character components of strings are not stored in your
  7276.    computer's memory in a form generally recognizable to humans. Instead,
  7277.    each character is translated to a number known as the ASCII code for that
  7278.    character. For example, capital "A" is stored as decimal 65 (or
  7279.    hexadecimal 41H), while lowercase "a" is stored as decimal 97 (or
  7280.    hexadecimal 61H). See Appendix D, "Keyboard Scan Codes and ASCII
  7281.    Character Codes," for a complete list of the ASCII codes for each
  7282.    character.
  7283.  
  7284.    You can also use the BASIC ASC function to determine the ASCII code for a
  7285.    character; for example, ASC("A") returns the value 65. The inverse of the
  7286.    ASC function is the CHR$ function. CHR$ takes an ASCII code as its
  7287.    argument and returns the character with that code; for example, the
  7288.    statement PRINT CHR$(64) displays the character @.
  7289.  
  7290.  
  7291.  4.2  Variable- and Fixed-Length Strings
  7292.  
  7293.    In previous versions of BASIC, strings were always variable length. BASIC
  7294.    now supports both variable-length strings and fixed-length strings.
  7295.  
  7296.  4.2.1  Variable-Length Strings
  7297.  
  7298.    Variable-length strings are "elastic"; that is, they expand and contract
  7299.    to store different numbers of characters (from none to a maximum of
  7300.    32,767). For example, the length of the variable Temp$ in the following
  7301.    example varies according to the size of what is stored in Temp$:
  7302.  
  7303.    Temp$ = "1234567"
  7304.  
  7305.    ' LEN function returns length of string
  7306.    '  (number of characters it contains):
  7307.  
  7308.  
  7309.  
  7310.    PRINT LEN(Temp$)
  7311.  
  7312.    Temp$ = "1234"
  7313.    PRINT LEN(Temp$)
  7314.  
  7315.    Output
  7316.  
  7317.     7
  7318.     4
  7319.  
  7320.  4.2.2  Fixed-Length Strings
  7321.  
  7322.    Fixed-length strings are commonly used as record elements in a TYPE...END
  7323.    TYPE user-defined data type. However, they can also be declared by
  7324.    themselves in COMMON, DIM, REDIM, SHARED, or STATIC statements, as in the
  7325.    following statement:
  7326.  
  7327.    DIM Buffer AS STRING * 10
  7328.  
  7329.    As their name implies, fixed-length strings have a constant length,
  7330.    regardless of the length of the string stored in them. This is shown by
  7331.    the output from the following example:
  7332.  
  7333.    DIM LastName AS STRING * 12
  7334.    DIM FirstName AS STRING * 10
  7335.  
  7336.    LastName = "Huntington-Ashley"
  7337.    FirstName = "Claire"
  7338.  
  7339.    PRINT "123456789012345678901234567890"
  7340.    PRINT FirstName; LastName
  7341.    PRINT LEN(FirstName)
  7342.    PRINT LEN(LastName)
  7343.  
  7344.    Output
  7345.  
  7346.    123456789012345678901234567890
  7347.    Claire    Huntington-A
  7348.     10
  7349.     12
  7350.  
  7351.    Note that the lengths of the string variables FirstName and LastName did
  7352.    not change, as demonstrated by the values returned by the LEN function (as
  7353.    well as the four spaces following the six-letter name, Claire).
  7354.  
  7355.    The output from the above example also illustrates how values assigned to
  7356.    fixed-length variables are left-justified and, if necessary, truncated on
  7357.    the right. It is not necessary to use the LSET function to left-justify
  7358.    values in fixed-length strings; this is done automatically. If you want to
  7359.    right-justify a string inside a fixed-length string, use RSET, as shown
  7360.    here:
  7361.  
  7362.    DIM NameBuffer AS STRING * 10
  7363.    RSET NameBuffer = "Claire"
  7364.    PRINT "1234567890"
  7365.    PRINT NameBuffer
  7366.  
  7367.    Output
  7368.  
  7369.    1234567890
  7370.        Claire
  7371.  
  7372.  
  7373.  4.3  Combining Strings
  7374.  
  7375.    Two strings can be combined with the plus (+) operator. The string
  7376.    following the plus operator is appended to the string preceding the plus
  7377.    operator, as shown in the next example:
  7378.  
  7379.    A$ = "first string"
  7380.    B$ = "second string"
  7381.    C$ = A$ + B$
  7382.    PRINT C$
  7383.  
  7384.    Output
  7385.  
  7386.    first stringsecond string
  7387.  
  7388.    The process of combining strings in this way is called "concatenation,"
  7389.    which means linking together.
  7390.  
  7391.    Note that in the previous example, the two strings are combined without
  7392.    any intervening spaces. If you want a space in the combined string, you
  7393.    could pad one of the strings A$ or B$, like this:
  7394.  
  7395.    B$ = " second string"          ' Leading blank in B$
  7396.  
  7397.    Because values are left-justified in fixed-length strings, you may find
  7398.    extra spaces when you concatenate them, as in this example:
  7399.  
  7400.    TYPE NameType
  7401.       First AS STRING * 10
  7402.       Last  AS STRING * 12
  7403.    END TYPE
  7404.  
  7405.    DIM NameRecord AS NameType
  7406.  
  7407.    ' The constant "Ed" is left-justified in the variable
  7408.    ' NameRecord.First, so there are eight trailing blanks:
  7409.    NameRecord.First = "Ed"
  7410.    NameRecord.Last  = "Feldstein"
  7411.  
  7412.    ' Print a line of numbers for reference:
  7413.    PRINT "123456789012345678901234567890"
  7414.  
  7415.    WholeName$ = NameRecord.First + NameRecord.Last
  7416.    PRINT WholeName$
  7417.  
  7418.    Output
  7419.  
  7420.    123456789012345678901234567890
  7421.    Ed        Feldstein
  7422.  
  7423.    The LTRIM$ function returns a string with its leading spaces stripped
  7424.    away, while the RTRIM$ function returns a string with its trailing spaces
  7425.    stripped away. The original string is unaltered. (See Section 4.6,
  7426.    "Retrieving Parts of Strings," for more information on these functions.)
  7427.  
  7428.  
  7429.  4.4  Comparing Strings
  7430.  
  7431.    Strings are compared with the following relational operators:
  7432.  
  7433.    Operator                 Meaning
  7434.    ──────────────────────────────────────────────────────────────────────────
  7435.    < >                      Not equal
  7436.  
  7437.    =                        Equal
  7438.  
  7439.    <                        Less than
  7440.  
  7441.    >                        Greater than
  7442.  
  7443.    <=                       Less than or equal to
  7444.  
  7445.    >=                       Greater than or equal to
  7446.    ──────────────────────────────────────────────────────────────────────────
  7447.  
  7448.    A single character is greater than another character if its ASCII value is
  7449.    greater. For example, the ASCII value of the letter "B" is greater than
  7450.    the ASCII value of the letter "A," so the expression "B" > "A"is true.
  7451.  
  7452.    When comparing two strings, BASIC looks at the ASCII values of
  7453.    corresponding characters. The first character where the two strings differ
  7454.    determines the alphabetical order of the strings. For instance, the
  7455.    strings "doorman" and "doormats" are the same up to the seventh character
  7456.    in each ("n" and "t"). Since the ASCII value of "n" is less than the ASCII
  7457.    value of "t", the expression "doorman" < "doormats"is true. Note that the
  7458.    ASCII values for letters follow alphabetical order from A to Z and from a
  7459.    to z, so you can use the relational operators listed above to alphabetize
  7460.    strings. Moreover, uppercase letters have smaller ASCII values than
  7461.    lowercase letters, so in a sorted list of strings, "ASCII" would come
  7462.    before "ascii".
  7463.  
  7464.    If there is no difference between corresponding characters of two strings
  7465.    and they are the same length, then the two strings are equal. If there is
  7466.    no difference between corresponding characters of two strings, but one of
  7467.    the strings is longer, then the longer string is greater than the shorter
  7468.    string. For example "abc" = "abc" and "aaaaaaa" > "aaa" are both true
  7469.    expressions.
  7470.  
  7471.    Leading and trailing blank spaces are significant in string comparisons.
  7472.    For example, the string " test" is less than the string "test", since a
  7473.    blank space (" ") is less than a"t"; on the other hand, the string "test "
  7474.    is greater than the string "test". Keep this in mind when comparing
  7475.    fixed-length and variable-length strings, since fixed-length strings may
  7476.    contain trailing spaces.
  7477.  
  7478.  
  7479.  4.5  Searching for Strings
  7480.  
  7481.    One of the most common string-processing tasks is searching for a string
  7482.    inside another string. The INSTR(string1, string2) function tells you
  7483.    whether or not string2 is contained in string1 by returning the position
  7484.    of the first character in string1 (if any) where the match begins, as
  7485.    shown in this next example:
  7486.  
  7487.    String1$ = "A line of text with 37 letters in it."
  7488.    String2$ = "letters"
  7489.  
  7490.    PRINT "         1         2         3         4"
  7491.    PRINT "1234567890123456789012345678901234567890"
  7492.    PRINT String1$
  7493.    PRINT String2$
  7494.    PRINT INSTR(String1$, String2$)
  7495.  
  7496.    Output
  7497.  
  7498.    1         2         3         4
  7499.    1234567890123456789012345678901234567890
  7500.    A line of text with 37 letters in it.
  7501.    letters
  7502.     24
  7503.  
  7504.    If no match is found (that is, string2 is not a substring of string1),
  7505.    INSTR returns the value 0.
  7506.  
  7507.    A variation of the syntax shown above, INSTR(position, string1, string2),
  7508.    allows you to specify where you want the search to start in string1. To
  7509.    illustrate, making the following modification to the preceding example
  7510.    changes the output:
  7511.  
  7512.    ' Start looking for a match at the 30th
  7513.    ' character of String1$:
  7514.    PRINT INSTR(30, String1$, String2$)
  7515.  
  7516.    Output
  7517.  
  7518.    1         2         3         4
  7519.    1234567890123456789012345678901234567890
  7520.    A line of text with 37 letters in it.
  7521.    letters
  7522.     0
  7523.  
  7524.    In other words, the string "letters" does not appear after the 30th
  7525.    character of String1$.
  7526.  
  7527.    The INSTR(position, string1, string2) variation is useful for finding
  7528.    every occurrence of string2 in string1 instead of just the first
  7529.    occurrence, as shown in the next example:
  7530.  
  7531.    String1$ = "the dog jumped over the broken saxophone."
  7532.    String2$ = "the"
  7533.    PRINT String1$
  7534.  
  7535.    Start      = 1
  7536.    NumMatches = 0
  7537.  
  7538.    DO
  7539.       Match = INSTR(Start, String1$, String2$)
  7540.       IF Match > 0 THEN
  7541.          PRINT TAB(Match); String2$
  7542.          Start      = Match + 1
  7543.          NumMatches = NumMatches + 1
  7544.       END IF
  7545.    LOOP WHILE MATCH
  7546.  
  7547.    PRINT "Number of matches ="; NumMatches
  7548.  
  7549.    Output
  7550.  
  7551.    the dog jumped over the broken saxophone.
  7552.    the
  7553.                                      the
  7554.    Number of matches = 2
  7555.  
  7556.  
  7557.  4.6  Retrieving Parts of Strings
  7558.  
  7559.    Section 4.3, "Combining Strings," shows how to put strings together
  7560.    (concatenate them) by using the + operator. Several functions are
  7561.    available in BASIC that take strings apart, returning pieces of a string,
  7562.    either from the left side, the right side, or the middle of a target
  7563.    string.
  7564.  
  7565.  4.6.1  Retrieving Characters from the Left Side of a String
  7566.  
  7567.    The LEFT$ and RTRIM$ functions return characters from the left side of a
  7568.    string. The LEFT$(string, number) function returns the specified number of
  7569.    characters from the left side of the string. For example:
  7570.  
  7571.    Test$ = "Overtly"
  7572.  
  7573.    ' Print the leftmost 4 characters from Test$:
  7574.    PRINT LEFT$(Test$, 4)
  7575.  
  7576.    Output
  7577.  
  7578.    Over
  7579.  
  7580.    Note that LEFT$, like the other functions described in this chapter, does
  7581.    not change the original string Test$; it merely returns a different
  7582.    string, a copy of part of Test$.
  7583.  
  7584.    The RTRIM$ function returns the left part of a string after removing any
  7585.    blank spaces at the end. For example, contrast the output from the two
  7586.    PRINT statements in the following example:
  7587.  
  7588.    PRINT "a left-justified string      "; "next"
  7589.    PRINT RTRIM$("a left-justified string      "); "next"
  7590.  
  7591.    Output
  7592.  
  7593.    a left-justified string      next
  7594.    a left-justified stringnext
  7595.  
  7596.    The RTRIM$ function is useful for comparing fixed-length and
  7597.    variable-length strings, as in the next example:
  7598.  
  7599.    DIM NameRecord AS STRING * 10
  7600.    NameRecord = "Ed"
  7601.  
  7602.    NameTest$ = "Ed"
  7603.  
  7604.    ' Use RTRIM$ to trim all the blank spaces from the right
  7605.    ' side of the fixed-length string NameRecord, then compare
  7606.    ' it with the variable-length string NameTest$:
  7607.    IF RTRIM$(NameRecord) = NameTest$ THEN
  7608.       PRINT "They're equal"
  7609.    ELSE
  7610.       PRINT "They're not equal"
  7611.    END IF
  7612.  
  7613.    Output
  7614.  
  7615.    They're equal
  7616.  
  7617.  4.6.2  Retrieving Characters from the Right Side of a String
  7618.  
  7619.    The RIGHT$ and LTRIM$ functions return characters from the right side of a
  7620.    string. The RIGHT$(string, number) function returns the specified number
  7621.    of characters from the right side of the string. For example:
  7622.  
  7623.    Test$ = "1234567890"
  7624.  
  7625.    ' Print the rightmost 5 characters from Test$:
  7626.    PRINT RIGHT$(Test$,5)
  7627.  
  7628.    Output
  7629.  
  7630.    67890
  7631.  
  7632.    The LTRIM$ function returns the right part of a string after removing any
  7633.    blank spaces at the beginning. For example, contrast the output from the
  7634.    next two PRINT statements:
  7635.  
  7636.    PRINT "first"; "      a right-justified string"
  7637.    PRINT "first"; LTRIM$("      a right-justified string")
  7638.  
  7639.    Output
  7640.  
  7641.    first      a right-justified string
  7642.    firsta right-justified string
  7643.  
  7644.  4.6.3  Retrieving Characters from Anywhere in a String
  7645.  
  7646.    Use the MID$ function to retrieve any number of characters from any point
  7647.    in a string. The MID$(string, start, number) function returns the
  7648.    specified number of characters from the string, starting at the character
  7649.    with position start. For example, the statement
  7650.  
  7651.    MID$("**over the hill**", 12, 4)
  7652.  
  7653.    starts at the twelfth character (or h) of the string
  7654.  
  7655.    **over the hill**
  7656.  
  7657.    and returns that character plus the next three characters (hill).
  7658.  
  7659.    The following example shows how to use the MID$ function to step through a
  7660.    line of text character by character:
  7661.  
  7662.    .
  7663.    .
  7664.    .
  7665.    ' Get the number of characters in the string of text:
  7666.    Length = LEN(TextString$)
  7667.  
  7668.    FOR I = 1 TO Length
  7669.  
  7670.      ' Get the first character, then the second, third,
  7671.      ' and so forth, up to the end of the string:
  7672.      Char$ = MID$(TextString$, I, 1)
  7673.  
  7674.      ' Evaluate that character:
  7675.      .
  7676.      .
  7677.      .
  7678.    NEXT
  7679.  
  7680.  
  7681.  4.7  Generating Strings
  7682.  
  7683.    The easiest way to create a string of one character repeated over and over
  7684.    is to use the intrinsic function STRING$. The STRING$(number, string)
  7685.    function produces a new string the specified number of characters long,
  7686.    each character of which is the first character of the string argument. For
  7687.    example, the statement
  7688.  
  7689.    Filler$ = STRING$(27, "*")
  7690.  
  7691.    generates a string of 27 asterisks. For characters that cannot be produced
  7692.    by typing, such as characters whose ASCII values are greater than 127, use
  7693.    the alternative form of this function, STRING$(number, code). This form
  7694.    creates a string the specified number of characters long, each character
  7695.    of which has the ASCII code specified by the code argument, as in the next
  7696.    example:
  7697.  
  7698.    ' Print a string of 10 "@" characters
  7699.    ' (64 is ASCII code for @):
  7700.    PRINT STRING$(10, 64)
  7701.  
  7702.    Output
  7703.  
  7704.    @@@@@@@@@@@
  7705.  
  7706.    The SPACE$(number) function generates a string consisting of the specified
  7707.    number of blank spaces.
  7708.  
  7709.  
  7710.  4.8  Changing the Case of Letters
  7711.  
  7712.    You may want to convert uppercase (capital) letters in a string to
  7713.    lowercase or vice versa. This conversion would be useful in a
  7714.    case-insensitive search for a particular string pattern in a large file
  7715.    (in other words, help, HELP, or Help would all be considered the same).
  7716.    These functions would also be handy when you are not sure whether a user
  7717.    will input text in capital or lowercase letters.
  7718.  
  7719.    The UCASE$ and LCASE$ functions make the following conversions to a
  7720.    string:
  7721.  
  7722.    ■ UCASE$ returns a copy of the string passed to it, with all the lowercase
  7723.      letters converted to uppercase.
  7724.  
  7725.    ■ LCASE$ returns a copy of the string passed to it, with all the uppercase
  7726.      letters converted to lowercase.
  7727.  
  7728.    Example
  7729.  
  7730.    Sample$ = "* The ASCII Appendix: a table
  7731.    of useful codes *"
  7732.    PRINT Sample$
  7733.    PRINT UCASE$(Sample$)
  7734.    PRINT LCASE$(Sample$)
  7735.  
  7736.    Output
  7737.  
  7738.    * The ASCII Appendix: a table of useful codes *
  7739.    * THE ASCII APPENDIX: A TABLE OF USEFUL CODES *
  7740.    * the ascii appendix: a table of useful codes *
  7741.  
  7742.    Letters that are already uppercase, as well as characters that are not
  7743.    letters, remain unchanged by UCASE$; similarly, lowercase letters and
  7744.    characters that are not letters are unaffected by LCASE$.
  7745.  
  7746.  
  7747.  4.9  Strings and Numbers
  7748.  
  7749.    BASIC does not allow a string to be assigned to a numeric variable, nor
  7750.    does it allow a numeric expression to be assigned to a string variable.
  7751.    For example, both of these statements result in an error message reading
  7752.    Type mismatch:
  7753.  
  7754.    TempBuffer$ = 45
  7755.    Counter% = "45"
  7756.  
  7757.    Instead, use the STR$ function to return the string representation of a
  7758.    number or the VAL function to return the numeric representation of a
  7759.    string:
  7760.  
  7761.    ' The following statements are both valid:
  7762.    TempBuffer$ = STR$(45)
  7763.    Counter%  = VAL("45")
  7764.  
  7765.    Note that STR$ includes the leading blank space that BASIC prints for
  7766.    positive numbers, as this short example shows:
  7767.  
  7768.    FOR I = 0 TO 9
  7769.       PRINT STR$(I);
  7770.    NEXT
  7771.  
  7772.    Output
  7773.  
  7774.    0 1 2 3 4 5 6 7 8 9
  7775.  
  7776.    If you want to eliminate this space, you can use the LTRIM$ function, as
  7777.    shown in the example below:
  7778.  
  7779.    FOR I = 0 TO 9
  7780.       PRINT LTRIM$(STR$(I));
  7781.    NEXT
  7782.  
  7783.    Output
  7784.  
  7785.    0123456789
  7786.  
  7787.    Another way to format numeric output is with the PRINT USING statement
  7788.    (see Section 3.1, "Printing Text on the Screen").
  7789.  
  7790.  
  7791.  4.10  Changing Strings
  7792.  
  7793.    The functions mentioned in each of the preceding sections all leave their
  7794.    string arguments unchanged. Changes are made to a copy of the argument.
  7795.  
  7796.    In contrast, the MID$ statement (unlike the MID$ function discussed in
  7797.    Section 4.6.3, "Retrieving Characters from Anywhere in a String") changes
  7798.    its argument by embedding another string in it. The embedded string
  7799.    replaces part or all of the original string, as shown in the following
  7800.    example:
  7801.  
  7802.    Temp$ = "In the sun."
  7803.    PRINT Temp$
  7804.  
  7805.    ' Replace the "I" with an "O":
  7806.    MID$(Temp$,1) = "O"
  7807.  
  7808.    ' Replace "sun." with "road":
  7809.    MID$(Temp$,8) = "road"
  7810.    PRINT Temp$
  7811.  
  7812.    Output
  7813.  
  7814.    In the sun.
  7815.    On the road
  7816.  
  7817.  
  7818.  4.11  Sample Application: Converting a String to a Number (STRTONUM.BAS)
  7819.  
  7820.    The following program takes a number that is input as a string, filters
  7821.    any numeric characters (such as commas) out of the string, then converts
  7822.    the string to a number with the VAL function.
  7823.  
  7824.    Statements and Functions Used
  7825.  
  7826.    This program demonstrates the following string-handling functions
  7827.    discussed in this chapter:
  7828.  
  7829.    ■ INSTR
  7830.  
  7831.    ■ LEN
  7832.  
  7833.    ■ MID$
  7834.  
  7835.    ■ VAL
  7836.  
  7837.    Program Listing
  7838.  
  7839.    DECLARE FUNCTION Filter$ (Txt$, FilterString$)
  7840.  
  7841.    ' Input a line:
  7842.    LINE INPUT "Enter a number with commas: ", A$
  7843.  
  7844.    ' Look only for valid numeric characters (0123456789.-)
  7845.    ' in the input string:
  7846.    CleanNum$ = Filter$(A$, "0123456789.-")
  7847.  
  7848.    ' Convert the string to a number:
  7849.    PRINT "The number's value = " VAL(CleanNum$)
  7850.    END
  7851.  
  7852.    ' ========================== FILTER =======================
  7853.    '         Takes unwanted characters out of a string by
  7854.    '         comparing them with a filter string containing
  7855.    '         only acceptable numeric characters
  7856.    ' =========================================================
  7857.  
  7858.    FUNCTION Filter$ (Txt$, FilterString$) STATIC
  7859.       Temp$ = ""
  7860.       TxtLength = LEN(Txt$)
  7861.  
  7862.       FOR I = 1 TO TxtLength     ' Isolate each character in
  7863.          C$ = MID$(Txt$, I, 1)   ' the string.
  7864.  
  7865.          ' If the character is in the filter string, save it:
  7866.          IF INSTR(FilterString$, C$) <> 0 THEN
  7867.             Temp$ = Temp$ + C$
  7868.          END IF
  7869.       NEXT I
  7870.  
  7871.       Filter$ = Temp$
  7872.    END FUNCTION
  7873.  
  7874.  
  7875.  
  7876.  ────────────────────────────────────────────────────────────────────────────
  7877.  Chapter 5  Graphics
  7878.  
  7879.    This chapter shows you how to use the graphics statements and functions of
  7880.    BASIC to create a wide variety of shapes, colors, and patterns on your
  7881.    screen. With graphics, you can add a visual dimension to almost any
  7882.    program, whether it's a game, an educational tool, a scientific
  7883.    application, or a financial package.
  7884.  
  7885.    When you have finished studying this chapter, you will know how to perform
  7886.    the following graphics tasks:
  7887.  
  7888.    ■ Use the physical-coordinate system of your personal computer's screen to
  7889.      locate individual pixels, turn those pixels on or off, and change their
  7890.      colors
  7891.  
  7892.    ■ Draw lines
  7893.  
  7894.    ■ Draw and fill simple shapes, such as circles, ovals, and boxes
  7895.  
  7896.    ■ Restrict the area of the screen showing graphics output by using
  7897.      viewports
  7898.  
  7899.    ■ Adjust the coordinates used to locate a pixel by redefining screen
  7900.      coordinates
  7901.  
  7902.    ■ Use color in graphics output
  7903.  
  7904.    ■ Create patterns and use them to fill enclosed figures
  7905.  
  7906.    ■ Copy images and reproduce them in another location on the screen
  7907.  
  7908.    ■ Animate graphics output
  7909.  
  7910.    Section 5.1 below contains important information on what you'll need to
  7911.    run the graphics examples shown in this chapter. Read it first.
  7912.  
  7913.  
  7914.  5.1  What You Need for Graphics Programs
  7915.  
  7916.    To run the graphics examples shown in this chapter, your computer must
  7917.    have graphics capability, either built in or in the form of a graphics
  7918.    card such as the Color Graphics Adapter (CGA), Enhanced Graphics Adapter
  7919.    (EGA), or Video Graphics Array (VGA). You also need a video display
  7920.    (either monochrome or color) that supports pixel-based graphics.
  7921.  
  7922.    Also, please keep in mind that these programs all require that your screen
  7923.    be in one of the "screen modes" supporting graphics output. (The screen
  7924.    mode controls the clarity of graphics images, the number of colors
  7925.    available, and the part of the video memory to display.) To select a
  7926.    graphics output mode, use the following statement in your program before
  7927.    using any of the graphics statements or functions described in this
  7928.    chapter:
  7929.  
  7930.    SCREEN mode
  7931.  
  7932.    Here, mode can be either 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, or 13, depending
  7933.    on the monitor/adapter combination installed on your computer.
  7934.  
  7935.    If you are not sure whether or not the users of your programs have
  7936.    hardware that supports graphics, you can use the following simple test:
  7937.  
  7938.    CONST FALSE = 0, TRUE = NOT FALSE
  7939.  
  7940.    ' Test to make sure user has hardware
  7941.    ' with color/graphics capability:
  7942.    ON ERROR GOTO Message      ' Turn on error trapping.
  7943.    SCREEN 1                   ' Try graphics mode one.
  7944.    ON ERROR GOTO 0            ' Turn off error trapping.
  7945.    IF NoGraphics THEN END     ' End if no graphics hardware.
  7946.    .
  7947.    .
  7948.    .
  7949.    END
  7950.  
  7951.    ' Error-handling routine:
  7952.    Message:
  7953.       PRINT "This program requires graphics capability."
  7954.       NoGraphics = TRUE
  7955.       RESUME NEXT
  7956.  
  7957.    If the user has only a monochrome display with no graphics adapter, the
  7958.    SCREEN statement produces an error that in turn triggers a branch to the
  7959.    error-handling routine Message. (See Chapter 6, "Error and Event
  7960.    Trapping," for more information on error trapping.)
  7961.  
  7962.  
  7963.  5.2  Pixels and Screen Coordinates
  7964.  
  7965.    Shapes and figures on a video display are composed of individual dots of
  7966.    light known as picture elements or "pixels" (or sometimes as "pels") for
  7967.    short. BASIC draws and paints on the screen by turning these pixels on or
  7968.    off and by changing their colors.
  7969.  
  7970.    A typical screen is composed of a grid of pixels. The exact number of
  7971.    pixels in this grid depends on the hardware you have installed and the
  7972.    screen mode you have selected in the SCREEN statement. The larger the
  7973.    number of pixels, the higher the clarity of graphics output. For example,
  7974.    a SCREEN 1 statement gives a resolution of 320 pixels horizontally by 200
  7975.    pixels vertically (320 x 200 pixels), while a SCREEN 2 statement gives a
  7976.    resolution of 640 x 200 pixels. The higher horizontal density in screen
  7977.    mode 2──640 pixels per row versus 320 pixels per row──gives images a
  7978.    sharper, less ragged appearance than they have in screen mode 1.
  7979.  
  7980.    Depending on the graphics capability of your system, you can use other
  7981.    screen modes that support even higher resolutions (as well as adjust other
  7982.    screen characteristics). Consult the QB Advisor for more information.
  7983.  
  7984.    When your screen is in one of the graphics modes, you can locate each
  7985.    pixel by means of pairs of coordinates. The first number in each
  7986.    coordinate pair tells the number of pixels from the left side of the
  7987.    screen, while the second number in each pair tells the number of pixels
  7988.    from the top of the screen. For example, in screen mode 2 the point in the
  7989.    extreme upper-left corner of the screen has coordinates (0, 0), the point
  7990.    in the center of the screen has coordinates (320, 100), and the point in
  7991.    the extreme lower-right corner of the screen has coordinates (639, 199),
  7992.    as shown in Figure 5.1.
  7993.  
  7994.    BASIC uses these screen coordinates to determine where to display graphics
  7995.    (for example, to locate the end points of a line or the center of a
  7996.    circle), as shown in Section 5.3, "Drawing Basic Shapes."
  7997.  
  7998.    Graphics coordinates differ from text-mode coordinates specified in a
  7999.    LOCATE statement. First, LOCATE is not as precise: graphics coordinates
  8000.    pinpoint individual pixels on the screen, whereas coordinates used by
  8001.    LOCATE are character positions. Second, text-mode coordinates are given in
  8002.    the form "row, column," as in the following:
  8003.  
  8004.    ' Move to the 13th row, 15th column,
  8005.    ' then print the message shown:
  8006.    LOCATE 13, 15
  8007.    PRINT "This should appear in the middle of the screen."
  8008.  
  8009.    This is the reverse of graphics coordinates, which are given in the form
  8010.    "column, row." A LOCATE statement has no effect on the positioning of
  8011.    graphics output on the screen.
  8012.  
  8013.  
  8014.    ┌──────────────────────────────────────────────────────────────────┐
  8015.    │                              x positive                          │
  8016.    │              ────────────────────────────────────────────       │
  8017.    │            ┌──────────────────────────────────────────────────┐  │
  8018.    │          │ │°(0,0)                °(320,0)            (639,0)°│  │
  8019.    │          │ │                                                  │  │
  8020.    │          │ │                                                  │  │
  8021.    │          │ │                                                  │  │
  8022.    │          │ │                                                  │  │
  8023.    │   y      │ │                      °(320,100)                  │  │
  8024.    │ positive │ │                                                  │  │
  8025.    │          │ │                                                  │  │
  8026.    │          │ │                                                  │  │
  8027.    │          │ │                                                  │  │
  8028.    │          │ │                                                  │  │
  8029.    │           │°(0,199)              °(320,199)        (639,199)°│  │
  8030.    │            └──────────────────────────────────────────────────┘  │
  8031.    └──────────────────────────────────────────────────────────────────┘
  8032.  
  8033.    Figure 5.1  Coordinates of Selected Pixels in Screen Mode 2
  8034.  
  8035.  
  8036.  5.3  Drawing Basic Shapes: Points, Lines, Boxes, and Circles
  8037.  
  8038.    You can pass coordinate values to BASIC graphics statements to produce a
  8039.    variety of simple figures, as shown in Sections 5.3.1-5.3.2.
  8040.  
  8041.  5.3.1  Plotting Points with PSET and PRESET
  8042.  
  8043.    The most fundamental level of control over graphics output is simply
  8044.    turning individual pixels on and off. You do this in BASIC with the PSET
  8045.    (for pixel set) and PRESET (for pixel reset) statements. The statement
  8046.    PSET (x, y) gives the pixel at location (x, y) the current foreground
  8047.    color. The PRESET (x, y) statement gives the pixel at location (x, y) the
  8048.    current background color.
  8049.  
  8050.    On monochrome monitors, the foreground color is the color that is used for
  8051.    printed text and is typically white, amber, or light green; the background
  8052.    color on monochrome monitors is typically black or dark green. You can
  8053.    choose another color for PSET and PRESET to use by adding an optional
  8054.    color argument. The syntax is then:
  8055.  
  8056.    PSET (x, y), color
  8057.  
  8058.    or
  8059.  
  8060.    PRESET (x, y), color
  8061.  
  8062.    See Section 5.7 for more information on choosing colors.
  8063.  
  8064.    Because PSET uses the current foreground color by default and PRESET uses
  8065.    the current background color by default, PRESET without a color argument
  8066.    erases a point drawn with PSET, as shown in the next example:
  8067.  
  8068.    SCREEN 2          ' 640 x 200 resolution
  8069.    PRINT "Press any key to end."
  8070.  
  8071.    DO
  8072.  
  8073.       ' Draw a horizontal line from the left to the right:
  8074.       FOR X = 0 TO 640
  8075.          PSET (X, 100)
  8076.       NEXT
  8077.  
  8078.       ' Erase the line from the right to the left:
  8079.       FOR X = 640 TO 0 STEP -1
  8080.          PRESET (X, 100)
  8081.       NEXT
  8082.  
  8083.    LOOP UNTIL INKEY$ <> ""
  8084.    END
  8085.  
  8086.    While it is possible to draw any figure using only PSET statements to
  8087.    manipulate individual pixels, the output tends to be rather slow, since
  8088.    most pictures consist of many pixels. BASIC has several statements that
  8089.    dramatically increase the speed with which simple figures──such as lines,
  8090.    boxes, and ellipses──are drawn, as shown in Sections 5.3.2 and
  8091.    5.4.1-5.4.4.
  8092.  
  8093.  5.3.2  Drawing Lines and Boxes with LINE
  8094.  
  8095.    When using PSET or PRESET, you specify only one coordinate pair since you
  8096.    are dealing with only one point on the screen. With LINE, you specify two
  8097.    pairs, one for each end of a line segment. The simplest form of the LINE
  8098.    statement is as follows:
  8099.  
  8100.    LINE (x1, y1) - (x2, y2)
  8101.  
  8102.    where (x1, y1) are the coordinates of one end of a line segment and (x2,
  8103.    y2) are the coordinates of the other. For example, the following statement
  8104.    draws a straight line from the pixel with coordinates (10, 10) to the
  8105.    pixel with coordinates (150, 200):
  8106.  
  8107.    SCREEN 1
  8108.    LINE (10, 10)-(150, 200)
  8109.  
  8110.    Note that BASIC does not care about the order of the coordinate pairs: a
  8111.    line from (x1, y1) to (x2, y2) is the same as a line from (x2, y2) to (x1,
  8112.    y1). This means you could also write the preceding statement as:
  8113.  
  8114.    SCREEN 1
  8115.    LINE (150, 200)-(10, 10)
  8116.  
  8117.    However, reversing the order of the coordinates could have an effect on
  8118.    graphics statements that follow, as shown in the next section.
  8119.  
  8120.    5.3.2.1  Using the STEP Option
  8121.  
  8122.    Up to this point, screen coordinates have been presented as absolute
  8123.    values measuring the horizontal and vertical distances from the extreme
  8124.    upper-left corner of the screen, which has coordinates (0, 0). However, by
  8125.    using the STEP option in any of the following graphics statements, you can
  8126.    make the coordinates that follow STEP relative to the last point
  8127.    referenced on the screen:
  8128.  
  8129.    CIRCLE
  8130.    GET
  8131.    LINE
  8132.    PAINT
  8133.    PRESET
  8134.    PSET
  8135.    PUT
  8136.  
  8137.    If you picture images as being drawn on the screen by a tiny paintbrush
  8138.    exactly the size of one pixel, then the last point referenced is the
  8139.    location of this paintbrush, or "graphics cursor," when it finishes
  8140.    drawing an image. For example, the following statements leave the graphics
  8141.    cursor at the pixel with coordinates (100, 150):
  8142.  
  8143.    SCREEN 2
  8144.    LINE (10, 10)-(100, 150)
  8145.  
  8146.    If the next graphics statement in the program is
  8147.  
  8148.    PSET STEP(20, 20)
  8149.  
  8150.    then the point plotted by PSET is not in the upper-left quadrant of the
  8151.    screen. Instead, the STEP option has made the coordinates (20, 20)
  8152.    relative to the last point referenced, which has coordinates (100, 150).
  8153.    This makes the absolute coordinates of the point (100 + 20, 150 + 20) or
  8154.    (120, 170).
  8155.  
  8156.    In the last example, the last point referenced is determined by a
  8157.    preceding graphics statement. You can also establish a reference point
  8158.    within the same statement, as shown in the next example:
  8159.  
  8160.    ' Set 640 x 200 pixel resolution, and make the last
  8161.    ' point referenced the center of the screen:
  8162.    SCREEN 2
  8163.  
  8164.    ' Draw a line from the lower-left corner of the screen
  8165.    ' to the upper-left corner:
  8166.    LINE STEP(-310, 100) -STEP(0, -200)
  8167.  
  8168.    ' Draw the "stair steps" down from the upper-left corner
  8169.    ' to the right side of the screen:
  8170.    FOR I% = 1 TO 20
  8171.       LINE -STEP(30, 0)     ' Draw the horizontal line.
  8172.       LINE -STEP(0, 5)      ' Draw the vertical line.
  8173.    NEXT
  8174.  
  8175.    ' Draw the unconnected vertical line segments from the
  8176.    ' right side to the lower-left corner:
  8177.    FOR I% = 1 TO 20
  8178.       LINE STEP(-30, 0) -STEP(0, 5)
  8179.    NEXT
  8180.  
  8181.    DO: LOOP WHILE INKEY$ = ""       ' Wait for a keystroke.
  8182.  
  8183.    Output
  8184.  
  8185.    ┌──────────────────────────────────────────────────────────────────┐
  8186.    │ ┌─┐                                                              │
  8187.    │ │ └──────┐                                                       │
  8188.    │ │        └──────┐                                                │
  8189.    │ │               └──────┐                                         │
  8190.    │ │                      └──────┐                                  │
  8191.    │ │                             └──────┐                           │
  8192.    │ │                                    └──────┐                    │
  8193.    │ │                                           └──────┐             │
  8194.    │ │                                                  └──────┐      │
  8195.    │ │                                                                │
  8196.    │ │                                                  │             │
  8197.    │ │                                           │                    │
  8198.    │ │                                    │                           │
  8199.    │ │                             │                                  │
  8200.    │ │                      │                                         │
  8201.    │ │               │                                                │
  8202.    │ │        │                                                       │
  8203.    │ │ │                                                              │
  8204.    └──────────────────────────────────────────────────────────────────┘
  8205.  
  8206.    ──────────────────────────────────────────────────────────────────────────
  8207.    NOTE
  8208.      Note the empty DO loop at the end of the last program. If you are
  8209.      running a compiled, stand-alone BASIC program that produces graphics
  8210.      output, your program needs some mechanism like this at the end to hold
  8211.      the output on the screen. Otherwise, it vanishes from the screen before
  8212.      the user has time to notice it.
  8213.    ──────────────────────────────────────────────────────────────────────────
  8214.  
  8215.    5.3.2.2  Drawing Boxes
  8216.  
  8217.    Using the forms of the LINE statement already presented, it is quite easy
  8218.    to write a short program that connects four straight lines to form a box,
  8219.    as shown here:
  8220.  
  8221.    SCREEN 1        ' 320 x 200 pixel resolution
  8222.  
  8223.    ' Draw a box measuring 120 pixels on a side:
  8224.    LINE (50, 50)-(170, 50)
  8225.    LINE -STEP(0, 120)
  8226.    LINE -STEP(-120, 0)
  8227.    LINE -STEP(0, -120)
  8228.  
  8229.    However, BASIC provides an even simpler way to draw a box, using a single
  8230.    LINE statement with the B (for box) option. The B option is shown in the
  8231.    next example, which produces the same output as the four LINE statements
  8232.    in the preceding program:
  8233.  
  8234.    SCREEN 1        ' 320 x 200 pixel resolution
  8235.  
  8236.    ' Draw a box with coordinates (50, 50) for the upper-left
  8237.    ' corner, and (170, 170) for the lower-right corner:
  8238.    LINE (50, 50)-(170, 170), , B
  8239.  
  8240.    When you add the B option, the LINE statement no longer connects the two
  8241.    points you specify with a straight line; instead, it draws a rectangle
  8242.    whose opposite corners (upper left and lower right) are at the locations
  8243.    specified.
  8244.  
  8245.    Two commas precede the B in the last example. The first comma functions
  8246.    here as a placeholder for an unused option (the color argument), which
  8247.    allows you to pick the color for a line or the sides of a box. (See
  8248.    Section 5.7 for more information on the use of color.)
  8249.  
  8250.    As before, it does not matter what order the coordinate pairs are given
  8251.    in, so the rectangle from the last example could also be drawn with this
  8252.    statement:
  8253.  
  8254.    LINE (170, 170)-(50, 50), , B
  8255.  
  8256.    Adding the F (for fill) option after B fills the interior of the box with
  8257.    the same color used to draw the sides. With a monochrome display, this is
  8258.    the same as the foreground color used for printed text. If your hardware
  8259.    has color capabilities, you can change this color with the optional color
  8260.    argument (see Section 5.7.1, "Selecting a Color for Graphics Output").
  8261.  
  8262.    The syntax introduced here for drawing a box is the general syntax used in
  8263.    BASIC to define a rectangular graphics region, and it also appears in the
  8264.    GET and VIEW statements:
  8265.  
  8266.    {GET| LINE| VIEW} (x1, y1) - (x2, y2),...
  8267.  
  8268.    Here, (x1, y1) and (x2, y2) are the coordinates of diagonally opposite
  8269.    corners of the rectangle (upper left and lower right). (See Section 5.5,
  8270.    "Defining a Graphics Viewport," for a discussion of VIEW, and Section
  8271.    5.10, "Basic Animation Techniques," for information on GET and PUT.)
  8272.  
  8273.    5.3.2.3  Drawing Dotted Lines
  8274.  
  8275.    The previous sections explain how to use LINE to draw solid lines and use
  8276.    them in rectangles; that is, no pixels are skipped. Using yet another
  8277.    option with LINE, you can draw dashed or dotted lines instead. This
  8278.    process is known as "line styling." The following is the syntax for
  8279.    drawing a single dashed line from point (x1, y1) to point (x2, y2) using
  8280.    the current foreground color:
  8281.  
  8282.    LINE (x1,y1) - (x2,y2), ,[[B]], style
  8283.  
  8284.    Here style is a 16-bit decimal or hexadecimal integer. The LINE statement
  8285.    uses the binary representation of the line-style argument to create dashes
  8286.    and blank spaces, with a 1 bit meaning "turn on the pixel," and a 0 bit
  8287.    meaning "leave the pixel off." For example, the hexadecimal integer &HCCCC
  8288.    is equal to the binary integer 1100110011001100, and when used as a style
  8289.    argument it draws a line alternating two pixels on, two pixels off.
  8290.  
  8291.    Example
  8292.  
  8293.    The following example shows different dashed lines produced using
  8294.    different values for style:
  8295.  
  8296.    SCREEN 2        ' 640 x 200 pixel resolution
  8297.  
  8298.    ' Style data:
  8299.    DATA &HCCCC, &HFF00, &HF0F0
  8300.    DATA &HF000, &H7777, &H8888
  8301.  
  8302.    Row% = 4
  8303.    Column% = 4
  8304.    XLeft% = 60
  8305.    XRight% = 600
  8306.    Y% = 28
  8307.  
  8308.    FOR I% = 1 TO 6
  8309.       READ Style%
  8310.       LOCATE Row%, Column%
  8311.       PRINT HEX$(Style%)
  8312.       LINE (XLeft%, Y%)-(XRight%,Y%), , , Style%
  8313.       Row% = Row% + 3
  8314.       Y% = Y% + 24
  8315.    NEXT
  8316.  
  8317.    Output
  8318.  
  8319.    ┌───────────────────────────────────────────────────────────────────┐
  8320.    │                                                                   │
  8321.    │                                                                   │
  8322.    │ CCCC····························································· │
  8323.    │                                                                   │
  8324.    │ FF00------------------------------------------------------------- │
  8325.    │                                                                   │
  8326.    │ F0F0 │
  8327.    │                                                                   │
  8328.    │ F000- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - │
  8329.    │                                                                   │
  8330.    │ 7777───────────────────────────────────────────────────────────── │
  8331.    │                                                                   │
  8332.    │ 8888............................................................. │
  8333.    │                                                                   │
  8334.    │                                                                   │
  8335.    │                                                                   │
  8336.    └───────────────────────────────────────────────────────────────────┘
  8337.  
  8338.  
  8339.  5.4  Drawing Circles and Ellipses with CIRCLE
  8340.  
  8341.    The CIRCLE statement draws a variety of circular and elliptical, or oval,
  8342.    shapes. In addition, CIRCLE draws arcs (segments of circles), and
  8343.    pie-shaped wedges. In graphics mode you can produce just about any kind of
  8344.    curved line with some variation of CIRCLE.
  8345.  
  8346.  5.4.1  Drawing Circles
  8347.  
  8348.    To draw a circle, you need to know only two things: the location of its
  8349.    center and the length of its radius (the distance from the center to any
  8350.    point on the circle). With this information and a reasonably steady hand
  8351.    (or better yet, a compass), you can produce an attractive circle.
  8352.  
  8353.    Similarly, BASIC needs only the location of a circle's center and the
  8354.    length of its radius to draw a circle. The simplest form of the CIRCLE
  8355.    syntax is
  8356.  
  8357.    CIRCLE[[STEP]](x, y), radius
  8358.  
  8359.    where x, y are the coordinates of the center, and radius is the radius of
  8360.    the circle. The next example draws a circle with center (200, 100) and
  8361.    radius 75:
  8362.  
  8363.    SCREEN 2
  8364.    CIRCLE (200, 100), 75
  8365.  
  8366.    You could rewrite the preceding example as follows, making the same circle
  8367.    but using the STEP option to make the coordinates relative to the center
  8368.    rather than to the upper-left corner:
  8369.  
  8370.    SCREEN 2       ' Uses center of screen (320,100) as the
  8371.                   ' reference point for the CIRCLE statement:
  8372.    CIRCLE STEP(-120, 0), 75
  8373.  
  8374.  5.4.2  Drawing Ellipses
  8375.  
  8376.    The CIRCLE statement automatically adjusts the "aspect ratio" to make sure
  8377.    that circles appear round and not flattened on your screen. However, you
  8378.    may need to adjust the aspect ratio to make circles come out right on your
  8379.    monitor, or you may want to change the aspect ratio to draw the oval
  8380.    figure known as an ellipse. In either case, use the syntax
  8381.  
  8382.    CIRCLE[[STEP]] (x,y), radius, , , , aspect
  8383.  
  8384.    where aspect is a positive real number. (See Section 5.4.5 for more
  8385.    information on the aspect ratio and how to calculate it for different
  8386.    screen modes.)
  8387.  
  8388.    The extra commas between radius and aspect are placeholders for other
  8389.    options that tell CIRCLE which color to use (if you have a color
  8390.    monitor/adapter and are using one of the screen modes that support color),
  8391.    or whether to draw an arc or wedge. (See Sections 5.4.3, "Drawing Arcs,"
  8392.    and 5.7.1, "Selecting a Color for Graphics Output," for more information
  8393.    on these options.)
  8394.  
  8395.    Since the aspect argument specifies the ratio of the vertical to
  8396.    horizontal dimensions, large values for aspect produce ellipses stretched
  8397.    out along the vertical axis, while small values for aspect produce
  8398.    ellipses stretched out along the horizontal axis. Since an ellipse has two
  8399.    radii──one horizontal x-radius and one vertical y-radius──BASIC uses the
  8400.    single radius argument in a CIRCLE statement as follows: if aspect is less
  8401.    than one, then radius is the x-radius; if aspect is greater than or equal
  8402.    to one, then radius is the y-radius.
  8403.  
  8404.    Example
  8405.  
  8406.    The following example and its output show how different aspect values
  8407.    affect whether the CIRCLE statement uses the radius argument as the
  8408.    x-radius or the y-radius of an ellipse:
  8409.  
  8410.    SCREEN 1
  8411.  
  8412.    ' This draws the ellipse on the left:
  8413.    CIRCLE (60, 100), 80, , , , 3
  8414.  
  8415.    ' This draws the ellipse on the right:
  8416.    CIRCLE (180, 100), 80, , , , 3/10
  8417.  
  8418.    Output
  8419.  
  8420.    ┌────────────────────────────────────┐
  8421.    │                                    │
  8422.    │     The output for this example    │
  8423.    │     can be found on page 160 of    │
  8424.    │     the printed manual.            │
  8425.    │                                    │
  8426.    └────────────────────────────────────┘
  8427.  
  8428.  5.4.3  Drawing Arcs
  8429.  
  8430.    An arc is a segment of a ellipse, in other words a short, curved line. To
  8431.    understand how the CIRCLE statement draws arcs, you need to know how BASIC
  8432.    measures angles.
  8433.  
  8434.    BASIC uses the radian as its unit of angle measure, not only in the CIRCLE
  8435.    statement, but also in the intrinsic trigonometric functions such as COS,
  8436.    SIN, or TAN. (The one exception to this use of radians is the DRAW
  8437.    statement, which expects angle measurements in degrees. See Section 5.9
  8438.    for more information about DRAW.)
  8439.  
  8440.    The radian is closely related to the radius of a circle. In fact, the word
  8441.    "radian" is derived from the word "radius." The circumference of a circle
  8442.    equals 2 * π * radius, where π is equal to approximately 3.14159265.
  8443.    Similarly, the number of radians in one complete angle of revolution (or
  8444.    360) equals 2 * π, or a little more than 6.28. If you are more used to
  8445.    thinking of angles in terms of degrees, here are some common equivalences:
  8446.  
  8447.    Angle in Degrees         Angle in Radians
  8448.    ──────────────────────────────────────────────────────────────────────────
  8449.    360                      2π    (approximately 6.283)
  8450.  
  8451.    180                      π    (approximately 3.142)
  8452.  
  8453.    90                       π/2  (approximately 1.571)
  8454.  
  8455.    60                       π/3  (approximately 1.047)
  8456.    ──────────────────────────────────────────────────────────────────────────
  8457.  
  8458.    If you picture a clock face on the screen, CIRCLE measures angles by
  8459.    starting at the "3:00" position and rotating counterclockwise, as shown in
  8460.    Figure 5.2:
  8461.  
  8462.  
  8463.    ┌────────────────────────────────────┐
  8464.    │                                    │
  8465.    │   Figure 5.2 can be found on       │
  8466.    │   page 161 of the printed manual.  │
  8467.    │                                    │
  8468.    └────────────────────────────────────┘
  8469.  
  8470.    Figure 5.2  How Angles Are Measured for CIRCLE
  8471.  
  8472.    The general formula for converting from degrees to radians is to multiply
  8473.    degrees by π/180.
  8474.  
  8475.    To draw an arc, give angle arguments defining the arc's limits:
  8476.  
  8477.    CIRCLE[[STEP]] (x, y), radius,[[color]], start, end [[, aspect]]
  8478.  
  8479.    Example
  8480.  
  8481.    The CIRCLE statements in the next example draw seven arcs, with the
  8482.    innermost arc starting at the "3:00" position (0 radians) and the
  8483.    outermost arc starting at the "6:00" position (3π/2 radians), as you can
  8484.    see from the output:
  8485.  
  8486.    SCREEN 2
  8487.    CLS
  8488.  
  8489.    CONST PI = 3.141592653589#      ' Double-precision constant
  8490.  
  8491.    StartAngle = 0
  8492.    FOR Radius% = 100 TO 220 STEP 20
  8493.       EndAngle = StartAngle + (PI / 2.01)
  8494.       CIRCLE (320, 100), Radius%, , StartAngle, EndAngle
  8495.       StartAngle = StartAngle + (PI / 4)
  8496.    NEXT Radius%
  8497.  
  8498.    Output
  8499.  
  8500.    ┌────────────────────────────────────┐
  8501.    │                                    │
  8502.    │     The output for this example    │
  8503.    │     can be found on page 162 of    │
  8504.    │     the printed manual.            │
  8505.    │                                    │
  8506.    └────────────────────────────────────┘
  8507.  
  8508.  5.4.4  Drawing Pie Shapes
  8509.  
  8510.    By making either of CIRCLE's start or end arguments negative, you can
  8511.    connect the arc at its beginning or ending point with the center of the
  8512.    circle. By making both arguments negative, you can draw shapes ranging
  8513.    from a wedge that resembles a slice of pie to the pie itself with the
  8514.    piece missing.
  8515.  
  8516.    Example
  8517.  
  8518.    This example draws a pie shape with a piece missing:
  8519.  
  8520.    SCREEN 2
  8521.  
  8522.    CONST RADIUS = 150, PI = 3.141592653589#
  8523.  
  8524.    StartAngle = 2.5
  8525.    EndAngle = PI
  8526.  
  8527.    ' Draw the wedge:
  8528.    CIRCLE (320, 100), RADIUS, , -StartAngle, -EndAngle
  8529.  
  8530.    ' Swap the values for the start and end angles:
  8531.    SWAP StartAngle, EndAngle
  8532.  
  8533.    ' Move the center 10 pixels down and 70 pixels to the
  8534.    ' right, then draw the "pie" with the wedge missing:
  8535.    CIRCLE STEP(70, 10), RADIUS, , -StartAngle, -EndAngle
  8536.  
  8537.    Output
  8538.  
  8539.    ┌────────────────────────────────────┐
  8540.    │                                    │
  8541.    │     The output for this example    │
  8542.    │     can be found on page 163 of    │
  8543.    │     the printed manual.            │
  8544.    │                                    │
  8545.    └────────────────────────────────────┘
  8546.  
  8547.  5.4.5  Drawing Shapes to Proportion with the Aspect Ratio
  8548.  
  8549.    As discussed in Section 5.4.2, "Drawing Ellipses," BASIC's CIRCLE
  8550.    statement automatically corrects the aspect ratio, which determines how
  8551.    figures are scaled on the screen. However, with other graphics statements
  8552.    you need to scale horizontal and vertical dimensions yourself to make
  8553.    shapes appear with correct proportions. For example, although the
  8554.    following statement draws a rectangle that measures 100 pixels on all
  8555.    sides, it does not look like a square:
  8556.  
  8557.    SCREEN 1
  8558.    LINE (0, 0)-(100, 100), , B
  8559.  
  8560.    In fact, this is not an optical illusion; the rectangle really is taller
  8561.    than it is wide. This is because in screen mode 1 there is more space
  8562.    between pixels vertically than horizontally. To draw a perfect square, you
  8563.    have to change the aspect ratio.
  8564.  
  8565.    The aspect ratio is defined as follows: in a given screen mode consider
  8566.    two lines, one vertical and one horizontal, that appear to have the same
  8567.    length. The aspect ratio is the number of pixels in the vertical line
  8568.    divided by the number of pixels in the horizontal line. This ratio depends
  8569.    on two factors:
  8570.  
  8571.    1. Because of the way pixels are spaced on most screens, a horizontal row
  8572.       has more pixels than a vertical column of the exact same physical
  8573.       length in all screen modes except modes 11 and 12.
  8574.  
  8575.    2. The standard personal computer's video-display screen is wider than it
  8576.       is high. Typically, the ratio of screen width to screen height is 4:3.
  8577.  
  8578.    To see how these two factors interact to produce the aspect ratio,
  8579.    consider a screen after a SCREEN 1 statement, which gives a resolution of
  8580.    320 x 200 pixels. If you draw a rectangle from the top of the screen to
  8581.    the bottom, and from the left side of the screen three-fourths of the way
  8582.    across, you have a square, as shown in Figure 5.3.
  8583.  
  8584.  
  8585.    ┌────────────────────────────────────────────────────────────────┐
  8586.    │ ┌──────────────────────────────────────────────────────┐       │
  8587.    │ │ ┌───────────────────────────────────┬─ - - - - - -   │       │
  8588.    │ │ │                                   │               │       │
  8589.    │ │ │                                   │      │         │       │
  8590.    │ │ │                                   │      │         │       │
  8591.    │ │ │                                   │      │         │       │
  8592.    │ │ │ ────────── 240 pixels───────────│   200 pixels   │       │
  8593.    │ │ │                                   │      │         │       │
  8594.    │ │ │                                   │      │         │       │
  8595.    │ │ │                                   │      │         │       │
  8596.    │ │ │                                   │      │         │       │
  8597.    │ │ │                                   │      │         │       │
  8598.    │ │ │                                   │               │       │
  8599.    │ │ └───────────────────────────────────┴─ - - - - - - - │       │
  8600.    │ │ ──────────────────320 pixels───────────────────────│       │
  8601.    │ └──────────────────────────────────────────────────────┘       │
  8602.    │                                                                │
  8603.    └────────────────────────────────────────────────────────────────┘
  8604.    Figure 5.3  The Aspect Ratio In Screen Mode 1
  8605.  
  8606.    As you can see from the diagram, this square has a height of 200 pixels
  8607.    and a width of 240 pixels. The ratio of the square's height to its width
  8608.    (200 / 240, or when simplified, 5 / 6) is the aspect ratio for this screen
  8609.    resolution. In other words, to draw a square in 320 x 200 resolution, make
  8610.    its height in pixels equal to 5 / 6 times its width in pixels, as shown in
  8611.    the next example:
  8612.  
  8613.    SCREEN 1        ' 320 x 200 pixel resolution
  8614.  
  8615.    ' The height of this box is 100 pixels, and the width is
  8616.    ' 120 pixels, which makes the ratio of the height to the
  8617.    ' width equal to 100/120, or 5/6. The result is a square:
  8618.    LINE (50, 50) -STEP(120, 100), , B
  8619.  
  8620.    The formula for calculating the aspect ratio for a given screen mode is
  8621.  
  8622.    (4 / 3) * (ypixels / xpixels)
  8623.  
  8624.    where xpixelsby ypixels is the current screen resolution. In screen mode
  8625.    1, this formula shows the aspect ratio to be (4 / 3) * (200 / 320), or 5 /
  8626.    6; in screen mode 2, the aspect ratio is (4 / 3) * (200 / 640), or 5 / 12.
  8627.  
  8628.    If you have a video display with a ratio of width to height that is not
  8629.    equal to 4:3, use the more general form of the formula for computing the
  8630.    aspect ratio:
  8631.  
  8632.    (screenwidth / screenheight) * (ypixels / xpixels)
  8633.  
  8634.    The CIRCLE statement can be made to draw an ellipse by varying the value
  8635.    of the aspect argument, as shown above in Section 5.4.2.
  8636.  
  8637.  
  8638.  5.5  Defining a Graphics Viewport
  8639.  
  8640.    The graphics examples presented so far have all used the entire
  8641.    video-display screen as their drawing board, with absolute coordinate
  8642.    distances measured from the extreme upper-left corner of the screen.
  8643.  
  8644.    However, using the VIEW statement you can also define a kind of miniature
  8645.    screen (known as a "graphics viewport") inside the boundaries of the
  8646.    physical screen. Once it is defined, all graphics operations take place
  8647.    within this viewport. Any graphics output outside the viewport boundaries
  8648.    is "clipped"; that is, any attempt to plot a point outside the viewport is
  8649.    ignored. There are two main advantages to using a viewport:
  8650.  
  8651.    1. A viewport makes it easy to change the size and position of the screen
  8652.       area where graphics appear.
  8653.  
  8654.    2. Using CLS 1, you can clear the screen inside a viewport without
  8655.       disturbing the screen outside the viewport.
  8656.  
  8657.    ──────────────────────────────────────────────────────────────────────────
  8658.    NOTE
  8659.      Refer to Section 3.1.6 to learn how to create a "text viewport" for
  8660.      output printed on the screen.
  8661.    ──────────────────────────────────────────────────────────────────────────
  8662.  
  8663.    The general syntax for VIEW (note that the STEP option is not allowed with
  8664.    VIEW) is
  8665.  
  8666.    VIEW[[[[SCREEN]] (x1, y1) - (x2, y2)[[,[[color]], [[border]]]]]]
  8667.  
  8668.    where (x1, y1) and (x2, y2) define the corners of the viewport, using the
  8669.    standard BASIC syntax for rectangles (see Section 5.3.2.2, "Drawing
  8670.    Boxes"). The optional color and border arguments allow you to choose a
  8671.    color for the interior and edges, respectively, of the viewport rectangle.
  8672.    See Section 5.7 below for more information on setting and changing
  8673.    colors.
  8674.  
  8675.    The VIEW statement without arguments makes the entire screen the viewport.
  8676.    Without the SCREEN option, the VIEW statement makes all pixel coordinates
  8677.    relative to the viewport, rather than the full screen. In other words,
  8678.    after the statement
  8679.  
  8680.    VIEW (50, 60)-(150, 175)
  8681.  
  8682.    the pixel plotted with
  8683.  
  8684.    PSET (10, 10)
  8685.  
  8686.    is visible, since it is 10 pixels below and 10 pixels to the right of the
  8687.    upper-left corner of the viewport. Note that this makes the pixel's
  8688.    absolute screen coordinates (50 + 10, 60 + 10) or (60, 70).
  8689.  
  8690.    In contrast, the VIEW statement with the SCREEN option keeps all
  8691.    coordinates absolute; that is, coordinates measure distances from the side
  8692.    of the screen, not from the sides of the viewport. Therefore, after the
  8693.    statement
  8694.  
  8695.    VIEW SCREEN (50, 60)-(150, 175)
  8696.  
  8697.    the pixel plotted with
  8698.  
  8699.    PSET (10, 10)
  8700.  
  8701.    is not visible, since it is 10 pixels below and 10 pixels to the right of
  8702.    the upper-left corner of the screen──outside the viewport.
  8703.  
  8704.    Examples
  8705.  
  8706.    The output from the next two examples should further clarify the
  8707.    distinction between VIEW and VIEW SCREEN:
  8708.  
  8709.    SCREEN 2
  8710.  
  8711.    VIEW (100, 50)-(450, 150), , 1
  8712.  
  8713.    ' This circle's center point has absolute coordinates
  8714.    ' (100 + 100, 50 + 50), or (200, 100):
  8715.    CIRCLE (100, 50), 50
  8716.  
  8717.    Output using VIEW
  8718.  
  8719.    ┌────────────────────────────────────┐
  8720.    │                                    │
  8721.    │     The output for this example    │
  8722.    │     can be found on page 167 of    │
  8723.    │     the printed manual.            │
  8724.    │                                    │
  8725.    └────────────────────────────────────┘
  8726.  
  8727.    SCREEN 2
  8728.  
  8729.    ' This circle's center point has absolute coordinates
  8730.    ' (100, 50), so only part of the circle appears
  8731.    '  within the view port:
  8732.    VIEW SCREEN (100, 50)-(450, 150), , 1
  8733.    CIRCLE (100, 50), 50
  8734.  
  8735.    Output using VIEW SCREEN
  8736.  
  8737.    ┌────────────────────────────────────┐
  8738.    │                                    │
  8739.    │     The output for this example    │
  8740.    │     can be found on page 167 of    │
  8741.    │     the printed manual.            │
  8742.    │                                    │
  8743.    └────────────────────────────────────┘
  8744.  
  8745.    Note that graphics output located outside the current viewport is clipped
  8746.    by the viewport's edges and does not appear on the screen.
  8747.  
  8748.  
  8749.  5.6  Redefining Viewport Coordinates with WINDOW
  8750.  
  8751.    This section shows you how to use the WINDOW statement and your own
  8752.    coordinate system to redefine pixel coordinates.
  8753.  
  8754.    In Sections 5.2-5.5, the coordinates used to locate pixels on the screen
  8755.    represent actual physical distances from the upper-left corner of the
  8756.    screen (or the upper-left corner of the current viewport, if it has been
  8757.    defined with a VIEW statement). These are known as "physical coordinates."
  8758.    The "origin," or reference point, for physical coordinates is always the
  8759.    upper-left corner of the screen or viewport, which has coordinates (0, 0).
  8760.  
  8761.    As you move down the screen and to the right, x values (horizontal
  8762.    coordinates) and y values (vertical coordinates) get bigger, as shown in
  8763.    the upper diagram of Figure 5.4. While this scheme is standard for video
  8764.    displays, it may seem counterintuitive if you have used other coordinate
  8765.    systems to draw graphs. For example, on the Cartesian grid used in
  8766.    mathematics, y values get bigger toward the top of a graph and smaller
  8767.    toward the bottom.
  8768.  
  8769.    With BASIC's WINDOW statement, you can change the way pixels are addressed
  8770.    to use any coordinate system you choose, thus freeing you from the
  8771.    limitations of using physical coordinates.
  8772.  
  8773.    The general syntax for WINDOW is
  8774.  
  8775.    WINDOW [[[[SCREEN]] (x1, y1) - (x2, y2)]]
  8776.  
  8777.    where y1, y2, x1, and x2 are real numbers specifying the top, bottom,
  8778.    left, and right sides of the window, respectively. These numbers are known
  8779.    as "view coordinates." For example, the following statement remaps your
  8780.    screen so that it is bounded on the top and bottom by the lines y = 10 and
  8781.    y = -15 and on the left and right by the lines x = -25 and x = 5 :
  8782.  
  8783.    WINDOW (-25, -15)-(5, 10)
  8784.  
  8785.    After a WINDOW statement, y values get bigger toward the top of the
  8786.    screen. In contrast, after a WINDOW SCREEN statement, y values get bigger
  8787.    toward the bottom of the screen. The bottom half of Figure 5.4 shows the
  8788.    effects of both a WINDOW statement and a WINDOW SCREEN statement on a line
  8789.    drawn in screen mode 2. Note also how both of these statements change the
  8790.    coordinates of the screen corners. A WINDOW statement with no arguments
  8791.    restores the regular physical-coordinate system.
  8792.  
  8793.    Example
  8794.  
  8795.  
  8796.    ┌──────────────────────────────────────────────────────────────────────────
  8797.    │                               Increasing X
  8798.    │                     ─────────────────────────────
  8799.    │                     ┌────────────────────────────┐
  8800.    │                   │ │°(0,0)              (639,0)°│
  8801.    │                   │ │                            │
  8802.    │        Increasing │ │                            │
  8803.    │             Y     │ │                            │
  8804.    │                   │ │                            │
  8805.    │                   │ │                            │
  8806.    │                   │ │°(0,199)          (639,199)°│
  8807.    │                    └────────────────────────────┘
  8808.    │                                   ^
  8809.    │                                 /   \
  8810.    │                                /      \
  8811.    │       WINDOW (-25, -15) - (5, 10)   WINDOW SCREEN (-25, -15) - (5, 10)
  8812.    │       LINE (-15, -10  - (-5, -5)    LINE (-15, -10) - (-5, -5)
  8813.    │                            /              \
  8814.    │                          /                  \
  8815.    │                        /                      \
  8816.    │                                                       Increasing X
  8817.    │                                                ─────────────────────────
  8818.    │            ┌─────────────────────┐             ┌────────────────────────┐
  8819.    │           │°(-25,10)     (5,10)°│            ││°(-25,-15)    (5,-15)°  │
  8820.    │           ││                     │            ││        °(-15,-10)      │
  8821.    │           ││           (0,0)°    │            ││             \          │
  8822.    │ Increasing││                     │  Increasing││              °(-5,-5)  │
  8823.    │      Y    ││       (-5,-5)°      │       Y    ││                        │
  8824.    │           ││(-15,-10)  /         │            ││                   °    │
  8825.    │           ││         °           │            ││               (0,0)    │
  8826.    │           ││°(-25,-15)   (5,-15)°│            ││°(-25,10)        (5,10)°│
  8827.    │            └─────────────────────┘            └────────────────────────┘
  8828.    │            ──────────────────────
  8829.    │                 Increasing X
  8830.    └──────────────────────────────────────────────────────────────────────────
  8831.  
  8832.    Figure 5.4  WINDOW Contrasted with WINDOW SCREEN
  8833.  
  8834.    The following example uses both VIEW and WINDOW to simplify writing a
  8835.    program to graph the sine-wave function for angle values from 0 radians to
  8836.    p radians (or 0° to 180°). This program is in the file named SINEWAVE.BAS
  8837.    on the QuickBASIC distribution disks.
  8838.  
  8839.    SCREEN 2
  8840.  
  8841.    ' Viewport sized to proper scale for graph:
  8842.    VIEW (20, 2)-(620, 172), , 1
  8843.    CONST PI = 3.141592653589#
  8844.  
  8845.    ' Make window large enough to graph sine wave from
  8846.    ' 0 radians to pi radians:
  8847.    WINDOW (0, -1.1)-(PI, 1.1)
  8848.    Style% = &HFF00                 ' Use to make dashed line.
  8849.    VIEW PRINT 23 TO 24  ' Scroll printed output in rows 23, 24.
  8850.    DO
  8851.       PRINT TAB(20);
  8852.       INPUT "Number of cycles (0 to end): ", Cycles
  8853.       CLS
  8854.       LINE (PI, 0)-(0, 0), , , Style%  ' Draw the x axis.
  8855.       IF Cycles > 0 THEN
  8856.  
  8857.          ' Start at (0,0) and plot the graph:
  8858.          FOR X = 0 TO PI STEP .01
  8859.             Y = SIN(Cycles * X)    ' Calculate the y coordinate.
  8860.             LINE -(X, Y)           ' Draw a line to new point.
  8861.          NEXT X
  8862.       END IF
  8863.    LOOP WHILE Cycles > 0
  8864.  
  8865.    Output
  8866.  
  8867.    ┌────────────────────────────────────┐
  8868.    │                                    │
  8869.    │     The output for this example    │
  8870.    │     can be found on page 170 of    │
  8871.    │     the printed manual.            │
  8872.    │                                    │
  8873.    └────────────────────────────────────┘
  8874.  
  8875.  5.6.1  The Order of Coordinate Pairs
  8876.  
  8877.    As with the other BASIC graphics statements that define rectangular areas
  8878.    (GET, LINE, and VIEW), the order of coordinate pairs in a WINDOW statement
  8879.    is unimportant. The first pair of statements below has the same effect as
  8880.    the second pair of statements:
  8881.  
  8882.    VIEW (100, 20)-(300, 120)
  8883.    WINDOW (-4, -3)-(0, 0)
  8884.  
  8885.    VIEW (300, 120)-(100, 20)
  8886.    WINDOW (0, 0)-(-4, -3)
  8887.  
  8888.  5.6.2  Keeping Track of View and Physical Coordinates
  8889.  
  8890.    The PMAP and POINT functions are useful for keeping track of physical and
  8891.    view coordinates. POINT(number) tells you the current location of the
  8892.    graphics cursor by returning either the physical or view coordinates
  8893.    (depending on the value for number) of the last point referenced in a
  8894.    graphics statement. PMAP allows you to translate physical coordinates to
  8895.    view coordinates and vice versa. The physical-coordinate values returned
  8896.    by PMAP are always relative to the current viewport.
  8897.  
  8898.    Examples
  8899.  
  8900.    The following example shows the different values that are returned by
  8901.    POINT (number) for number values of 0, 1, 2, or 3:
  8902.  
  8903.    SCREEN 2
  8904.    ' Define the view-coordinate window:
  8905.    WINDOW (-10, -30)-(-5, -10)
  8906.    ' Draw a line from the point with view coordinates (-9,-28)
  8907.    ' to the point with view coordinates (-6,-24):
  8908.    LINE (-9, -28)-(-6, -24)
  8909.  
  8910.    PRINT "Physical x-coordinate of the last point = " POINT(0)
  8911.    PRINT "Physical y-coordinate of the last point = " POINT(1)
  8912.    PRINT
  8913.    PRINT "View x-coordinate of the last point  = " POINT(2)
  8914.    PRINT "View y-coordinate of the last point  = " POINT(3)
  8915.  
  8916.    END
  8917.  
  8918.    Output
  8919.  
  8920.    Physical x-coordinate of the last point = 511
  8921.    Physical y-coordinate of the last point = 139
  8922.  
  8923.    View x-coordinate of the last point  = -6
  8924.    View y-coordinate of the last point  = -24
  8925.  
  8926.    Given the WINDOW statement in the preceding example, the next four PMAP
  8927.    statements would print the output that follows:
  8928.  
  8929.    ' Map the view x-coordinate -6 to physical x and print:
  8930.    PhysX% = PMAP(-6, 0)
  8931.    PRINT PhysX%
  8932.  
  8933.    ' Map the view y-coordinate -24 to physical y and print:
  8934.    PhysY% = PMAP(-24, 1)
  8935.    PRINT PhysY%
  8936.  
  8937.    ' Map physical x back to view x and print:
  8938.    ViewX% = PMAP(PhysX%, 2)
  8939.    PRINT ViewX%
  8940.  
  8941.    ' Map physical y back to view y and print:
  8942.    ViewY% = PMAP(PhysY%, 3)
  8943.    PRINT ViewY%
  8944.  
  8945.    Output
  8946.  
  8947.     511
  8948.     139
  8949.    -6
  8950.    -24
  8951.  
  8952.  
  8953.  5.7  Using Colors
  8954.  
  8955.    If you have a Color Graphics Adapter (CGA), you can choose between the
  8956.    following two graphics modes only:
  8957.  
  8958.    1. Screen mode 2 has 640 x 200 high resolution, with only one foreground
  8959.       and one background color. This is known as "monochrome," since all
  8960.       graphics output has the same color.
  8961.  
  8962.    2. Screen mode 1 has 320 x 200 medium resolution with 4 foreground colors
  8963.       and 16 background colors.
  8964.  
  8965.    There is thus a tradeoff between color and clarity in the two screen modes
  8966.    supported by most color-graphics display adapter hardware. Depending on
  8967.    the graphics capability of your system, you may not have to sacrifice
  8968.    clarity to get a full range of color. However, this section focuses on
  8969.    screen modes 1 and 2.
  8970.  
  8971.  5.7.1  Selecting a Color for Graphics Output
  8972.  
  8973.    The following list shows where to put the color argument in the graphics
  8974.    statements discussed in previous sections of this chapter. This list also
  8975.    shows other options (such as BF with the LINE statement or border with the
  8976.    VIEW statement) that can have a different colors. (Please note that these
  8977.    do not give the complete syntax for some of these statements. This summary
  8978.    is intended to show how to use the color option in those statements that
  8979.    accept it.)
  8980.  
  8981.    PSET (x, y), color
  8982.    PRESET (x, y), color
  8983.    LINE (x1, y1) - (x2, y2), color [[, B[[F]]]]
  8984.    CIRCLE (x, y), radius, color
  8985.    VIEW (x1, y1) - (x2, y2), color, border
  8986.  
  8987.    In screen mode 1, the color argument is a numeric expression with the
  8988.    value 0, 1, 2, or 3. Each of these values, known as an "attribute,"
  8989.    represents a different color, as demonstrated by the following program:
  8990.  
  8991.    ' Draw an "invisible" line (same color as background):
  8992.    LINE (10, 10)-(310, 10), 0
  8993.  
  8994.    ' Draw a light blue (cyan) line:
  8995.    LINE (10, 30)-(310, 30), 1
  8996.  
  8997.    ' Draw a purple (magenta) line:
  8998.    LINE (10, 50)-(310, 50), 2
  8999.  
  9000.    ' Draw a white line:
  9001.    LINE (10, 70)-(310, 70), 3
  9002.    END
  9003.  
  9004.    As noted in the comments for the preceding example, a color value of 0
  9005.    produces no visible output, since it is always equal to the current
  9006.    background color. At first glance, this may not seem like such a useful
  9007.    color value, but in fact it is useful for erasing a figure without having
  9008.    to clear the entire screen or viewport, as shown in the next example:
  9009.  
  9010.    SCREEN 1
  9011.  
  9012.    CIRCLE (100, 100), 80, 2, , , 3   ' Draw an ellipse.
  9013.    Pause$ = INPUT$(1)                ' Wait for a key press.
  9014.    CIRCLE (100, 100), 80, 0, , , 3   ' Erase the ellipse.
  9015.  
  9016.  5.7.2  Changing the Foreground or Background Color
  9017.  
  9018.    Section 5.7.1 above describes how to use 4 different foreground colors
  9019.    for graphics output. You have a wider variety of colors in screen mode 1
  9020.    for the screen's background: 16 in all.
  9021.  
  9022.    In addition, you can change the foreground color by using a different
  9023.    "palette." In screen mode 1, there are two palettes, or groups of four
  9024.    colors. Each palette assigns a different color to the same attribute; so,
  9025.    for instance, in palette 1 (the default) the color associated with
  9026.    attribute 2 is magenta, while in palette 0 the color associated with
  9027.    attribute 2 is red. If you have a CGA, these colors are predetermined for
  9028.    each palette; that is, the color assigned to number 2 in palette 1 is
  9029.    always magenta, while the color assigned to number 2 in palette 0 is
  9030.    always red.
  9031.  
  9032.    If you have an Enhanced Graphics Adapter (EGA) or Video Graphics Adapter
  9033.    (VGA), you can use the PALETTE statement to choose the color displayed by
  9034.    any attribute. For example, by changing arguments in a PALETTE statement,
  9035.    you could make the color displayed by attribute 1 green one time and brown
  9036.    the next. (See Section 5.7.3, "Changing Colors with PALETTE and PALETTE
  9037.    USING," in this manual for more information on reassigning colors.)
  9038.  
  9039.    In screen mode 1, the COLOR statement allows you to control both the
  9040.    background color and the palette for the foreground colors. Here is the
  9041.    syntax for COLOR in screen mode 1:
  9042.  
  9043.    COLOR[[background]] [[, palette]]
  9044.  
  9045.    The background argument is a numeric expression from 0 to 15, and palette
  9046.    is a numeric expression equal to either 0 or 1.
  9047.  
  9048.    Table 5.1 shows the colors produced with the 4 different foreground
  9049.    numbers in each of the two palettes, while Table 5.2 shows the colors
  9050.    produced with the 16 different background numbers.
  9051.  
  9052.    Table 5.1  Color Palettes in Screen Mode 1
  9053.    Foreground Color Number  Color in Palette 0      Color in Palette 1
  9054.    ──────────────────────────────────────────────────────────────────────────
  9055.    0                        Current background      Current background color
  9056.                             color
  9057.  
  9058.    1                        Green                   Cyan (bluish green)
  9059.  
  9060.    2                        Red                     Magenta (light purple)
  9061.  
  9062.    3                        Brown                   White (light grey on some
  9063.                                                     monitors)
  9064.    ──────────────────────────────────────────────────────────────────────────
  9065.  
  9066.    Table 5.2  Background Colors in Screen Mode 1
  9067. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  9068.    Background Color Number  Color
  9069.    ──────────────────────────────────────────────────────────────────────────
  9070.    0                        Black
  9071.  
  9072.    1                        Blue
  9073.  
  9074.    Background Color Number  Color
  9075.    ──────────────────────────────────────────────────────────────────────────
  9076. 
  9077.    2                        Green
  9078.  
  9079.    3                        Cyan
  9080.  
  9081.    4                        Red
  9082.  
  9083.    5                        Magenta
  9084.  
  9085.    6                        Brown (dark yellow on some monitors)
  9086.  
  9087.    7                        White (light grey on some monitors)
  9088.  
  9089.    8                        Dark grey (black on some monitors)
  9090.  
  9091.    9                        Light blue
  9092.  
  9093.    10                       Light green
  9094.  
  9095.    Background Color Number  Color
  9096.    ──────────────────────────────────────────────────────────────────────────
  9097. 
  9098.    11                       Light cyan
  9099.  
  9100.    12                       Light red
  9101.  
  9102.    13                       Light magenta
  9103.  
  9104.    14                       Light yellow (may have greenish tinge on some
  9105.                             monitors)
  9106.  
  9107.    15                       Bright white or very light grey
  9108.    ──────────────────────────────────────────────────────────────────────────
  9109.  
  9110.  
  9111.    Example
  9112.  
  9113.    The following program shows all combinations of the two color palettes
  9114.    with the 16 different background screen colors. This program is in the
  9115.    file named COLORS.BAS on the QuickBASIC distribution disks.
  9116.  
  9117.    SCREEN 1
  9118.  
  9119.    Esc$ = CHR$(27)
  9120.    ' Draw three boxes and paint the interior
  9121.    ' of each box with a different color:
  9122.    FOR ColorVal = 1 TO 3
  9123.       LINE (X, Y) -STEP(60, 50), ColorVal, BF
  9124.       X = X + 61
  9125.       Y = Y + 51
  9126.    NEXT ColorVal
  9127.  
  9128.    LOCATE 21, 1
  9129.    PRINT "Press ESC to end."
  9130.    PRINT "Press any other key to continue."
  9131.  
  9132.    ' Restrict additional printed output to the 23rd line:
  9133.    VIEW PRINT 23 TO 23
  9134.    DO
  9135.       PaletteVal = 1
  9136.       DO
  9137.  
  9138.          ' PaletteVal is either 1 or 0:
  9139.          PaletteVal = 1 - PaletteVal
  9140.  
  9141.          ' Set the background color and choose the palette:
  9142.          COLOR BackGroundVal, PaletteVal
  9143.          PRINT "Background ="; BackGroundVal;
  9144.          PRINT "Palette ="; PaletteVal;
  9145.  
  9146.          Pause$ = INPUT$(1)        ' Wait for a keystroke.
  9147.          PRINT
  9148.  
  9149.       ' Exit the loop if both palettes have been shown,
  9150.       ' or if the user pressed the ESC key:
  9151.       LOOP UNTIL PaletteVal = 1 OR Pause$ = Esc$
  9152.  
  9153.       BackGroundVal = BackGroundVal + 1
  9154.  
  9155.    ' Exit this loop if all 16 background colors have
  9156.    ' been shown, or if the user pressed the ESC key:
  9157.    LOOP UNTIL BackGroundVal > 15 OR Pause$ = Esc$
  9158.  
  9159.    SCREEN 0                     ' Restore text mode and
  9160.    WIDTH 80                     ' 80-column screen width.
  9161.  
  9162.  5.7.3  Changing Colors with PALETTE and PALETTE USING
  9163.  
  9164.    The preceding section showed how you can change the color displayed by an
  9165.    attribute simply by specifying a different palette in the COLOR statement.
  9166.    However, this restricts you to two fixed color palettes, with just 4
  9167.    colors in each. Furthermore, each attribute can stand for only one of two
  9168.    possible colors; for example, attribute 1 can signify only green or cyan.
  9169.  
  9170.    With an EGA or VGA, your choices are potentially much broader. (If you
  9171.    don't have an EGA or VGA, you may want to skip this section.) For
  9172.    instance, depending on the amount of video memory available to your
  9173.    computer, with a VGA you can choose from a palette with as many as 256K
  9174.    (that's right, over 256,000) colors and assign those colors to 256
  9175.    different attributes. Even an EGA allows you to display up to 16 different
  9176.    colors from a palette of 64 colors.
  9177.  
  9178.    In contrast to the COLOR statement, the PALETTE and PALETTE USING
  9179.    statements give you a lot more flexibility in manipulating the available
  9180.    color palette. Using these statements, you can assign any color from the
  9181.    palette to any attribute. For example, after the following statement, the
  9182.    output of all graphics statements using attribute 4 appears in light
  9183.    magenta (color 13):
  9184.  
  9185.    PALETTE 4, 13
  9186.  
  9187.    This color change is instantaneous and affects not only subsequent
  9188.    graphics statements but any output already on the screen. In other words,
  9189.    you can draw and paint your screen, then switch the palette to achieve an
  9190.    immediate change of color, as shown by the following example:
  9191.  
  9192.    SCREEN 8
  9193.    LINE (50, 50)-(150, 150), 4  ' Draws a line in red.
  9194.    SLEEP 1                      ' Pauses program.
  9195.    PALETTE 4, 13                ' Attribute 4 now means color
  9196.                                 ' 13, so the line drawn in the
  9197.                                 ' last statement is now light
  9198.                                 ' magenta.
  9199.  
  9200.    With the PALETTE statement's USING option, you can change the colors
  9201.    assigned to every attribute all at once.
  9202.  
  9203.    Example
  9204.  
  9205.    The following example uses the PALETTE USING statement to give the
  9206.    illusion of movement on the screen by constantly rotating the colors
  9207.    displayed by attributes 1 through 15. This program is in the file named
  9208.    PALETTE.BAS on the QuickBASIC distribution disks.
  9209.  
  9210.    DECLARE SUB InitPalette ()
  9211.    DECLARE SUB ChangePalette ()
  9212.    DECLARE SUB DrawEllipses ()
  9213.  
  9214.    DEFINT A-Z
  9215.    DIM SHARED PaletteArray(15)
  9216.  
  9217.    SCREEN 8                 ' 640 x 200 resolution; 16 colors
  9218.  
  9219.    InitPalette              ' Initialize PaletteArray.
  9220.    DrawEllipses             ' Draw and paint concentric ellipses.
  9221.  
  9222.    DO                       ' Shift the palette until a key
  9223.       ChangePalette         ' is pressed.
  9224.    LOOP WHILE INKEY$ = ""
  9225.  
  9226.    END
  9227.  
  9228.  
  9229.    ' ====================== InitPalette ======================
  9230.    '    This procedure initializes the integer array used to
  9231.    '    change the palette.
  9232.    ' =========================================================
  9233.  
  9234.    SUB InitPalette STATIC
  9235.       FOR I = 0 TO 15
  9236.          PaletteArray(I) = I
  9237.       NEXT I
  9238.    END SUB
  9239.    ' ===================== DrawEllipses ======================
  9240.    '    This procedure draws 15 concentric ellipses and
  9241.    '    paints the interior of each with a different color.
  9242.    ' =========================================================
  9243.  
  9244.    SUB DrawEllipses STATIC
  9245.       CONST ASPECT = 1 / 3
  9246.       FOR ColorVal = 15 TO 1 STEP -1
  9247.          Radius = 20 * ColorVal
  9248.          CIRCLE (320, 100), Radius, ColorVal, , , ASPECT
  9249.          PAINT (320, 100), ColorVal
  9250.       NEXT
  9251.    END SUB
  9252.  
  9253.  
  9254.    ' ===================== ChangePalette =====================
  9255.    '  This procedure rotates the palette by one each time it
  9256.    '  is called. For example, after the first call to
  9257.    '  ChangePalette, PaletteArray(1) = 2, PaletteArray(2) = 3,
  9258.    '  . . . , PaletteArray(14) = 15, and PaletteArray(15) = 1
  9259.    ' =========================================================
  9260.  
  9261.    SUB ChangePalette STATIC
  9262.       FOR I = 1 TO 15
  9263.          PaletteArray(I) = (PaletteArray(I) MOD 15) + 1
  9264.       NEXT I
  9265.       PALETTE USING PaletteArray(0) ' Shift the color displayed
  9266.                                     ' by each of the attributes.
  9267.    END SUB
  9268.  
  9269.  
  9270.  5.8  Painting Shapes
  9271.  
  9272.    Section 5.3.2.2 above shows how to draw a box with the LINE statement's B
  9273.    option, then paint the box by appending the F (for fill) option:
  9274.  
  9275.    SCREEN 1
  9276.  
  9277.    ' Draw a square, then paint the interior with color 1
  9278.    ' (cyan in the default palette):
  9279.    LINE (50, 50)-(110, 100), 1, BF
  9280.  
  9281.    With BASIC's PAINT statement, you can fill any enclosed figure with any
  9282.    color you choose. PAINT also allows you to fill enclosed figures with your
  9283.    own custom patterns, such as stripes or checks, as shown in Section
  9284.    5.8.2, "Painting with Patterns."
  9285.  
  9286.  5.8.1  Painting with Colors
  9287.  
  9288.    To paint an enclosed shape with a solid color, use this form of the PAINT
  9289.    statement:
  9290.  
  9291.    PAINT[[STEP]](x, y) [[,[[interior]],[[border]]]]
  9292.  
  9293.    Here, x, y are the coordinates of a point in the interior of the figure
  9294.    you want to paint, interior is the number for the color you want to paint
  9295.    with, and border is the color number for the outline of the figure.
  9296.  
  9297.    For example, the following program lines draw a circle in cyan, then paint
  9298.    the inside of the circle magenta:
  9299.  
  9300.    SCREEN 1
  9301.    CIRCLE (160, 100), 50, 1
  9302.    PAINT (160, 100), 2, 1
  9303.  
  9304.    The following three rules apply when painting figures:
  9305.  
  9306.    1. The coordinates given in the PAINT statement must refer to a point
  9307.       inside the figure.
  9308.  
  9309.       For example, any one of the following statements would have the same
  9310.       effect as the PAINT statements shown in the two preceding examples,
  9311.       since all of the coordinates identify points in the interior of the
  9312.       circle:
  9313.  
  9314.       PAINT (150, 90), 2, 1
  9315.       PAINT (170, 110), 2, 1
  9316.       PAINT (180, 80), 2, 1
  9317.  
  9318.       In contrast, since (5, 5) identifies a point outside the circle, the
  9319.       next statement would paint all of the screen except the inside of the
  9320.       circle, leaving it colored with the current background color:
  9321.  
  9322.       PAINT (5, 5), 2, 1
  9323.  
  9324.       If the coordinates in a PAINT statement specify a point right on the
  9325.       border of the figure, then no painting occurs:
  9326.  
  9327.       LINE (50, 50)-(150, 150), , B  ' Draw a box.
  9328.       PAINT (50, 100)  ' The point with coordinates
  9329.                        ' (50, 100) is on the top edge of the
  9330.                        ' box, so no painting occurs.
  9331.  
  9332.    2. The figure must be completely enclosed; otherwise, the paint color will
  9333.       "leak out," filling the entire screen or viewport (or any larger figure
  9334.       completely enclosing the first one).
  9335.  
  9336.       For example, in the following program, the CIRCLE statement draws an
  9337.       ellipse that is not quite complete (there is a small gap on the right
  9338.       side); the LINE statement then encloses the partial ellipse inside a
  9339.       box. Even though painting starts in the interior of the ellipse, the
  9340.       paint color flows through the gap and fills the entire box.
  9341.  
  9342.       SCREEN 2
  9343.       CONST PI = 3.141592653589#
  9344.       CIRCLE (300, 100), 80, , 0, 1.9 * PI, 3
  9345.       LINE (200, 10)-(400, 190), , B
  9346.       PAINT (300, 100)
  9347.  
  9348.    3. If you are painting an object a different color from the one used to
  9349.       outline the object, you must use the border option to tell PAINT where
  9350.       to stop painting.
  9351.  
  9352.       For example, the following program draws a triangle outlined in green
  9353.       (attribute 1 in palette 0) and then tries to paint the interior of the
  9354.       triangle red (attribute 2). However, since the PAINT statement doesn't
  9355.       indicate where to stop painting, it paints the entire screen red.
  9356.  
  9357.       SCREEN 1
  9358.       COLOR , 0
  9359.  
  9360.       LINE (10, 25)-(310, 25), 1
  9361.       LINE -(160, 175), 1
  9362.       LINE -(10, 25), 1
  9363.  
  9364.       PAINT (160, 100), 2
  9365.  
  9366.       Making the following change to the PAINT statement (choose red for the
  9367.       interior and stop when a border colored green is reached) produces the
  9368.       desired effect:
  9369.  
  9370.       PAINT (160, 100), 2, 1
  9371.  
  9372.       Note that you don't have to specify a border color in the PAINT
  9373.       statement if the paint color is the same as the border color.
  9374.  
  9375.       LINE (10, 25)-(310, 25), 1
  9376.       LINE -(160, 175), 1
  9377.       LINE -(10, 25), 1
  9378.  
  9379.       PAINT (160, 100), 1
  9380.  
  9381.  5.8.2  Painting with Patterns: Tiling
  9382.  
  9383.    You can use the PAINT statement to fill any enclosed figure with a
  9384.    pattern; this process is known as "tiling." A "tile" is the pattern's
  9385.    basic building block. The process is identical to laying down tiles on a
  9386.    floor. When you use tiling, the argument interior in the syntax for PAINT
  9387.    is a string expression, rather than a number. While interior can be any
  9388.    string expression, a convenient way to define tile patterns uses the
  9389.    following form for interior:
  9390.  
  9391.    CHR$(arg1) + CHR$(arg2) + CHR$(arg3) + ... + CHR$(argn)
  9392.  
  9393.    Here, arg1, arg2, and so forth are eight-bit integers. See Sections
  9394.    5.8.2.2-5.8.2.4 below for an explanation of how these eight-bit integers
  9395.    are derived.
  9396.  
  9397.    5.8.2.1  Pattern-Tile Size in Different Screen Modes
  9398.  
  9399.    Each tile for a pattern is composed of a rectangular grid of pixels. This
  9400.    tile grid can have up to 64 rows in all screen modes. However, the number
  9401.    of pixels in each row depends on the screen mode.
  9402.  
  9403.    Here is why the length of each tile row varies according to the screen
  9404.    mode: although the number of bits in each row is fixed at eight (the
  9405.    length of an integer), the number of pixels these eight bits can represent
  9406.    decreases as the number of color attributes in a given screen mode
  9407.    increases. For example, in screen mode 2, which has only 1 color
  9408.    attribute, the number of bits per pixel is 1; in screen mode 1, which has
  9409.    4 different attributes, the number of bits per pixel is 2; and in the EGA
  9410.    screen mode 7, which has 16 attributes, the number of bits per pixel is 4.
  9411.    The following formula allows you to compute the bits per pixel in any
  9412.    given screen mode:
  9413.  
  9414.    bits-per-pixel = log2(numattributes)
  9415.  
  9416.    Here, numattributes is the number of color attributes in that screen mode.
  9417.    (The on-line QB Advisor has this information.)
  9418.  
  9419.    Thus, the length of a tile row is eight pixels in screen mode 2 (eight
  9420.    bits divided by one bit per pixel), but only four pixels in screen mode 1
  9421.    (eight bits divided by two bits per pixel).
  9422.  
  9423.    The next three sections show the step-by-step process involved in creating
  9424.    a pattern tile. Section 5.8.2.2 shows how to make a monochrome pattern in
  9425.    screen mode 2. Next, Section 5.8.2.3 shows how to make a multicolored
  9426.    pattern in screen mode 1. Finally, if you have an EGA, read Section
  9427.    5.8.2.4 to see how to make a multicolored pattern in screen mode 8.
  9428.  
  9429.    5.8.2.2  Creating a Single-Color Pattern in Screen Mode 2
  9430.  
  9431.    The following steps show how to define and use a pattern tile that
  9432.    resembles the letter "M":
  9433.  
  9434.    1. Draw the pattern for a tile in a grid with 8 columns and however many
  9435.       rows you need (up to 64). In this example, the tile has 6 rows; an
  9436.       asterisk (*) in a box means the pixel is on:
  9437.  
  9438.       ┌──────────────────────────────────────────────────────────────────┐
  9439.       │            1 pixel                                               │
  9440.       │            ┌──┴───┐                                              │
  9441.       │          ┌ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐     │
  9442.       │ 1 pixel ─┤ │  *  │     │     │     │     │  *  │     │     │     │
  9443.       │          └ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤     │
  9444.       │            │  *  │  *  │     │     │  *  │  *  │     │     │     │
  9445.       │            ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤     │
  9446.       │            │  *  │     │  *  │  *  │     │  *  │     │     │     │
  9447.       │            ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤     │
  9448.       │            │  *  │     │     │     │     │  *  │     │     │     │
  9449.       │            ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤     │
  9450.       │            │  *  │     │     │     │     │  *  │     │     │     │
  9451.       │            ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤     │
  9452.       │            │  *  │     │     │     │     │  *  │     │     │     │
  9453.       │            ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤     │
  9454.       │            │     │     │     │     │     │     │     │     │     │
  9455.       │            └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘     │
  9456.       │                                                                  │
  9457.       └──────────────────────────────────────────────────────────────────┘
  9458.  
  9459.    2. Next, translate each row of pixels to an eight-bit number, with a 1
  9460.       meaning the pixel is on, and a 0 meaning the pixel is off:
  9461.  
  9462.       ┌─────────────────────────────────────────────────────────────────┐
  9463.       │                                                                 │
  9464.       │        ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐        │
  9465.       │        │  1  │  0  │  0  │  0  │  0  │  1  │  0  │  0  │        │
  9466.       │        ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤        │
  9467.       │        │  1  │  1  │  0  │  0  │  0  │  1  │  0  │  0  │        │
  9468.       │        ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤        │
  9469.       │        │  1  │  0  │  1  │  1  │  0  │  1  │  0  │  0  │        │
  9470.       │        ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤        │
  9471.       │        │  1  │  0  │  0  │  0  │  0  │  1  │  0  │  0  │        │
  9472.       │        ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤        │
  9473.       │        │  1  │  0  │  0  │  0  │  0  │  1  │  0  │  0  │        │
  9474.       │        ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤        │
  9475.       │        │  1  │  0  │  0  │  0  │  0  │  1  │  0  │  0  │        │
  9476.       │        ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤        │
  9477.       │        │  0  │  0  │  0  │  0  │  0  │  0  │  0  │  0  │        │
  9478.       │        └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘        │
  9479.       │                                                                 │
  9480.       │                                                                 │
  9481.       └─────────────────────────────────────────────────────────────────┘
  9482.  
  9483.    3. Convert the binary numbers given in step 2 to hexadecimal integers:
  9484.  
  9485.       10000100 = &H84
  9486.       11001100 = &HCC
  9487.       10110100 = &HB4
  9488.       10000100 = &H84
  9489.       10000100 = &H84
  9490.       00000000 = &H00
  9491.  
  9492.       These integers do not have to be hexadecimal; they could be decimal or
  9493.       octal. However, binary to hexadecimal conversion easier. To convert
  9494.       from binary to hexadecimal, read the binary number from right to left.
  9495.       Each group of four digits is then converted to its hexadecimal
  9496.       equivalent, as shown here:
  9497.  
  9498.       ┌───────────────────────────────────────────────────────────┐
  9499.       │                                                           │
  9500.       │                Binary         1010    1001    1111        │
  9501.       │                              └─┬──┘  └─┬──┘  └─┬──┘       │
  9502.       │                                │       │       │          │
  9503.       │                Hexadecimal     A       9       F          │
  9504.       │                                                           │
  9505.       └───────────────────────────────────────────────────────────┘
  9506.  
  9507.       Table 5.3 lists four-bit binary sequences and their hexadecimal
  9508.       equivalents.
  9509.  
  9510.    4. Create a string by concatenating the characters with the ASCII values
  9511.       from step 3 (use the CHR$ function to get these characters):
  9512.  
  9513.       Tile$ = CHR$(&H84) + CHR$(&HCC) + CHR$(&HB4)
  9514.       Tile$ = Tile$ + CHR$(&H84) + CHR$(&H84) + CHR$(&H00)
  9515.  
  9516.    5. Draw a figure and paint its interior, using PAINT and the string
  9517.       argument from step 4:
  9518.  
  9519.       PAINT (X, Y), Tile$
  9520.  
  9521.    Table 5.3  Binary to Hexadecimal Conversion
  9522. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  9523.    Binary Number            Hexadecimal Number
  9524.    ──────────────────────────────────────────────────────────────────────────
  9525.    0000                     0
  9526.  
  9527.    0001                     1
  9528.  
  9529.    0010                     2
  9530.  
  9531.    0011                     3
  9532.  
  9533.    0100                     4
  9534.  
  9535.    0101                     5
  9536.    Binary Number            Hexadecimal Number
  9537.    ──────────────────────────────────────────────────────────────────────────
  9538.   0101                     5
  9539.  
  9540.    0110                     6
  9541.  
  9542.    0111                     7
  9543.  
  9544.    1000                     8
  9545.  
  9546.    1001                     9
  9547.  
  9548.    1010                     A
  9549.  
  9550.    1011                     B
  9551.  
  9552.    1100                     C
  9553.  
  9554.    1101                     D
  9555.  
  9556.    1110                     E
  9557.    Binary Number            Hexadecimal Number
  9558.    ──────────────────────────────────────────────────────────────────────────
  9559.   1110                     E
  9560.  
  9561.    1111                     F
  9562.    ──────────────────────────────────────────────────────────────────────────
  9563.  
  9564.  
  9565.    Example
  9566.  
  9567.    The following example draws a circle and then paints the circle's interior
  9568.    with the pattern created in the preceding steps:
  9569.  
  9570.    SCREEN 2
  9571.    CLS
  9572.    Tile$ = CHR$(&H84) + CHR$(&HCC) + CHR$(&HB4)
  9573.    Tile$ = Tile$ + CHR$(&H84) + CHR$(&H84) + CHR$(&H00)
  9574.    CIRCLE STEP(0, 0), 150
  9575.    PAINT STEP(0, 0), Tile$
  9576.  
  9577.    Output
  9578.  
  9579.  
  9580.    ┌────────────────────────────────────┐
  9581.    │                                    │
  9582.    │   Figure 5.5 can be found on       │
  9583.    │   page 184 of the printed manual.  │
  9584.    │                                    │
  9585.    └────────────────────────────────────┘
  9586.  
  9587.    Figure 5.5  Patterned Circle
  9588.  
  9589.    5.8.2.3  Creating a Multicolor Pattern in Screen Mode 1
  9590.  
  9591.    The following steps show how to create a multicolor pattern consisting of
  9592.    alternating diagonal stripes of cyan and magenta (or green and red in
  9593.    palette 0):
  9594.  
  9595.    1. Draw the pattern for a tile in a grid with four columns (four columns
  9596.       because each row of pixels is stored in an eight-bit integer and each
  9597.       pixel in screen mode 1 requires two bits) and however many rows you
  9598.       need (up to 64). In this example, the tile has four rows, as shown in
  9599.       the next diagram:
  9600.  
  9601.       ┌──────────────────────────────────────────────────────────────────┐
  9602.       │                                                                  │
  9603.       │              1 pixel                                             │
  9604.       │             ┌────┴───┐                                           │
  9605.       │           ┌─┌────────┬────────┬────────┬────────┐                │
  9606.       │   1 pixel ┤ │  cyan  │magenta │magenta │magenta │                │
  9607.       │           │ │        │        │        │        │                │
  9608.       │           └─├────────┼────────┼────────┼────────┤                │
  9609.       │             │ magenta│ cyan   │magenta │magenta │                │
  9610.       │             │        │        │        │        │                │
  9611.       │             ├────────┼────────┼────────┼────────┤                │
  9612.       │             │ magenta│ magenta│ cyan   │magenta │                │
  9613.       │             │        │        │        │        │                │
  9614.       │             ├────────┼────────┼────────┼────────┤                │
  9615.       │             │ magenta│ magenta│ magenta│ cyan   │                │
  9616.       │             │        │        │        │        │                │
  9617.       │             └────────┴────────┴────────┴────────┘                │
  9618.       │                                                                  │
  9619.       └──────────────────────────────────────────────────────────────────┘
  9620.  
  9621.    2. Convert the colors to their respective color numbers in binary
  9622.       notation, as shown below (be sure to use two-bit values, so 1 that =
  9623.       binary 01 and 2 = binary 10):
  9624.  
  9625.       ┌──────────────────────────────────────────────────────────────────┐
  9626.       │                                                                  │
  9627.       │              2 bits                                              │
  9628.       │             ┌───┴────┐                                           │
  9629.       │             ┌────────┬────────┬────────┬────────┐                │
  9630.       │             │  01    │  10    │  10    │  10    │                │
  9631.       │             │        │        │        │        │                │
  9632.       │             ├────────┼────────┼────────┼────────┤                │
  9633.       │             │  10    │  01    │  10    │  10    │                │
  9634.       │             │        │        │        │        │                │
  9635.       │             ├────────┼────────┼────────┼────────┤                │
  9636.       │             │  10    │  10    │  01    │  10    │                │
  9637.       │             │        │        │        │        │                │
  9638.       │             ├────────┼────────┼────────┼────────┤                │
  9639.       │             │  10    │  10    │  10    │  01    │                │
  9640.       │             │        │        │        │        │                │
  9641.       │             └────────┴────────┴────────┴────────┘                │
  9642.       │                                                                  │
  9643.       └──────────────────────────────────────────────────────────────────┘
  9644.  
  9645.    3. Convert the binary numbers from step 2 to hexadecimal integers:
  9646.  
  9647.       01101010 = &H6A
  9648.       10011010 = &H9A
  9649.       10100110 = &HA6
  9650.       10101001 = &HA9
  9651.  
  9652.    4. Create a string by concatenating the characters with the ASCII values
  9653.       from step 3 (use the CHR$ function to get these characters):
  9654.  
  9655.       Tile$ = CHR$(&H6A) + CHR$(&H9A) + CHR$(&HA6) + CHR$(&HA9)
  9656.  
  9657.    5. Draw a figure and paint its interior using PAINT and the string
  9658.       argument from step 4:
  9659.  
  9660.       PAINT (X, Y), Tile$
  9661.  
  9662.    The following program draws a triangle and then paints its interior with
  9663.    the pattern created in the preceding steps:
  9664.  
  9665.    SCREEN 1
  9666.  
  9667.    ' Define a pattern:
  9668.    Tile$ = CHR$(&H6A) + CHR$(&H9A) + CHR$(&HA6) + CHR$(&HA9)
  9669.  
  9670.    ' Draw a triangle in white (color 3):
  9671.    LINE (10, 25)-(310, 25)
  9672.    LINE -(160, 175)
  9673.    LINE -(10, 25)
  9674.  
  9675.    ' Paint the interior of the triangle with the pattern:
  9676.    PAINT (160, 100), Tile$
  9677.  
  9678.    Note that if the figure you want to paint is outlined in a color that is
  9679.    also contained in the pattern, then you must give the border argument with
  9680.    PAINT as shown below; otherwise, the pattern spills over the edges of the
  9681.    figure:
  9682.  
  9683.    SCREEN 1
  9684.  
  9685.    ' Define a pattern:
  9686.    Tile$ = CHR$(&H6A) + CHR$(&H9A) + CHR$(&HA6) + CHR$(&HA9)
  9687.  
  9688.    ' Draw a triangle in magenta (color 2):
  9689.    LINE (10, 25)-(310, 25), 2
  9690.    LINE -(160, 175), 2
  9691.    LINE -(10, 25), 2
  9692.  
  9693.    ' Paint the interior of the triangle with the pattern,
  9694.    ' adding the border argument (, 2) to tell PAINT
  9695.    ' where to stop:
  9696.    PAINT (160, 100), Tile$, 2
  9697.  
  9698.    Sometimes, after painting a figure with a solid color or pattern, you may
  9699.    want to repaint that figure, or some part of it, with a new pattern. If
  9700.    the new pattern contains two or more adjacent rows that are the same as
  9701.    the figure's current background, you will find that tiling does not work.
  9702.    Instead, the pattern starts to spread, finds itself surrounded by pixels
  9703.    that are the same as two or more of its rows, then stops.
  9704.  
  9705.    You can alleviate this problem by using the background argument with PAINT
  9706.    if there are at most two adjacent rows in your new pattern that are the
  9707.    same as the old background. PAINT with background has the following
  9708.    syntax:
  9709.  
  9710.    PAINT[[ STEP]] (x, y) [[,[[ interior]][[,[[ border]][[,background]] ]]]]
  9711.  
  9712.    The background argument is a string character of the form CHR$(n) that
  9713.    specifies the rows in the pattern tile that are the same as the figure's
  9714.    current background. In essence, background tells PAINT to skip over these
  9715.    rows when repainting the figure. The next example clarifies how this
  9716.    works:
  9717.  
  9718.    SCREEN 1
  9719.  
  9720.    ' Define a pattern (two rows each of cyan, magenta, white):
  9721.    Tile$ = CHR$(&H55) + CHR$(&H55) + CHR$(&HAA)
  9722.    Tile$ = Tile$ + CHR$(&HAA) + CHR$(&HFF) + CHR$(&HFF)
  9723.  
  9724.    ' Draw a triangle in white (color number 3):
  9725.    LINE (10, 25)-(310, 25)
  9726.    LINE -(160, 175)
  9727.    LINE -(10, 25)
  9728.  
  9729.    ' Paint the interior magenta:
  9730.    PAINT (160, 100), 2, 3
  9731.  
  9732.    ' Wait for a keystroke:
  9733.    Pause$ = INPUT$(1)
  9734.  
  9735.    ' Since the background is already magenta, CHR$(&HAA) tells
  9736.    ' PAINT to skip over the magenta rows in the pattern tile:
  9737.    PAINT (160, 100), Tile$, , CHR$(&HAA)
  9738.  
  9739.    5.8.2.4  Creating a Multicolor Pattern in Screen Mode 8
  9740.  
  9741.    In the EGA and VGA screen modes, it takes more than one eight-bit integer
  9742.    to define one row in a pattern tile. In these screen modes, a row is
  9743.    composed of several layers of eight-bit integers. This is because a pixel
  9744.    is represented three dimensionally in a stack of "bit planes" rather than
  9745.    sequentially in a single plane, as is the case with screen modes 1 and 2.
  9746.    For example, screen mode 8 has four of these bit planes. Each of the four
  9747.    bits per pixel in this screen mode is on a different plane.
  9748.  
  9749.    The following steps diagram the process for creating a multicolor pattern
  9750.    consisting of rows of alternating yellow and magenta. Note how each row in
  9751.    the pattern tile is represented by four parallel bytes:
  9752.  
  9753.    1. Define one row of pixels in the pattern tile. Each pixel in the row
  9754.       takes four bits, and each bit is in a different plane, as shown below:
  9755.  
  9756.       ┌───────────────────────────────────────────────────────────────────────
  9757.       │
  9758.       │                  Read bits for each
  9759.       │                 plane in this order.
  9760.       │                ────────────────────────────────
  9761.       │                 ─────────────────────────────────
  9762.       │              / / 1 / 1 / 0 / 0 / 0 / 0 / 1 / 1  /──── CHR$ (&HC3) + /
  9763.       │Read bits for/ / 0 / 0 / 1 / 1 / 1 / 1 / 0 / 0  /──── CHR$ (&H3C) + /
  9764.       │each pixel  / / 1 / 1 / 1 / 1 / 1 / 1 / 1 / 1  /──── CHR$ (&HFF) + /AD
  9765.       │in this    / / 0 / 0 / 1 / 1 / 1 / 1 / 0 / 0  /──── CHR$ (&H3C)  /CHR$
  9766.       │order.    / /────────────────────────────────/                    valu
  9767.       │     Magenta ─┘   │   │   │   │   │    │   │                       in t
  9768.       │         Magenta ─┘   │   │   │   │    │   │                       orde
  9769.       │              Yellow ─┘   │   │   │    │   │
  9770.       │                  Yellow ─┘   │   │    │   │   ┌───────────────────────
  9771.       │                      Yellow ─┘   │    │   │   │Color   Decimal    Bina
  9772.       │                          Yellow ─┘    │   │   │Yellow  14         1110
  9773.       │                              Magenta ─┘   │   │Magenta  5         0101
  9774.       │                                  Magenta ─┘   └───────────────────────
  9775.       │
  9776.       └───────────────────────────────────────────────────────────────────────
  9777.  
  9778.       Add the CHR$ values for all four bit planes to get one tile byte. This
  9779.       row is repeated in the pattern tile, so
  9780.  
  9781.       Row$(1) = Row$(2) =
  9782.             CHR$(&HC3) + CHR$(&H3C) + CHR$(&HFF) + CHR$(&H3C)
  9783.  
  9784.    2. Define another row of pixels in the pattern tile, as follows:
  9785.  
  9786.       ┌───────────────────────────────────────────────────────────────────────
  9787.       │
  9788.       │                  Read bits for each
  9789.       │                 plane in this order.
  9790.       │                ────────────────────────────────
  9791.       │                 ─────────────────────────────────
  9792.       │              / / 0 / 0 / 1 / 1 / 1 / 1 / 0 / 0  /──── CHR$ (&HC3) + /
  9793.       │Read bits for/ / 1 / 1 / 0 / 0 / 0 / 0 / 1 / 1  /──── CHR$ (&H3C) + /
  9794.       │each pixel  / / 1 / 1 / 1 / 1 / 1 / 1 / 1 / 1  /──── CHR$ (&HFF) + /AD
  9795.       │in this    / / 1 / 1 / 0 / 0 / 0 / 0 / 1 / 1  /──── CHR$ (&H3C)  /CHR$
  9796.       │order.    / /────────────────────────────────/                    valu
  9797.       │      Yellow ─┘   │   │   │   │   │    │   │                       in t
  9798.       │          Yellow ─┘   │   │   │   │    │   │                       orde
  9799.       │             Magenta ─┘   │   │   │    │   │
  9800.       │                 Magenta ─┘   │   │    │   │   ┌───────────────────────
  9801.       │                     Magenta ─┘   │    │   │   │Color   Decimal    Bina
  9802.       │                         Magenta ─┘    │   │   │Yellow  14         1110
  9803.       │                               Yellow ─┘   │   │Magenta  5         0101
  9804.       │                                   Yellow ─┘   └───────────────────────
  9805.       │
  9806.       └───────────────────────────────────────────────────────────────────────
  9807.  
  9808.       This row is also repeated in the pattern tile, so
  9809.  
  9810.       Row$(3) = Row$(4) =
  9811.             CHR$(&H3C) + CHR$(&HC3) + CHR$(&HFF) + CHR$(&HC3)
  9812.  
  9813.    Example
  9814.  
  9815.    The following example draws a box, then paints its interior with the
  9816.    pattern created in the preceding steps:
  9817.  
  9818.    SCREEN 8
  9819.    DIM Row$(1 TO 4)
  9820.  
  9821.    ' Two rows of alternating magenta and yellow:
  9822.    Row$(1) = CHR$(&HC3) + CHR$(&H3C) + CHR$(&HFF) + CHR$(&H3C)
  9823.    Row$(2) = Row$(1)
  9824.  
  9825.    ' Invert the pattern (two rows of alternating yellow
  9826.    ' and magenta):
  9827.    Row$(3) = CHR$(&H3C) + CHR$(&HC3) + CHR$(&HFF) + CHR$(&HC3)
  9828.    Row$(4) = Row$(3)
  9829.  
  9830.    ' Create a pattern tile from the rows defined above:
  9831.    FOR I% = 1 TO 4
  9832.       Tile$ = Tile$ + Row$(I%)
  9833.    NEXT I%
  9834.  
  9835.    ' Draw box and fill it with the pattern:
  9836.    LINE (50, 50)-(570, 150), , B
  9837.    PAINT (320, 100), Tile$
  9838.  
  9839.  
  9840.  5.9  DRAW: a Graphics Macro Language
  9841.  
  9842.    The DRAW statement is a miniature language by itself. It draws and paints
  9843.    images on the screen using a set of one- or two-letter commands, known as
  9844.    "macros," embedded in a string expression.
  9845.  
  9846.    DRAW offers the following advantages over the other graphics statements
  9847.    discussed so far:
  9848.  
  9849.    ■ The macro string argument to DRAW is compact: a single, short string can
  9850.      produce the same output as several LINE statements.
  9851.  
  9852.    ■ Images created with DRAW can easily be scaled──that is, enlarged or
  9853.      reduced in size──by using the S macro in the macro string.
  9854.  
  9855.    ■ Images created with DRAW can be rotated any number of degrees by using
  9856.      the TA macro in the macro string.
  9857.  
  9858.    Consult the QB Advisor for more information.
  9859.  
  9860.    Example
  9861.  
  9862.    The following program gives a brief introduction to the movement macros U,
  9863.    D, L, R, E, F, G, and H; the "plot/don't plot" macro B; and the color
  9864.    macro C. This program draws horizontal, vertical, and diagonal lines in
  9865.    different colors, depending on which DIRECTION key on the numeric keypad
  9866.    (UP, DOWN, LEFT, PGUP, PGDN, and so on) is pressed.
  9867.  
  9868.    This program is in the file named PLOTTER.BAS on the QuickBASIC
  9869.    distribution disks.
  9870.  
  9871.    ' Values for keys on the numeric keypad and the spacebar:
  9872.    CONST UP = 72, DOWN = 80, LFT = 75, RGHT = 77
  9873.    CONST UPLFT = 71, UPRGHT = 73, DOWNLFT = 79, DOWNRGHT = 81
  9874.    CONST SPACEBAR = " "
  9875.  
  9876.    ' Null$ is the first character of the two-character INKEY$
  9877.    ' value returned for direction keys such as UP and DOWN:
  9878.    Null$ = CHR$(0)
  9879.  
  9880.    ' Plot$ = "" means draw lines; Plot$ = "B" means
  9881.    ' move graphics cursor, but don't draw lines:
  9882.    Plot$ = ""
  9883.  
  9884.    PRINT "Use the cursor movement keys to draw lines."
  9885.    PRINT "Press spacebar to toggle line drawing on and off."
  9886.    PRINT "Press <ENTER> to begin. Press q to end the program."
  9887.    DO : LOOP WHILE INKEY$ = ""
  9888.  
  9889.    SCREEN 1
  9890.  
  9891.    DO
  9892.       SELECT CASE KeyVal$
  9893.          CASE Null$ + CHR$(UP)
  9894.             DRAW Plot$ + "C1 U2"
  9895.          CASE Null$ + CHR$(DOWN)
  9896.             DRAW Plot$ + "C1 D2"
  9897.          CASE Null$ + CHR$(LFT)
  9898.             DRAW Plot$ + "C2 L2"
  9899.          CASE Null$ + CHR$(RGHT)
  9900.             DRAW Plot$ + "C2 R2"
  9901.          CASE Null$ + CHR$(UPLFT)
  9902.             DRAW Plot$ + "C3 H2"
  9903.          CASE Null$ + CHR$(UPRGHT)
  9904.             DRAW Plot$ + "C3 E2"
  9905.          CASE Null$ + CHR$(DOWNLFT)
  9906.             DRAW Plot$ + "C3 G2"
  9907.          CASE Null$ + CHR$(DOWNRGHT)
  9908.             DRAW Plot$ + "C3 F2"
  9909.          CASE SPACEBAR
  9910.             IF Plot$ = "" THEN Plot$ = "B " ELSE Plot$ = ""
  9911.          CASE ELSE
  9912.             ' The user pressed some key other than one of the
  9913.             ' direction keys, the spacebar, or "q," so
  9914.             ' don't do anything.
  9915.       END SELECT
  9916.  
  9917.       KeyVal$ = INKEY$
  9918.  
  9919.    LOOP UNTIL KeyVal$ = "q"
  9920.  
  9921.    SCREEN 0, 0             ' Restore the screen to 80-column
  9922.    WIDTH 80                ' text mode and end.
  9923.    END
  9924.  
  9925.    Output
  9926.  
  9927.    Here's a sample sketch created with this program.
  9928.  
  9929.    ┌──────────────────────────────────────────────────────────────────┐
  9930.    │                                                                  │
  9931.    │                                                                  │
  9932.    │        / ────\ │     │ │ ┌────\  │   /        │                  │
  9933.    │        │     │ │     │ │ │       │ /          │                  │
  9934.    │        │     │ │     │ │ │       /\           │                  │
  9935.    │        │     │ │     │ │ │       │  \         │                  │
  9936.    │        \────\/ \─────/ │ \─────/ │    \                         │
  9937.    │              \                                                   │
  9938.    │        ─────────────────────────────────                         │
  9939.    │                                                                  │
  9940.    │          ───────────────────────────────                         │
  9941.    │                                                                  │
  9942.    │             ────────────────────────────                         │
  9943.    │                                                                  │
  9944.    └──────────────────────────────────────────────────────────────────┘
  9945.  
  9946.  
  9947.  5.10  Basic Animation Techniques
  9948.  
  9949.    Using only the graphics statements covered in earlier sections, you can do
  9950.    simple animation of objects on the screen. For instance, you can first
  9951.    draw a circle with CIRCLE, then redraw it with the background color to
  9952.    erase it, and finally recalculate the circle's center point and draw it in
  9953.    a new location.
  9954.  
  9955.    This technique works well enough for simple figures, but its disadvantages
  9956.    become apparent when animating more complex images. Even though the
  9957.    graphics statements are very fast, you can still notice the lag. Moreover,
  9958.    it is not possible to preserve the background with this method: when you
  9959.    erase the object, you also erase whatever was already on the screen.
  9960.  
  9961.    Two statements allow you to do high-speed animation: GET and PUT. You can
  9962.    create an image using output from statements such as PSET, LINE, CIRCLE,
  9963.    or PAINT, then take a "snapshot" of that image with GET, copying the image
  9964.    to memory. With PUT, you can then reproduce the image stored with GET
  9965.    anywhere on the screen or viewport.
  9966.  
  9967.  5.10.1  Saving Images with GET
  9968.  
  9969.    After you have created the original image on the screen, you need to
  9970.    calculate the x- and y-coordinates of a rectangle large enough to hold the
  9971.    entire image. You then use GET to copy the entire rectangle to memory. The
  9972.    syntax for the graphics GET statement is
  9973.  
  9974.    GET[[STEP]](x1, y1) -[[STEP]](x2, y2), array-name
  9975.  
  9976.    where (x1, y1) and (x2, y2) give the coordinates of a rectangle's
  9977.    upper-left and lower-right corners. The argument array-name refers to any
  9978.    numeric array. The size specified in a DIM statement for array-name
  9979.    depends on the following three factors:
  9980.  
  9981.    1. The height and width of the rectangle enclosing the image
  9982.  
  9983.    2. The screen mode chosen for graphics output
  9984.  
  9985.    3. The type of the array (integer, long integer, single precision, or
  9986.       double precision)
  9987.  
  9988.    ──────────────────────────────────────────────────────────────────────────
  9989.    NOTE
  9990.      Although the array used to store images can have any numeric type, it is
  9991.      strongly recommended that you use only integer arrays. All possible
  9992.      graphics patterns on the screen can be represented by integers. This is
  9993.      not the case, however, with single-precision or double-precision real
  9994.      numbers: some graphics patterns are not valid real numbers, and it could
  9995.      lead to unforeseen results if these patterns were stored in a
  9996.      real-number array.
  9997.    ──────────────────────────────────────────────────────────────────────────
  9998.  
  9999.    The formula for calculating the size in bytes of arrayname is
  10000.  
  10001.    size-in-bytes = 4 + height * planes * INT((width * bits-per-pixel/planes +
  10002.    7)/8)
  10003.  
  10004.    where height and width are the dimensions, in number of pixels, of the
  10005.    rectangle to get, and the value for bits-per-pixel depends on the number
  10006.    of colors available in the given screen mode. More colors mean more bits
  10007.    are required to define each pixel. In screen mode 1, two bits define a
  10008.    pixel, while in screen mode 2, one bit is enough. (See Section 5.8.2.1
  10009.    above, "Pattern-Tile Size in Different Screen Modes," for the general
  10010.    formula for bits-per-pixel.) The following list shows the value for planes
  10011.    for each of the screen modes:
  10012.  
  10013.    Screen Mode                                             Number of Bit
  10014.                                                            Planes
  10015.    ──────────────────────────────────────────────────────────────────────────
  10016.    1, 2, 11, and 13                                        1
  10017.  
  10018.    9 (64K of video memory) and 10                          2
  10019.  
  10020.    7, 8, 9 (more than 64K of video memory), and 12         4
  10021.    ──────────────────────────────────────────────────────────────────────────
  10022.  
  10023.    To get the number of elements that should be in the array, divide the
  10024.    size-in-bytes by the number of bytes for one element in the array. This is
  10025.    where the type of the array comes into play. If it is an integer array,
  10026.    each element takes two bytes of memory (the size of an integer), so
  10027.    size-in-bytes should be divided by two to get the actual size of the
  10028.    array. Similarly, if it is a long integer array, size-in-bytes should be
  10029.    divided by four (since one long integer requires four bytes of memory),
  10030.    and so on. If it is single precision, divide by four; if it is double
  10031.    precision, divide by eight.
  10032.  
  10033.    The following steps show how to calculate the size of an integer array
  10034.    large enough to hold a rectangle in screen mode 1 with coordinates (10,
  10035.    40) for the upper-left corner and (90, 80) for the lower-right corner:
  10036.  
  10037.    1. Calculate the height and width of the rectangle:
  10038.  
  10039.       RectHeight = ABS(y2 - y1) + 1 = 80 - 40 + 1 = 41
  10040.       RectWidth = ABS(x2 - x1) + 1 = 90 - 10 + 1 = 81
  10041.  
  10042.       Remember to add one after subtracting y1 from y2 or x1 from x2. For
  10043.       example, if x1 = 10 and x2 = 20, then the width of the rectangle is 20
  10044.       - 10 + 1, or 11.
  10045.  
  10046.    2. Calculate the size in bytes of the integer array:
  10047.  
  10048.       ByteSize = 4 + RectHeight * INT((RectWidth * BitsPerPixel + 7) / 8)
  10049.                = 4 + 41 * INT((81 * 2 + 7) / 8)
  10050.                = 4 + 41 * INT(169 / 8)
  10051.                = 4 + 41 * 21
  10052.                = 865
  10053.  
  10054.    3. Divide the size in bytes by the bytes per element (two for integers)
  10055.       and round the result up to the nearest whole number:
  10056.  
  10057.       865 / 2 = 433
  10058.  
  10059.    Therefore, if the name of the array is Image, the following DIM statement
  10060.    ensures that Image is big enough to copy the pixel information in the
  10061.    rectangle:
  10062.  
  10063.    DIM Image (1 TO 433) AS INTEGER
  10064.  
  10065.    ──────────────────────────────────────────────────────────────────────────
  10066.    NOTE
  10067.      Although the GET statement uses view coordinates after a WINDOW
  10068.      statement, you must use physical coordinates to calculate the size of
  10069.      the array used in GET. (See Section 5.6 above, "Redefining Viewport
  10070.      Coordinates with WINDOW," for more information on WINDOW and how to
  10071.      convert view coordinates to physical coordinates.)
  10072.    ──────────────────────────────────────────────────────────────────────────
  10073.  
  10074.    Note that the steps outlined above give the minimum size required for the
  10075.    array; however, any larger size will do. For example, the following
  10076.    statement also works:
  10077.  
  10078.    DIM Image (1 TO 500) AS INTEGER
  10079.  
  10080.    Example
  10081.  
  10082.    The following program draws an ellipse and paints its interior. A GET
  10083.    statement copies the rectangular area containing the ellipse into memory.
  10084.    (Section 5.10.2 below, "Moving Images with PUT," shows how to use the PUT
  10085.    statement to reproduce the ellipse in a different location.)
  10086.  
  10087.    SCREEN 1
  10088.  
  10089.    ' Dimension an integer array large enough
  10090.    ' to hold the rectangle:
  10091.    DIM Image (1 TO 433) AS INTEGER
  10092.  
  10093.    ' Draw an ellipse inside the rectangle, using magenta for
  10094.    ' the outline and painting the interior white:
  10095.    CIRCLE (50, 60), 40, 2, , , .5
  10096.    PAINT (50, 60), 3, 2
  10097.  
  10098.    ' Store the image of the rectangle in the array:
  10099.    GET (10, 40)-(90, 80), Image
  10100.  
  10101.  5.10.2  Moving Images with PUT
  10102.  
  10103.    While the GET statement allows you to take a snapshot of an image, PUT
  10104.    allows you to paste that image anywhere you want on the screen. A
  10105.    statement of the form
  10106.  
  10107.    PUT (x, y), array-name [[, actionverb]]
  10108.  
  10109.    copies the rectangular image stored in array-name back to the screen and
  10110.    places its upper-left corner at the point with coordinates (x, y). Note
  10111.    that only one coordinate pair appears in PUT.
  10112.  
  10113.    If a WINDOW statement appears in the program before PUT, the coordinates x
  10114.    and y refer to the lower-left corner of the rectangle. WINDOW SCREEN,
  10115.    however, does not have this effect; that is, after WINDOW SCREEN, x and y
  10116.    still refer to the upper-left corner of the rectangle.
  10117.  
  10118.    For example, adding the next line to the last example in Section 5.10.1
  10119.    above causes an exact duplicate of the painted ellipse to appear on the
  10120.    right side of the screen much more quickly than redrawing and repainting
  10121.    the same figure with CIRCLE and PAINT:
  10122.  
  10123.    PUT (200, 40), Image
  10124.  
  10125.    Take care not to specify coordinates that would put any part of the image
  10126.    outside the screen or active viewport, as in the following statements:
  10127.  
  10128.    SCREEN 2
  10129.    .
  10130.    .
  10131.    .
  10132.    ' Rectangle measures 141 pixels x 91 pixels:
  10133.    GET (10, 10)-(150, 100), Image
  10134.    PUT (510, 120), Image
  10135.  
  10136.    Unlike other graphics statements such as LINE or CIRCLE, PUT does not clip
  10137.    images lying outside the viewport. Instead, it produces an error message
  10138.    reading Illegal function call.
  10139.  
  10140.    One of the other advantages of the PUT statement is that you can control
  10141.    how the stored image interacts with what is already on the screen by using
  10142.    the argument actionverb. The actionverb argument can be one of the
  10143.    following options: PSET, PRESET, AND, OR, or XOR.
  10144.  
  10145.    If you do not care what happens to the existing screen background, use the
  10146.    PSET option, since it transfers an exact duplicate of the stored image to
  10147.    the screen and overwrites anything that was already there.
  10148.  
  10149.    Table 5.4 shows how other options affect the way the PUT statement causes
  10150.    pixels in a stored image to interact with pixels on the screen. In this
  10151.    table, a 1 means a pixel is on and a 0 means a pixel is off.
  10152.  
  10153.    Table 5.4  The Effect of Different Action Options in Screen Mode 2
  10154. ╓┌─┌──────────────────┌─────────────────┌──────────────────┌─────────────────╖
  10155.                                         Pixel on Screen    Pixel on Screen
  10156.                       Pixel in          before PUT         after PUT
  10157.    Action Option      Stored Image      Statement          Statement
  10158.    ──────────────────────────────────────────────────────────────────────────
  10159.    PSET               0                 0                  0
  10160.  
  10161.                       0                 1                  0
  10162.  
  10163.                       1                 0                  1
  10164.  
  10165.                       1                 1                  1
  10166.                                         Pixel on Screen    Pixel on Screen
  10167.                       Pixel in          before PUT         after PUT
  10168.    Action Option      Stored Image      Statement          Statement
  10169.    ──────────────────────────────────────────────────────────────────────────
  10170.                      1                 1                  1
  10171.  
  10172.    PRESET             0                 0                  1
  10173.  
  10174.                       0                 1                  1
  10175.  
  10176.                       1                 0                  0
  10177.  
  10178.                       1                 1                  0
  10179.  
  10180.    AND                0                 0                  0
  10181.  
  10182.                       0                 1                  0
  10183.  
  10184.                       1                 0                  0
  10185.  
  10186.                       1                 1                  1
  10187.                                         Pixel on Screen    Pixel on Screen
  10188.                       Pixel in          before PUT         after PUT
  10189.    Action Option      Stored Image      Statement          Statement
  10190.    ──────────────────────────────────────────────────────────────────────────
  10191.                      1                 1                  1
  10192.  
  10193.    OR                 0                 0                  0
  10194.  
  10195.                       0                 1                  1
  10196.  
  10197.                       1                 0                  1
  10198.  
  10199.                       1                 1                  1
  10200.  
  10201.    XOR                0                 0                  0
  10202.  
  10203.                       0                 1                  1
  10204.  
  10205.                       1                 0                  1
  10206.  
  10207.                       1                 1                  0
  10208.                                         Pixel on Screen    Pixel on Screen
  10209.                       Pixel in          before PUT         after PUT
  10210.    Action Option      Stored Image      Statement          Statement
  10211.    ──────────────────────────────────────────────────────────────────────────
  10212.                      1                 1                  0
  10213.    ──────────────────────────────────────────────────────────────────────────
  10214.  
  10215.  
  10216.    As you can see, these options cause a PUT statement to treat pixels the
  10217.    same way logical operators treat numbers. The PRESET option is like the
  10218.    logical operator NOT in that it inverts the pixels in the stored image,
  10219.    regardless of what was on the screen. The options AND, OR, and XOR are
  10220.    identical to the logical operators with the same names; for example, the
  10221.    logical operation
  10222.  
  10223.    1 XOR 1
  10224.  
  10225.    gives 0 as its result, just as using the XOR option turns a pixel off when
  10226.    both the pixel in the image and the pixel in the background are on.
  10227.  
  10228.    The output from the following program shows the same image superimposed
  10229.    over a filled rectangle using each of the five options discussed above:
  10230.  
  10231.    SCREEN 2
  10232.  
  10233.    DIM CircImage (1 TO 485) AS INTEGER
  10234.  
  10235.    ' Draw and paint an ellipse then store its image with GET:
  10236.    CIRCLE (22, 100), 80, , , , 4
  10237.    PAINT (22, 100)
  10238.    GET (0, 20)-(44, 180), CircImage
  10239.    CLS
  10240.  
  10241.    ' Draw a box and fill it with a pattern:
  10242.    LINE (40, 40)-(600, 160), , B
  10243.    Pattern$ = CHR$(126) + CHR$(0) + CHR$(126) + CHR$(126)
  10244.    PAINT (50, 50), Pattern$
  10245.  
  10246.    ' Put the images of the ellipse over the box
  10247.    ' using the different action options:
  10248.    PUT (100, 20), CircImage, PSET
  10249.    PUT (200, 20), CircImage, PRESET
  10250.    PUT (300, 20), CircImage, AND
  10251.    PUT (400, 20), CircImage, OR
  10252.    PUT (500, 20), CircImage, XOR
  10253.  
  10254.    Output
  10255.  
  10256.    ┌────────────────────────────────────┐
  10257.    │                                    │
  10258.    │     The output for this example    │
  10259.    │     can be found on page 199 of    │
  10260.    │     the printed manual.            │
  10261.    │                                    │
  10262.    └────────────────────────────────────┘
  10263.  
  10264.    In screen modes supporting color, the options PRESET, AND, OR, and XOR
  10265.    produce a more complicated interaction, since color involves more than
  10266.    simply turning a pixel on or off. However, the analogy made above between
  10267.    these options and logical operators still holds in these modes. For
  10268.    example, if the current pixel on the screen is color 1 (cyan in palette 1)
  10269.    and the pixel in the overlaid image is color 2 (magenta in palette 1),
  10270.    then the color of the resulting pixel after a PUT statement depends on the
  10271.    option, as shown for just 2 of the 16 different combinations of image
  10272.    color and background color in Table 5.5.
  10273.  
  10274.    Table 5.5  The Effect of Different Action Options on Color in Screen Mode
  10275.    1 (Palette 1)
  10276.                                         Pixel Color on     Pixel Color on
  10277.                       Pixel Color in    Screen before      Screen after PUT
  10278.    Action Option      Stored Image      PUT Statement      Statement
  10279.    ──────────────────────────────────────────────────────────────────────────
  10280.    PSET               10 (magenta)      01 (cyan)          10 (magenta)
  10281.  
  10282.    PRESET             10 (magenta)      01 (cyan)          01 (cyan)
  10283.  
  10284.    AND                10 (magenta)      01 (cyan)          00 (black)
  10285.  
  10286.    OR                 10 (magenta)      01 (cyan)          11 (white)
  10287.  
  10288.    XOR                10 (magenta)      01 (cyan)          11 (white)
  10289.    ──────────────────────────────────────────────────────────────────────────
  10290.  
  10291.    In palette 1, cyan is assigned to attribute 1 (01 binary), magenta is
  10292.    assigned to attribute 2 (10 binary), and white is assigned to attribute 3
  10293.    (11 binary). If you have an EGA, you can use the PALETTE statement to
  10294.    assign different colors to the attributes 1, 2, and 3.
  10295.  
  10296.  5.10.3  Animation with GET and PUT
  10297.  
  10298.    One of the most useful things that can be done with the GET and PUT
  10299.    statements is animation. The two options best suited for animation are XOR
  10300.    and PSET. Animation done with PSET is faster; but as shown by the output
  10301.    from the last program, PSET erases the screen background. In contrast, XOR
  10302.    is slower but restores the screen background after the image is moved.
  10303.    Animation with XOR is done with the following four steps:
  10304.  
  10305.    1. Put the object on the screen with XOR.
  10306.  
  10307.    2. Recalculate the new position of the object.
  10308.  
  10309.    3. Put the object on the screen a second time at the old location, using
  10310.       XOR again, this time to remove the old image.
  10311.  
  10312.    4. Go to step 1, but this time put the object at the new location.
  10313.  
  10314.    Movement done with these four steps leaves the background unchanged after
  10315.    step 3. Flicker can be reduced by minimizing the time between steps 4 and
  10316.    1 and by making sure that there is enough time delay between steps 1 and
  10317.    3. If more than one object is being animated, every object should be
  10318.    processed at once, one step at a time.
  10319.  
  10320.    If it is not important to preserve the background, use the PSET option for
  10321.    animation. The idea is to leave a border around the image when you copy it
  10322.    with the GET statement. If this border is as large or larger than the
  10323.    maximum distance the object will move, then each time the image is put in
  10324.    a new location, the border erases all traces of the image in the old
  10325.    location. This method can be somewhat faster than the method using XOR
  10326.    described above, since only one PUT statement is required to move an
  10327.    object (although you must move a larger image).
  10328.  
  10329.    Examples
  10330.  
  10331.    The following example shows how to use PUT with the PSET option to produce
  10332.    the effect of a ball bouncing off the bottom and sides of a box. Note in
  10333.    the output that follows how the rectangle containing the ball, specified
  10334.    in the GET statement, erases the filled box and the printed message.
  10335.  
  10336.    This program is in the file named BALLPSET.BAS on the QuickBASIC
  10337.    distribution disks.
  10338.  
  10339.    DECLARE FUNCTION GetArraySize (WLeft, WRight, WTop,
  10340.    WBottom)
  10341.  
  10342.    SCREEN 2
  10343.  
  10344.    ' Define a viewport and draw a border around it:
  10345.    VIEW (20, 10)-(620, 190),,1
  10346.  
  10347.    CONST PI = 3.141592653589#
  10348.  
  10349.    ' Redefine the coordinates of the viewport with view
  10350.    ' coordinates:
  10351.    WINDOW (-3.15, -.14)-(3.56, 1.01)
  10352.  
  10353.    ' Arrays in program are now dynamic:
  10354.    ' $DYNAMIC
  10355.  
  10356.    ' Calculate the view coordinates for the top and bottom of a
  10357.    ' rectangle large enough to hold the image that will be
  10358.    ' drawn with CIRCLE and PAINT:
  10359.    WLeft = -.21
  10360.    WRight = .21
  10361.    WTop = .07
  10362.    WBottom = -.07
  10363.  
  10364.    ' Call the GetArraySize function,
  10365.    ' passing it the rectangle's view coordinates:
  10366.    ArraySize% = GetArraySize(WLeft, WRight, WTop, WBottom)
  10367.  
  10368.    DIM Array (1 TO ArraySize%) AS INTEGER
  10369.  
  10370.    ' Draw and paint the circle:
  10371.    CIRCLE (0, 0), .18
  10372.    PAINT (0, 0)
  10373.  
  10374.    ' Store the rectangle in Array:
  10375.    GET (WLeft, WTop)-(WRight, WBottom), Array
  10376.    CLS
  10377.    ' Draw a box and fill it with a pattern:
  10378.    LINE (-3, .8)-(3.4, .2), , B
  10379.    Pattern$ = CHR$(126) + CHR$(0) + CHR$(126) + CHR$(126)
  10380.    PAINT (0, .5), Pattern$
  10381.  
  10382.    LOCATE 21, 29
  10383.    PRINT "Press any key to end."
  10384.  
  10385.    ' Initialize loop variables:
  10386.    StepSize = .02
  10387.    StartLoop = -PI
  10388.    Decay = 1
  10389.  
  10390.    DO
  10391.       EndLoop = -StartLoop
  10392.       FOR X = StartLoop TO EndLoop STEP StepSize
  10393.  
  10394.          ' Each time the ball "bounces" (hits the bottom of the
  10395.          ' viewport), the Decay variable gets smaller, making
  10396.          ' the height of the next bounce smaller:
  10397.          Y = ABS(COS(X)) * Decay - .14
  10398.          IF Y < -.13 THEN Decay = Decay * .9
  10399.  
  10400.          ' Stop if key pressed or Decay less than .01:
  10401.          Esc$ = INKEY$
  10402.          IF Esc$ <> "" OR Decay < .01 THEN EXIT FOR
  10403.  
  10404.          ' Put the image on the screen. The StepSize offset is
  10405.          ' smaller than the border around the circle. Thus,
  10406.          ' each time the image moves, it erases any traces
  10407.          ' left from the previous PUT (and also erases anything
  10408.          ' else on the screen):
  10409.          PUT (X, Y), Array, PSET
  10410.       NEXT X
  10411.  
  10412.       ' Reverse direction:
  10413.       StepSize = -StepSize
  10414.       StartLoop = -StartLoop
  10415.    LOOP UNTIL Esc$ <> "" OR Decay < .01
  10416.  
  10417.    END
  10418.  
  10419.    FUNCTION GetArraySize (WLeft, WRight, WTop, WBottom) STATIC
  10420.  
  10421.       ' Map the view coordinates passed to this function to
  10422.       ' their physical-coordinate equivalents:
  10423.       VLeft = PMAP(WLeft, 0)
  10424.       VRight = PMAP(WRight, 0)
  10425.       VTop = PMAP(WTop, 1)
  10426.       VBottom = PMAP(WBottom, 1)
  10427.  
  10428.    ' Calculate the height and width in pixels
  10429.       ' of the enclosing rectangle:
  10430.       RectHeight = ABS(VBottom - VTop) + 1
  10431.       RectWidth = ABS(VRight - VLeft) + 1
  10432.  
  10433.       ' Calculate size in bytes of array:
  10434.       ByteSize = 4 + RectHeight * INT((RectWidth + 7) \ 8)
  10435.  
  10436.       ' Array is integer, so divide bytes by two:
  10437.       GetArraySize = ByteSize \ 2 + 1
  10438.    END FUNCTION
  10439.  
  10440.    Output
  10441.  
  10442.    ┌────────────────────────────────────┐
  10443.    │                                    │
  10444.    │     The output for this example    │
  10445.    │     can be found on page 203 of    │
  10446.    │     the printed manual.            │
  10447.    │                                    │
  10448.    └────────────────────────────────────┘
  10449.  
  10450.    Contrast the preceding program with the next program, which uses PUT with
  10451.    XOR to preserve the screen's background, according to the four steps
  10452.    outlined above. Note how the rectangle containing the ball is smaller than
  10453.    in the preceding program, since it is not necessary to leave a border.
  10454.    Also note that two PUT statements are required, one to make the image
  10455.    visible and another to make it disappear. Finally, observe the empty
  10456.    FOR...NEXT delay loop between the PUT statements; this loop reduces the
  10457.    flicker that results from the image appearing and disappearing too
  10458.    rapidly.
  10459.  
  10460.    This program is in the file named BALLXOR.BAS on the QuickBASIC
  10461.    distribution disks.
  10462.  
  10463.    .
  10464.    .
  10465.    .
  10466.    ' The rectangle is smaller than the one in the previous
  10467.    ' program, which means Array is also smaller:
  10468.    WLeft = -.18
  10469.    WRight = .18
  10470.    WTop = .05
  10471.    WBottom = -.05
  10472.    .
  10473.    .
  10474.    .
  10475.    DO
  10476.       EndLoop = -StartLoop
  10477.       FOR X = StartLoop TO EndLoop STEP StepSize
  10478.          Y = ABS(COS(X)) * Decay - .14
  10479.  
  10480.          ' The first PUT statement places the image
  10481.          ' on the screen:
  10482.          PUT (X,Y), Array, XOR
  10483.  
  10484.          ' Use an empty FOR...NEXT loop to delay
  10485.          ' the program and reduce image flicker:
  10486.          FOR I = 1 TO 5: NEXT I
  10487.  
  10488.          IF Y < -.13 THEN Decay = Decay * .9
  10489.          Esc$ = INKEY$
  10490.          IF Esc$ <> "" OR Decay < .01 THEN EXIT FOR
  10491.  
  10492.          ' The second PUT statement erases the image and
  10493.          ' restores the background:
  10494.          PUT (X, Y), Array, XOR
  10495.       NEXT X
  10496.  
  10497.       StepSize = -StepSize
  10498.       StartLoop = -StartLoop
  10499.    LOOP UNTIL Esc$ <> "" OR Decay < .01
  10500.  
  10501.    END
  10502.    .
  10503.    .
  10504.    .
  10505.  
  10506.    Output
  10507.  
  10508.    ┌────────────────────────────────────┐
  10509.    │                                    │
  10510.    │     The output for this example    │
  10511.    │     can be found on page 205 of    │
  10512.    │     the printed manual.            │
  10513.    │                                    │
  10514.    └────────────────────────────────────┘
  10515.  
  10516.  5.10.4  Animating with Screen Pages
  10517.  
  10518.    This section describes an animation technique that utilizes multiple pages
  10519.    of your computer's video memory.
  10520.  
  10521.    Pages in video memory are analogous to pages in a book. Depending on the
  10522.    graphics capability of your computer, what you see displayed on the screen
  10523.    may only be part of the video memory available──just as what you see when
  10524.    you open a book is only part of the book. However, unlike a book, the
  10525.    unseen pages of your computer's video memory can be active; that is, while
  10526.    you are looking at one page on the screen, graphics output can be taking
  10527.    place on the others. It's as if the author of a book were still writing
  10528.    new pages even as you were reading the book.
  10529.  
  10530.    The area of video memory visible on the screen is called the "visual
  10531.    page," while the area of video memory where graphics statements put their
  10532.    output is called the "active page." The SCREEN statement allows you to
  10533.    select visual and active screen pages with the following syntax:
  10534.  
  10535.    SCREEN[[mode]],[[,[[apage]][[, vpage]]]]
  10536.  
  10537.    In this syntax, apage is the number of the active page, and vpage is the
  10538.    number of the visual page. The active page and the visual page can be one
  10539.    and the same (and are by default when the apage or vpage arguments are not
  10540.    used with SCREEN, in which case the value of both arguments is 0).
  10541.  
  10542.    You can animate objects on the screen by selecting a screen mode with more
  10543.    than one video memory page, then alternating the pages, sending output to
  10544.    one or more active pages while displaying finished output on the visual
  10545.    page. This technique makes an active page visible only when output to that
  10546.    page is complete. Since the viewer sees only a finished image, the display
  10547.    is instantaneous.
  10548.  
  10549.    Example
  10550.  
  10551.    The following program demonstrates the technique discussed above. It
  10552.    selects screen mode 7, which has two pages, then draws a cube with the
  10553.    DRAW statement. This cube is then rotated through successive 15° angles by
  10554.    changing the value of the TA macro in the string used by DRAW. By swapping
  10555.    the active and visual pages back and forth, this program always shows a
  10556.    completed cube while a new one is being drawn.
  10557.  
  10558.    This program is in the file named CUBE.BAS on the QuickBASIC distribution
  10559.    disks.
  10560.  
  10561.    ' Define the macro string used to draw the cube
  10562.    ' and paint its sides:
  10563.    One$ =  "BR30 BU25 C1 R54 U45 L54 D45 BE20 P1,1 G20 C2 G20"
  10564.    Two$ =  "R54 E20 L54 BD5 P2,2 U5 C4 G20 U45 E20 D45 BL5 P4,4"
  10565.    Plot$ = One$ + Two$
  10566.  
  10567.    APage% = 1      ' Initialize values for the active and visual
  10568.    VPage% = 0      ' pages as well as the angle of rotation.
  10569.    Angle% = 0
  10570.  
  10571.    DO
  10572.       SCREEN 7, , APage%, VPage% ' Draw to the active page
  10573.                                  ' while showing the visual page.
  10574.  
  10575.       CLS 1                      ' Clear the active page.
  10576.  
  10577.       ' Rotate the cube "Angle%" degrees:
  10578.       DRAW "TA" + STR$(Angle%) + Plot$
  10579.  
  10580.       ' Angle% is some multiple of 15 degrees:
  10581.       Angle% = (Angle% + 15) MOD 360
  10582.  
  10583.       ' Drawing is complete, so make the cube visible in its
  10584.       ' new position by switching the active and visual pages:
  10585.       SWAP APage%, VPage%
  10586.  
  10587.    LOOP WHILE INKEY$ = ""        ' A keystroke ends the program.
  10588.  
  10589.    END
  10590.  
  10591.  
  10592.  5.11  Sample Applications
  10593.  
  10594.    The sample applications in this chapter are a bar-graph generator, a
  10595.    program that plots points in the Mandelbrot Set using different colors,
  10596.    and a pattern editor.
  10597.  
  10598.  5.11.1  Bar-Graph Generator (BAR.BAS)
  10599.  
  10600.    This program uses all the forms of the LINE statement presented above in
  10601.    Sections 5.3.2.1-5.3.2.3 to draw a filled bar chart. Each bar is filled
  10602.    with a pattern specified in a PAINT statement. The input for the program
  10603.    consists of titles for the graph, labels for the x- and y-axes, and a set
  10604.    of up to five labels (with associated values) for the bars.
  10605.  
  10606.    Statements and Functions Used
  10607.  
  10608.    This program demonstrates the use of the following graphics statements:
  10609.  
  10610.    ■ LINE
  10611.  
  10612.    ■ PAINT (with a pattern)
  10613.  
  10614.    ■ SCREEN
  10615.  
  10616.    Program Listing
  10617.  
  10618.    The bar-graph generator program BAR.BAS is listed below.
  10619.  
  10620.    ' Define type for the titles:
  10621.    TYPE TitleType
  10622.       MainTitle AS STRING * 40
  10623.       XTitle AS STRING * 40
  10624.       YTitle AS STRING * 18
  10625.    END TYPE
  10626.  
  10627.    DECLARE SUB InputTitles (T AS TitleType)
  10628.    DECLARE FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value!(), N%)
  10629.    DECLARE FUNCTION InputData% (Label$(), Value!())
  10630.  
  10631.    ' Variable declarations for titles and bar data:
  10632.    DIM Titles AS TitleType, Label$(1 TO 5), Value(1 TO 5)
  10633.  
  10634.    CONST FALSE = 0, TRUE = NOT FALSE
  10635.  
  10636.    DO
  10637.       InputTitles Titles
  10638.       N% = InputData%(Label$(), Value())
  10639.       IF N% <> FALSE THEN
  10640.          NewGraph$ = DrawGraph$(Titles, Label$(), Value(), N%)
  10641.       END IF
  10642.    LOOP WHILE NewGraph$ = "Y"
  10643.  
  10644.    END
  10645.  
  10646.    ' ======================== DRAWGRAPH ======================
  10647.    '   Draws a bar graph from the data entered in the
  10648.    '   INPUTTITLES and INPUTDATA procedures.
  10649.    ' =========================================================
  10650.  
  10651.    FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value(), N%) STATIC
  10652.  
  10653.       ' Set size of graph:
  10654.       CONST GRAPHTOP = 24, GRAPHBOTTOM = 171
  10655.       CONST GRAPHLEFT = 48, GRAPHRIGHT = 624
  10656.       CONST YLENGTH = GRAPHBOTTOM - GRAPHTOP
  10657.  
  10658.       ' Calculate maximum and minimum values:
  10659.       YMax = 0
  10660.       YMin = 0
  10661.       FOR I% = 1 TO N%
  10662.          IF Value(I%) < YMin THEN YMin = Value(I%)
  10663.          IF Value(I%) > YMax THEN YMax = Value(I%)
  10664.       NEXT I%
  10665.  
  10666.       ' Calculate width of bars and space between them:
  10667.       BarWidth = (GRAPHRIGHT - GRAPHLEFT) / N%
  10668.       BarSpace = .2 * BarWidth
  10669.       BarWidth = BarWidth - BarSpace
  10670.  
  10671.       SCREEN 2
  10672.       CLS
  10673.  
  10674.       ' Draw y-axis:
  10675.       LINE (GRAPHLEFT, GRAPHTOP)-(GRAPHLEFT, GRAPHBOTTOM), 1
  10676.  
  10677.       ' Draw main graph title:
  10678.       Start% = 44 - (LEN(RTRIM$(T.MainTitle)) / 2)
  10679.       LOCATE 2, Start%
  10680.       PRINT RTRIM$(T.MainTitle);
  10681.  
  10682.       ' Annotate y-axis:
  10683.       Start% = CINT(13 - LEN(RTRIM$(T.YTitle)) / 2)
  10684.       FOR I% = 1 TO LEN(RTRIM$(T.YTitle))
  10685.          LOCATE Start% + I% - 1, 1
  10686.          PRINT MID$(T.YTitle, I%, 1);
  10687.       NEXT I%
  10688.  
  10689.       ' Calculate scale factor so labels aren't bigger than four digits:
  10690.       IF ABS(YMax) > ABS(YMin) THEN
  10691.          Power = YMax
  10692.       ELSE
  10693.          Power = YMin
  10694.       END IF
  10695.       Power = CINT(LOG(ABS(Power) / 100) / LOG(10))
  10696.       IF Power < 0 THEN Power = 0
  10697.  
  10698.       ' Scale minimum and maximum values down:
  10699.       ScaleFactor = 10 ^ Power
  10700.       YMax = CINT(YMax / ScaleFactor)
  10701.       YMin = CINT(YMin / ScaleFactor)
  10702.  
  10703.  
  10704.       ' If power isn't zero then put scale factor on chart:
  10705.       IF Power <> 0 THEN
  10706.          LOCATE 3, 2
  10707.          PRINT "x 10^"; LTRIM$(STR$(Power))
  10708.       END IF
  10709.  
  10710.       ' Put tic mark and number for Max point on y-axis:
  10711.       LINE (GRAPHLEFT - 3, GRAPHTOP) -STEP(3, 0)
  10712.       LOCATE 4, 2
  10713.       PRINT USING "####"; YMax
  10714.  
  10715.       ' Put tic mark and number for Min point on y-axis:
  10716.       LINE (GRAPHLEFT - 3, GRAPHBOTTOM) -STEP(3, 0)
  10717.       LOCATE 22, 2
  10718.       PRINT USING "####"; YMin
  10719.  
  10720.       YMax = YMax * ScaleFactor ' Scale minimum and maximum back
  10721.       YMin = YMin * ScaleFactor ' up for charting calculations.
  10722.  
  10723.       ' Annotate x-axis:
  10724.       Start% = 44 - (LEN(RTRIM$(T.XTitle)) / 2)
  10725.       LOCATE 25, Start%
  10726.       PRINT RTRIM$(T.XTitle);
  10727.  
  10728.       ' Calculate the pixel range for the y-axis:
  10729.       YRange = YMax - YMin
  10730.  
  10731.       ' Define a diagonally striped pattern:
  10732.       Tile$ = CHR$(1)+CHR$(2)+CHR$(4)+CHR$(8)+CHR$(16)+CHR$(32)+CHR$(64)+CHR$
  10733.    (128)
  10734.  
  10735.       ' Draw a zero line if appropriate:
  10736.       IF YMin < 0 THEN
  10737.          Bottom = GRAPHBOTTOM - ((-YMin) / YRange * YLENGTH)
  10738.          LOCATE INT((Bottom - 1) / 8) + 1, 5
  10739.          PRINT "0";
  10740.       ELSE
  10741.          Bottom = GRAPHBOTTOM
  10742.       END IF
  10743.  
  10744.       ' Draw x-axis:
  10745.       LINE (GRAPHLEFT - 3, Bottom)-(GRAPHRIGHT, Bottom)
  10746.       ' Draw bars and labels:
  10747.       Start% = GRAPHLEFT + (BarSpace / 2)
  10748.       FOR I% = 1 TO N%
  10749.  
  10750.          ' Draw a bar label:
  10751.          BarMid = Start% + (BarWidth / 2)
  10752.          CharMid = INT((BarMid - 1) / 8) + 1
  10753.          LOCATE 23, CharMid - INT(LEN(RTRIM$(Label$(I%))) / 2)
  10754.          PRINT Label$(I%);
  10755.  
  10756.          ' Draw the bar and fill it with the striped pattern:
  10757.          BarHeight = (Value(I%) / YRange) * YLENGTH
  10758.          LINE (Start%, Bottom) -STEP(BarWidth, -BarHeight), , B
  10759.          PAINT (BarMid, Bottom - (BarHeight / 2)), Tile$, 1
  10760.  
  10761.          Start% = Start% + BarWidth + BarSpace
  10762.       NEXT I%
  10763.       LOCATE 1, 1
  10764.       PRINT "New graph? ";
  10765.       DrawGraph$ = UCASE$(INPUT$(1))
  10766.  
  10767.    END FUNCTION
  10768.  
  10769.    ' ======================== INPUTDATA ======================
  10770.    '     Gets input for the bar labels and their values
  10771.    ' =========================================================
  10772.  
  10773.    FUNCTION InputData% (Label$(), Value()) STATIC
  10774.  
  10775.       ' Initialize the number of data values:
  10776.       NumData% = 0
  10777.  
  10778.       ' Print data-entry instructions:
  10779.       CLS
  10780.       PRINT "Enter data for up to 5 bars:"
  10781.       PRINT "   * Enter the label and value for each bar."
  10782.       PRINT "   * Values can be negative."
  10783.       PRINT "   * Enter a blank label to stop."
  10784.       PRINT
  10785.       PRINT "After viewing the graph, press any key ";
  10786.       PRINT "to end the program."
  10787.  
  10788.       ' Accept data until blank label or 5 entries:
  10789.       Done% = FALSE
  10790.       DO
  10791.          NumData% = NumData% + 1
  10792.          PRINT
  10793.          PRINT "Bar("; LTRIM$(STR$(NumData%)); "):"
  10794.          INPUT ; "        Label? ", Label$(NumData%)
  10795.  
  10796.          ' Only input value if label isn't blank:
  10797.          IF Label$(NumData%) <> "" THEN
  10798.             LOCATE , 35
  10799.             INPUT "Value? ", Value(NumData%)
  10800.  
  10801.          ' If label is blank, decrement data counter
  10802.          ' and set Done flag equal to TRUE:
  10803.          ELSE
  10804.             NumData% = NumData% - 1
  10805.             Done% = TRUE
  10806.          END IF
  10807.       LOOP UNTIL (NumData% = 5) OR Done%
  10808.  
  10809.       ' Return the number of data values input:
  10810.       InputData% = NumData%
  10811.  
  10812.    END FUNCTION
  10813.  
  10814.    ' ====================== INPUTTITLES ======================
  10815.    '     Accepts input for the three different graph titles
  10816.    ' =========================================================
  10817.  
  10818.    SUB InputTitles (T AS TitleType) STATIC
  10819.       SCREEN 0, 0          ' Set text screen.
  10820.       DO                   ' Input titles.
  10821.          CLS
  10822.          INPUT "Enter main graph title: ", T.MainTitle
  10823.          INPUT "Enter x-axis title    : ", T.XTitle
  10824.          INPUT "Enter y-axis title    : ", T.YTitle
  10825.  
  10826.          ' Check to see if titles are OK:
  10827.          LOCATE 7, 1
  10828.          PRINT "OK (Y to continue, N to change)? ";
  10829.          LOCATE , , 1
  10830.          OK$ = UCASE$(INPUT$(1))
  10831.       LOOP UNTIL OK$ = "Y"
  10832.    END SUB
  10833.  
  10834.    Output
  10835.  
  10836.    ┌─────────────────────────────────────────────────────────────────┐
  10837.    │    New graph?                                                   │
  10838.    │                    LOW TEMPERATURE BY MONTH                     │
  10839.    │     15 ┐                                        ┌───────┐       │
  10840.    │ C      │                                        │░░░░░░░│       │
  10841.    │ e      │                                        │░░░░░░░│       │
  10842.    │ l      │                                        │░░░░░░░│       │
  10843.    │ s      │                                        │░░░░░░░│       │
  10844.    │ i      │                                        │░░░░░░░│       │
  10845.    │ u      │                                        │░░░░░░░│       │
  10846.    │ s      │                              ┌───────┐ │░░░░░░░│       │
  10847.    │        │                              │░░░░░░░│ │░░░░░░░│       │
  10848.    │ D      │                              │░░░░░░░│ │░░░░░░░│       │
  10849.    │ e    0 ┼┬───────┬─┬───────┬─┬───────┬─┴───────┴─┴───────┴─      │
  10850.    │ g      ││░░░░░░░│ │░░░░░░░│ │░░░░░░░│                           │
  10851.    │ r      ││░░░░░░░│ │░░░░░░░│ └───────┘                           │
  10852.    │ e      ││░░░░░░░│ │░░░░░░░│                                     │
  10853.    │ e      ││░░░░░░░│ │░░░░░░░│                                     │
  10854.    │ s      │└───────┘ │░░░░░░░│                                     │
  10855.    │      -9┘          └───────┘                                     │
  10856.    │          January   February    March    April     May           │
  10857.    │                              Month                              │
  10858.    └─────────────────────────────────────────────────────────────────┘
  10859.  
  10860.  5.11.2  Color in a Figure Generated Mathematically (MANDEL.BAS)
  10861.  
  10862.    This program uses BASIC graphics statements to generate a figure known as
  10863.    a "fractal." A fractal is a graphic representation of what happens to
  10864.    numbers when they are subjected to a repeated sequence of mathematical
  10865.    operations. The fractal generated by this program shows a subset of the
  10866.    class of numbers known as complex numbers; this subset is called the
  10867.    "Mandelbrot Set," named after Benoit B. Mandelbrot of the IBM Thomas J.
  10868.    Watson Research Center.
  10869.  
  10870.    Briefly, complex numbers have two parts, a real part and a so-called
  10871.    imaginary part, some multiple of the √-1. Squaring a complex number, then
  10872.    plugging the real and imaginary parts back into a second complex number,
  10873.    squaring the new complex number, and repeating the process causes some
  10874.    complex numbers to get very large fairly fast. However, others hover
  10875.    around some stable value. The stable values are in the Mandelbrot Set and
  10876.    are represented in this program by the color black. The unstable values──
  10877.    that is, the ones that are moving away from the Mandelbrot Set──are
  10878.    represented by the other colors in the palette. The smaller the color
  10879.    attribute, the more unstable the point.
  10880.  
  10881.    See A.K. Dewdney's column, "Computer Recreations," in Scientific American,
  10882.    August 1985, for more background on the Mandelbrot Set.
  10883.  
  10884.    This program also tests for the presence of an EGA card, and if one is
  10885.    present, it draws the Mandelbrot Set in screen mode 8. After drawing each
  10886.    line, the program rotates the 16 colors in the palette with a PALETTE
  10887.    USING statement. If there is no EGA card, the program draws a four-color
  10888.    (white, magenta, cyan, and black) Mandelbrot Set in screen mode 1.
  10889.  
  10890.    Statements and Functions Used
  10891.  
  10892.    This program demonstrates the use of the following graphics statements:
  10893.  
  10894.    ■ LINE
  10895.  
  10896.    ■ PALETTE USING
  10897.  
  10898.    ■ PMAP
  10899.  
  10900.    ■ PSET
  10901.  
  10902.    ■ SCREEN
  10903.  
  10904.    ■ VIEW
  10905.  
  10906.    ■ WINDOW
  10907.  
  10908.    Program Listing
  10909.  
  10910.    DEFINT A-Z           ' Default variable type is integer.
  10911.  
  10912.    DECLARE SUB ShiftPalette ()
  10913.    DECLARE SUB WindowVals (WL%, WR%, WT%, WB%)
  10914.    DECLARE SUB ScreenTest (EM%, CR%, VL%, VR%, VT%, VB%)
  10915.  
  10916.    CONST FALSE = 0, TRUE = NOT FALSE ' Boolean constants
  10917.  
  10918.    ' Set maximum number of iterations per point:
  10919.    CONST MAXLOOP = 30, MAXSIZE = 1000000
  10920.  
  10921.    DIM PaletteArray(15)
  10922.    FOR I = 0 TO 15: PaletteArray(I) = I: NEXT I
  10923.  
  10924.    ' Call WindowVals to get coordinates of window corners:
  10925.    WindowVals WLeft, WRight, WTop, WBottom
  10926.  
  10927.    ' Call ScreenTest to find out if this is an EGA machine
  10928.    ' and get coordinates of viewport corners:
  10929.    ScreenTest EgaMode, ColorRange, VLeft, VRight, VTop, VBottom
  10930.  
  10931.    ' Define viewport and corresponding window:
  10932.    VIEW (VLeft, VTop)-(VRight, VBottom), 0, ColorRange
  10933.    WINDOW (WLeft, WTop)-(WRight, WBottom)
  10934.  
  10935.    LOCATE 24, 10 : PRINT "Press any key to quit.";
  10936.  
  10937.    XLength = VRight - VLeft
  10938.    YLength = VBottom - VTop
  10939.    ColorWidth = MAXLOOP \ ColorRange
  10940.  
  10941.    ' Loop through each pixel in viewport and calculate
  10942.    ' whether or not it is in the Mandelbrot Set:
  10943.    FOR Y = 0 TO YLength       ' Loop through every line
  10944.                               ' in the viewport.
  10945.       LogicY = PMAP(Y, 3)     ' Get the pixel's view
  10946.                               ' y-coordinate.
  10947.       PSET (WLeft, LogicY)    ' Plot leftmost pixel in the line.
  10948.       OldColor = 0            ' Start with background color.
  10949.  
  10950.       FOR X = 0 TO XLength    ' Loop through every pixel
  10951.                               ' in the line.
  10952.          LogicX = PMAP(X, 2)  ' Get the pixel's view
  10953.                               ' x-coordinate.
  10954.          MandelX& = LogicX
  10955.          MandelY& = LogicY
  10956.  
  10957.  
  10958.          ' Do the calculations to see if this point
  10959.          ' is in the Mandelbrot Set:
  10960.          FOR I = 1 TO MAXLOOP
  10961.             RealNum& = MandelX& * MandelX&
  10962.             ImagNum& = MandelY& * MandelY&
  10963.             IF (RealNum& + ImagNum&) >= MAXSIZE THEN EXIT FOR
  10964.             MandelY& = (MandelX& * MandelY&) \ 250 + LogicY
  10965.             MandelX& = (RealNum& - ImagNum&) \ 500 + LogicX
  10966.          NEXT I
  10967.  
  10968.          ' Assign a color to the point:
  10969.          PColor = I \ ColorWidth
  10970.  
  10971.          ' If color has changed, draw a line from
  10972.          ' the last point referenced to the new point,
  10973.          ' using the old color:
  10974.          IF PColor <> OldColor THEN
  10975.             LINE -(LogicX, LogicY), (ColorRange - OldColor)
  10976.             OldColor = PColor
  10977.          END IF
  10978.  
  10979.          IF INKEY$ <> "" THEN END
  10980.       NEXT X
  10981.  
  10982.       ' Draw the last line segment to the right edge
  10983.       ' of the viewport:
  10984.       LINE -(LogicX, LogicY), (ColorRange - OldColor)
  10985.  
  10986.       ' If this is an EGA machine, shift the palette after
  10987.       ' drawing each line:
  10988.       IF EgaMode THEN ShiftPalette
  10989.    NEXT Y
  10990.  
  10991.    DO
  10992.       ' Continue shifting the palette
  10993.       ' until the user presses a key:
  10994.       IF EgaMode THEN ShiftPalette
  10995.    LOOP WHILE INKEY$ = ""
  10996.  
  10997.    SCREEN 0, 0             ' Restore the screen to text mode,
  10998.    WIDTH 80                ' 80 columns.
  10999.    END
  11000.  
  11001.    BadScreen:              ' Error handler that is invoked if
  11002.       EgaMode = FALSE      ' there is no EGA graphics card
  11003.       RESUME NEXT
  11004.  
  11005.    ' ====================== ShiftPalette =====================
  11006.    '    Rotates the palette by one each time it is called
  11007.    ' =========================================================
  11008.  
  11009.    SUB ShiftPalette STATIC
  11010.       SHARED PaletteArray(), ColorRange
  11011.  
  11012.       FOR I = 1 TO ColorRange
  11013.          PaletteArray(I) = (PaletteArray(I) MOD ColorRange) + 1
  11014.       NEXT I
  11015.       PALETTE USING PaletteArray(0)
  11016.  
  11017.    END SUB
  11018.  
  11019.    ' ======================= ScreenTest ======================
  11020.    '    Uses a SCREEN 8 statement as a test to see if user has
  11021.    '    EGA hardware. If this causes an error, the EM flag is
  11022.    '    set to FALSE, and the screen is set with SCREEN 1.
  11023.  
  11024.    '    Also sets values for corners of viewport (VL = left,
  11025.    '    VR = right, VT = top, VB = bottom), scaled with the
  11026.    '    correct aspect ratio so viewport is a perfect square.
  11027.    ' =========================================================
  11028.  
  11029.    SUB ScreenTest (EM, CR, VL, VR, VT, VB) STATIC
  11030.       EM = TRUE
  11031.       ON ERROR GOTO BadScreen
  11032.       SCREEN 8, 1
  11033.       ON ERROR GOTO 0
  11034.  
  11035.       IF EM THEN                   ' No error, SCREEN 8 is OK.
  11036.          VL = 110: VR = 529
  11037.          VT = 5: VB = 179
  11038.          CR = 15                   ' 16 colors (0 - 15)
  11039.  
  11040.       ELSE                         ' Error, so use SCREEN 1.
  11041.          SCREEN 1, 1
  11042.          VL = 55: VR = 264
  11043.          VT = 5: VB = 179
  11044.          CR = 3                    ' 4 colors (0 - 3)
  11045.       END IF
  11046.  
  11047.    END SUB
  11048.  
  11049.    ' ======================= WindowVals ======================
  11050.    '     Gets window corners as input from the user, or sets
  11051.    '     values for the corners if there is no input
  11052.    ' =========================================================
  11053.  
  11054.    SUB WindowVals (WL, WR, WT, WB) STATIC
  11055.       CLS
  11056.       PRINT "This program prints the graphic representation of"
  11057.       PRINT "the complete Mandelbrot Set. The default window"
  11058.       PRINT "is from (-1000,625) to (250,-625). To zoom in on"
  11059.       PRINT "part of the figure, input coordinates inside"
  11060.       PRINT "this window."
  11061.       PRINT "Press <ENTER> to see the default window or"
  11062.       PRINT "any other key to input window coordinates: ";
  11063.       LOCATE , , 1
  11064.       Resp$ = INPUT$(1)
  11065.  
  11066.       ' User didn't press ENTER, so input window corners:
  11067.       IF Resp$ <> CHR$(13) THEN
  11068.          PRINT
  11069.          INPUT "x-coordinate of upper-left corner: ", WL
  11070.          DO
  11071.             INPUT "x-coordinate of lower-right corner: ", WR
  11072.             IF WR <= WL THEN
  11073.             PRINT "Right corner must be greater than left corner."
  11074.             END IF
  11075.          LOOP WHILE WR <= WL
  11076.          INPUT "y-coordinate of upper-left corner: ", WT
  11077.          DO
  11078.             INPUT "y-coordinate of lower-right corner: ", WB
  11079.             IF WB >= WT THEN
  11080.             PRINT "Bottom corner must be less than top corner."
  11081.             END IF
  11082.          LOOP WHILE WB >= WT
  11083.  
  11084.       ' User pressed ENTER, so set default values:
  11085.       ELSE
  11086.          WL = -1000
  11087.          WR = 250
  11088.          WT = 625
  11089.          WB = -625
  11090.       END IF
  11091.    END SUB
  11092.  
  11093.    Output
  11094.  
  11095.    The following figure shows the Mandelbrot Set in screen mode 1. This is
  11096.    the output you see if you have a CGA and you choose the default window
  11097.    coordinates.
  11098.  
  11099.    ┌────────────────────────────────────┐
  11100.    │                                    │
  11101.    │     The output for this example    │
  11102.    │     can be found on page 217 of    │
  11103.    │     the printed manual.            │
  11104.    │                                    │
  11105.    └────────────────────────────────────┘
  11106.  
  11107.    The next figure shows the Mandelbrot Set with (x, y) coordinates of (-500,
  11108.    250) for the upper-left corner and (-300, 50) for the lower-right corner.
  11109.    This figure is drawn in screen mode 8, the default for an EGA or VGA.
  11110.  
  11111.    ┌────────────────────────────────────┐
  11112.    │                                    │
  11113.    │     The output for this example    │
  11114.    │     can be found on page 217 of    │
  11115.    │     the printed manual.            │
  11116.    │                                    │
  11117.    └────────────────────────────────────┘
  11118.  
  11119.  5.11.3  Pattern Editor (EDPAT.BAS)
  11120.  
  11121.    This program allows you to edit a pattern tile for use with PAINT. While
  11122.    you are editing the tile on the left side of the screen, you can check the
  11123.    appearance of the finished pattern on the right side of the screen. When
  11124.    you have finished editing the pattern tile, the program prints the integer
  11125.    arguments used by the CHR$ statement to draw each row of the tile.
  11126.  
  11127.    Statements and Functions Used
  11128.  
  11129.    This program demonstrates the use of the following graphics statements:
  11130.  
  11131.    ■ LINE
  11132.  
  11133.    ■ PAINT (with pattern)
  11134.  
  11135.    ■ VIEW
  11136.  
  11137.    Program Listing
  11138.  
  11139.    DECLARE SUB DrawPattern ()
  11140.    DECLARE SUB EditPattern ()
  11141.    DECLARE SUB Initialize ()
  11142.    DECLARE SUB ShowPattern (OK$)
  11143.  
  11144.    DIM Bit%(0 TO 7), Pattern$, Esc$, PatternSize%
  11145.  
  11146.    DO
  11147.       Initialize
  11148.       EditPattern
  11149.       ShowPattern OK$
  11150.    LOOP WHILE OK$ = "Y"
  11151.  
  11152.    END
  11153.  
  11154.    ' ======================= DRAWPATTERN ====================
  11155.    '  Draws a patterned rectangle on the right side of screen
  11156.    ' ========================================================
  11157.  
  11158.    SUB DrawPattern STATIC
  11159.    SHARED Pattern$
  11160.  
  11161.       VIEW (320, 24)-(622, 160), 0, 1  ' Set view to rectangle.
  11162.       PAINT (1, 1), Pattern$           ' Use PAINT to fill it.
  11163.       VIEW                             ' Set view to full screen.
  11164.  
  11165.    END SUB
  11166.  
  11167.    ' ======================= EDITPATTERN =====================
  11168.    '                  Edits a tile-byte pattern
  11169.    ' =========================================================
  11170.  
  11171.    SUB EditPattern STATIC
  11172.    SHARED Pattern$, Esc$, Bit%(), PatternSize%
  11173.  
  11174.       ByteNum% = 1         ' Starting position.
  11175.       BitNum% = 7
  11176.       Null$ = CHR$(0)      ' CHR$(0) is the first byte of the
  11177.                            ' two-byte string returned when a
  11178.                            ' direction key such as UP or DOWN is
  11179.                            ' pressed.
  11180.       DO
  11181.  
  11182.          ' Calculate starting location on screen of this bit:
  11183.          X% = ((7 - BitNum%) * 16) + 80
  11184.          Y% = (ByteNum% + 2) * 8
  11185.  
  11186.          ' Wait for a key press (flash cursor each 3/10 second):
  11187.          State% = 0
  11188.          RefTime = 0
  11189.          DO
  11190.  
  11191.             ' Check timer and switch cursor state if 3/10 second:
  11192.             IF ABS(TIMER - RefTime) > .3 THEN
  11193.                RefTime = TIMER
  11194.                State% = 1 - State%
  11195.  
  11196.             ' Turn the border of bit on and off:
  11197.               LINE (X%-1, Y%-1) -STEP(15, 8), State%, B
  11198.             END IF
  11199.  
  11200.             Check$ = INKEY$ ' Check for keystroke.
  11201.  
  11202.          LOOP WHILE Check$ = "" ' Loop until a key is pressed.
  11203.  
  11204.          ' Erase cursor:
  11205.          LINE (X%-1, Y%-1) -STEP(15, 8), 0, B
  11206.  
  11207.          SELECT CASE Check$ ' Respond to keystroke.
  11208.  
  11209.          CASE CHR$(27)      ' ESC key pressed:
  11210.             EXIT SUB        ' exit this subprogram.
  11211.  
  11212.    CASE CHR$(32)      ' SPACEBAR pressed:
  11213.                             ' reset state of bit.
  11214.  
  11215.             ' Invert bit in pattern string:
  11216.             CurrentByte% = ASC(MID$(Pattern$, ByteNum%, 1))
  11217.             CurrentByte% = CurrentByte% XOR Bit%(BitNum%)
  11218.             MID$ (Pattern$, ByteNum%) = CHR$(CurrentByte%)
  11219.  
  11220.             ' Redraw bit on screen:
  11221.             IF (CurrentByte% AND Bit%(BitNum%)) <> 0 THEN
  11222.                 CurrentColor% = 1
  11223.             ELSE
  11224.                 CurrentColor% = 0
  11225.             END IF
  11226.             LINE (X%+1, Y%+1) -STEP(11, 4), CurrentColor%, BF
  11227.  
  11228.          CASE CHR$(13)              ' ENTER key pressed: draw
  11229.             DrawPattern             ' pattern in box on right.
  11230.  
  11231.          CASE Null$ + CHR$(75)      ' LEFT key: move cursor left.
  11232.  
  11233.             BitNum% = BitNum% + 1
  11234.             IF BitNum% > 7 THEN BitNum% = 0
  11235.  
  11236.          CASE Null$ + CHR$(77)      ' RIGHT key: move cursor right.
  11237.  
  11238.             BitNum% = BitNum% - 1
  11239.             IF BitNum% < 0 THEN BitNum% = 7
  11240.  
  11241.          CASE Null$ + CHR$(72)      ' UP key: move cursor up.
  11242.  
  11243.             ByteNum% = ByteNum% - 1
  11244.             IF ByteNum% < 1 THEN ByteNum% = PatternSize%
  11245.  
  11246.          CASE Null$ + CHR$(80)      ' DOWN key: move cursor down.
  11247.  
  11248.             ByteNum% = ByteNum% + 1
  11249.             IF ByteNum% > PatternSize% THEN ByteNum% = 1
  11250.  
  11251.          CASE ELSE
  11252.             ' User pressed a key other than ESC, SPACEBAR,
  11253.             ' ENTER, UP, DOWN, LEFT, or RIGHT, so don't
  11254.             ' do anything.
  11255.          END SELECT
  11256.       LOOP
  11257.    END SUB
  11258.  
  11259.    ' ======================= INITIALIZE ======================
  11260.    '             Sets up starting pattern and screen
  11261.    ' =========================================================
  11262.  
  11263.    SUB Initialize STATIC
  11264.    SHARED Pattern$, Esc$, Bit%(), PatternSize%
  11265.  
  11266.       Esc$ = CHR$(27)              ' ESC character is ASCII 27.
  11267.  
  11268.       ' Set up an array holding bits in positions 0 to 7:
  11269.       FOR I% = 0 TO 7
  11270.          Bit%(I%) = 2 ^ I%
  11271.       NEXT I%
  11272.  
  11273.       CLS
  11274.  
  11275.       ' Input the pattern size (in number of bytes):
  11276.       LOCATE 5, 5
  11277.       PRINT "Enter pattern size (1-16 rows):";
  11278.       DO
  11279.          LOCATE 5, 38
  11280.          PRINT "  ";
  11281.          LOCATE 5, 38
  11282.          INPUT "", PatternSize%
  11283.       LOOP WHILE PatternSize% < 1 OR PatternSize% > 16
  11284.  
  11285.       ' Set initial pattern to all bits set:
  11286.       Pattern$ = STRING$(PatternSize%, 255)
  11287.  
  11288.       SCREEN 2             ' 640 x 200 monochrome graphics mode
  11289.  
  11290.       ' Draw dividing lines:
  11291.       LINE (0, 10)-(635, 10), 1
  11292.       LINE (300, 0)-(300, 199)
  11293.       LINE (302, 0)-(302, 199)
  11294.  
  11295.       ' Print titles:
  11296.       LOCATE 1, 13: PRINT "Pattern Bytes"
  11297.       LOCATE 1, 53: PRINT "Pattern View"
  11298.  
  11299.    ' Draw editing screen for pattern:
  11300.       FOR I% = 1 TO PatternSize%
  11301.  
  11302.          ' Print label on left of each line:
  11303.          LOCATE I% + 3, 8
  11304.          PRINT USING "##:"; I%
  11305.  
  11306.          ' Draw "bit" boxes:
  11307.          X% = 80
  11308.          Y% = (I% + 2) * 8
  11309.          FOR J% = 1 TO 8
  11310.             LINE (X%, Y%) -STEP(13, 6), 1, BF
  11311.             X% = X% + 16
  11312.          NEXT J%
  11313.       NEXT I%
  11314.  
  11315.       DrawPattern          ' Draw   "Pattern View" box.
  11316.  
  11317.       LOCATE 21, 1
  11318.       PRINT "DIRECTION keys........Move cursor"
  11319.       PRINT "SPACEBAR............Changes point"
  11320.       PRINT "ENTER............Displays pattern"
  11321.       PRINT "ESC.........................Quits";
  11322.  
  11323.    END SUB
  11324.  
  11325.    ' ======================== SHOWPATTERN ====================
  11326.    '   Prints the CHR$ values used by PAINT to make pattern
  11327.    ' =========================================================
  11328.  
  11329.    SUB ShowPattern (OK$) STATIC
  11330.    SHARED Pattern$, PatternSize%
  11331.  
  11332.       ' Return screen to 80-column text mode:
  11333.       SCREEN 0, 0
  11334.       WIDTH 80
  11335.  
  11336.       PRINT "The following characters make up your pattern:"
  11337.       PRINT
  11338.  
  11339.       ' Print out the value for each pattern byte:
  11340.       FOR I% = 1 TO PatternSize%
  11341.          PatternByte% = ASC(MID$(Pattern$, I%, 1))
  11342.          PRINT "CHR$("; LTRIM$(STR$(PatternByte%)); ")"
  11343.       NEXT I%
  11344.       PRINT
  11345.       LOCATE , , 1
  11346.       PRINT "New pattern? ";
  11347.       OK$ = UCASE$(INPUT$(1))
  11348.    END SUB
  11349.  
  11350.    Output
  11351.  
  11352.    This is a sample pattern generated by the pattern editor.
  11353.  
  11354.    ┌────────────────────────────────────┐
  11355.    │                                    │
  11356.    │     The output for this example    │
  11357.    │     can be found on page 223 of    │
  11358.    │     the printed manual.            │
  11359.    │                                    │
  11360.    └────────────────────────────────────┘
  11361.  
  11362.  
  11363.  
  11364.  ────────────────────────────────────────────────────────────────────────────
  11365.  Chapter 6  Error and Event Trapping
  11366.  
  11367.    This chapter shows how to trap errors and events that occur while a
  11368.    program is running. With error trapping, you can protect your program from
  11369.    such user errors as entering a string when a numeric value is expected or
  11370.    trying to open a file in a nonexistent directory. With event trapping,
  11371.    your program can detect and respond to real-time events such as keystrokes
  11372.    or data arriving at a COM port.
  11373.  
  11374.    When you have completed this chapter, you will know how to perform these
  11375.    tasks:
  11376.  
  11377.    ■ Activate error trapping or event trapping
  11378.  
  11379.    ■ Write a routine to process trapped errors or events
  11380.  
  11381.    ■ Return control from an error-handling routine or an event-handling
  11382.      routine
  11383.  
  11384.    ■ Write a program that traps any keystroke or combination of keystrokes
  11385.  
  11386.    ■ Trap errors or events within SUB or FUNCTION procedures
  11387.  
  11388.    ■ Trap errors or events in programs composed of more than one module
  11389.  
  11390.  
  11391.  6.1  Error Trapping
  11392.  
  11393.    Error trapping lets your program intercept run-time errors before they
  11394.    force the program to halt. Without error trapping, errors during program
  11395.    execution (such as trying to open a nonexistent data file) cause BASIC to
  11396.    display the appropriate error message, then stop the program. If someone
  11397.    is running the stand-alone version of your program, they will have to
  11398.    restart the program, losing data entered or calculations performed before
  11399.    the error occurred.
  11400.  
  11401.    When error trapping is active, the trapped error makes the program branch
  11402.    to a user-written "error-handling routine," which corrects the error. If
  11403.    you can anticipate errors that might occur when someone else uses your
  11404.    program, error trapping will let you handle those errors in a
  11405.    "user-friendly" way.
  11406.  
  11407.    Sections 6.1.1 and 6.1.2 below show how to activate error trapping, how
  11408.    to write a routine to handle errors when they are trapped, and how to
  11409.    return control from the error-handling routine after it has dealt with the
  11410.    error.
  11411.  
  11412.  6.1.1  Activating Error Trapping
  11413.  
  11414.    You activate error trapping with the statement ON ERROR GOTO line, where
  11415.    line is a line number or line label identifying the first line of an
  11416.    error-handling routine. Once BASIC has encountered an ON ERROR GOTO line
  11417.    statement, any run-time error within the module containing that statement
  11418.    causes a branch to the specified line. (If the number or label does not
  11419.    exist within the module, a run-time error message reading Label not
  11420.    defined appears.)
  11421.  
  11422.    An ON ERROR GOTO statement must be executed before error trapping takes
  11423.    effect. Therefore, you must position the ON ERROR GOTO statement so that
  11424.    program execution reaches it before it is needed. This statement would
  11425.    usually be one of the first executable statements in the main module or a
  11426.    procedure.
  11427.  
  11428.    You cannot use an ON ERROR GOTO 0 statement to branch to an error handler,
  11429.    because this statement has a special meaning in error trapping. The ON
  11430.    ERROR GOTO 0 statement has two effects, depending on where it appears. If
  11431.    it appears outside an error-handling routine, it turns off error trapping.
  11432.    If it appears inside an error-handling routine (as it does in the Handler
  11433.    routine in the next example), it causes BASIC to print its standard
  11434.    message for the given error and stops the program.
  11435.  
  11436.    Therefore, even if your program has a line with line-number 0, an ON ERROR
  11437.    GOTO 0 statement tells BASIC either to turn off error detection or to
  11438.    terminate execution.
  11439.  
  11440.  6.1.2  Writing an Error-Handling Routine
  11441.  
  11442.    An error-handling routine consists of the following three parts:
  11443.  
  11444.    1. The line label or line number that is specified in the statement ON
  11445.       ERROR GOTO line, which is the first statement the program branches to
  11446.       after an error
  11447.  
  11448.    2. The body of the routine, which determines the error that caused the
  11449.       branch and takes appropriate action for each anticipated error
  11450.  
  11451.    3. At least one RESUME or RESUME NEXT statement to return control from the
  11452.       routine
  11453.  
  11454.    An error handler must be placed where it cannot be executed during the
  11455.    normal flow of program execution. For example, an error-handling routine
  11456.    in the program's main module might be placed after an END statement.
  11457.    Otherwise, a GOTO statement might be needed to skip over it during normal
  11458.    execution.
  11459.  
  11460.    6.1.2.1  Using ERR to Identify Errors
  11461.  
  11462.    Once the program has branched to an error-handling routine, it must
  11463.    determine which error caused the branch. To identify the culprit, use the
  11464.    ERR function. This function returns a numeric code for the program's most
  11465.    recent run-time error. (See Table I.1, "Run-Time Error Codes," for a
  11466.    complete list of the error codes associated with run-time errors.)
  11467.  
  11468.    ──────────────────────────────────────────────────────────────────────────
  11469.    NOTE
  11470.      Errors cannot be trapped within an error-handling routine. If an error
  11471.      occurs while the error-handling routine is processing another error, the
  11472.      program displays the message for the new error and then terminates.
  11473.      Event handling is also suspended, but resumes when QuickBASIC returns
  11474.      from the error handler. The first event that occurred after event
  11475.      handling was suspended is saved.
  11476.    ──────────────────────────────────────────────────────────────────────────
  11477.  
  11478.    Example
  11479.  
  11480.    The following program includes the error-handling routine Handler,
  11481.    designed to deal specifically with three different error situations. The
  11482.    ERR function, used in a SELECT CASE statement, allows this routine to take
  11483.    actions appropriate for each error.
  11484.  
  11485.    DATA BASIC, Pascal, FORTRAN, C, Modula, Forth
  11486.    DATA LISP, Ada, COBOL
  11487.  
  11488.    CONST FALSE = 0, TRUE = NOT FALSE
  11489.  
  11490.    EndOfData = FALSE                     ' Set end of data flag.
  11491.  
  11492.    ON ERROR GOTO Handler                 ' Activate error trapping.
  11493.  
  11494.    OPEN "LPT1:" FOR OUTPUT AS #1 ' Open the printer for output.
  11495.  
  11496.    DO
  11497.       ' Continue reading items from the DATA statements above,
  11498.       ' then printing them on the line printer, until there is
  11499.       ' an "Out of DATA" error message signifying no more data:
  11500.       READ Buffer$
  11501.       IF NOT EndOfData THEN
  11502.          PRINT #1, Buffer$
  11503.       ELSE
  11504.          EXIT DO
  11505.       END IF
  11506.    LOOP
  11507.  
  11508.    CLOSE #1
  11509.    END
  11510.  
  11511.    Handler:                        ' Error-handling routine
  11512.  
  11513.       ' Use ERR to determine which error
  11514.       ' caused the branch to "Handler":
  11515.       SELECT CASE ERR
  11516.          CASE 4
  11517.  
  11518.             ' 4 is the code for "Out of DATA" in DATA
  11519.             ' statements:
  11520.             EndOfData = TRUE
  11521.             RESUME NEXT
  11522.          CASE 25
  11523.  
  11524.             ' 25 is the code for "Device fault" error,
  11525.             ' which can be caused by trying to output
  11526.             ' to the printer when it's not on:
  11527.             PRINT "Turn printer on, then";
  11528.             PRINT "press any key to continue"
  11529.             Pause$ = INPUT$(1)
  11530.             RESUME
  11531.          CASE 27
  11532.  
  11533.             ' 27 is the code for "Out of paper":
  11534.             PRINT "Printer is out of paper. Insert"
  11535.             PRINT "paper, then press any key to continue."
  11536.             Pause$ = INPUT$(1)
  11537.  
  11538.             ' Start reading data from the beginning of first
  11539.             ' DATA statement after the paper is inserted:
  11540.             RESTORE
  11541.             RESUME
  11542.          CASE ELSE
  11543.  
  11544.             ' An unanticipated error has occurred; display the
  11545.             ' message for that error and stop the program:
  11546.             ON ERROR GOTO 0
  11547.       END SELECT
  11548.  
  11549.    6.1.2.2  Returning from an Error-Handling Routine
  11550.  
  11551.    The RESUME statement returns control from an error-handling routine. The
  11552.    preceding example used the following two variations of RESUME to return
  11553.    from Handler:
  11554.  
  11555. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  11556.    Statement                Action
  11557.    ──────────────────────────────────────────────────────────────────────────
  11558.    RESUME                   Causes the program to branch back to the exact
  11559.                             statement that caused the error.
  11560.  
  11561.                             If the program had to go to another module to
  11562.                             find an active error handler, control returns to
  11563.                             the last statement executed in that module.
  11564.  
  11565.                             The preceding program used RESUME to return to
  11566.                             the PRINT statement that attempted to send output
  11567.                             to the printer, giving it another chance to print
  11568.                             the value in Buffer$ after the printer has
  11569.                             (presumably) been turned on.
  11570.  
  11571.    RESUME NEXT              Causes the program to branch back to the
  11572.                             statement following the one that caused the
  11573.    Statement                Action
  11574.    ──────────────────────────────────────────────────────────────────────────
  11575.                            statement following the one that caused the
  11576.                             error.If the program had to go to another module
  11577.                             to find an active error handler, control returns
  11578.                             to the statement following the last statement
  11579.                             executed in that module.
  11580.  
  11581.                             The preceding program used the statement RESUME
  11582.                             NEXT when recovering from the Out of DATA error.
  11583.                             In this case, a simple RESUME would have sent the
  11584.                             program into an endless loop, since each time
  11585.                             control returned to the READ statement in the
  11586.                             main program, another Out of DATA error would
  11587.                             result, invoking the error routine over and over
  11588.                             again.
  11589.  
  11590.    ──────────────────────────────────────────────────────────────────────────
  11591.  
  11592.  
  11593.    Figure 6.1 outlines the flow of a program's control during error handling
  11594.    with RESUME.
  11595.  
  11596.  
  11597.    ┌──────────────────────────────────────────────────────────────────┐
  11598.    │          ┌─────────┐                                             │
  11599.    │          │  Start  │                                             │
  11600.    │          └────┬────┘                                             │
  11601.    │               │                                                  │
  11602.    │               │                                                  │
  11603.    │    ┌─────────────────────┐        ┌──────────────────────┐      │
  11604.    │ ┌─│ Statement with error ├───────│    Error handler     │      │
  11605.    │ │  └──────────┬───────────┘        └───────────┬──────────┘      │
  11606.    │ │             │                                │                 │
  11607.    │ │            ┌┼┐                   ┌─────────────────────┐      │
  11608.    │ └────────────┘│└───────────────────┤        RESUME        │      │
  11609.    │               │                    └──────────────────────┘      │
  11610.    │               │                                                  │
  11611.    │          ┌────────┐                                             │
  11612.    │          │   End   │                                             │
  11613.    │          └─────────┘                                             │
  11614.    └──────────────────────────────────────────────────────────────────┘
  11615.  
  11616.    Figure 6.1  Program Flow of Control with RESUME
  11617.  
  11618.    Contrast the preceding figure with Figure 6.2, which shows what happens
  11619.    in a program using RESUME NEXT.
  11620.  
  11621.  
  11622.    ┌──────────────────────────────────────────────────────────────────┐
  11623.    │        ┌─────────┐                                               │
  11624.    │        │  Start  │                                               │
  11625.    │        └────┬────┘                                               │
  11626.    │             │                                                    │
  11627.    │  ┌─────────────────────┐        ┌──────────────────────┐        │
  11628.    │  │ Statement with error ├───────│    Error handler     │        │
  11629.    │  └──────────────────────┘        └───────────┬──────────┘        │
  11630.    │                                              │                   │
  11631.    │  ┌──────────────────────┐        ┌─────────────────────┐        │
  11632.    │  │ Statement following  │───────┤        RESUME        │        │
  11633.    │  │the one with the error│        └──────────────────────┘        │
  11634.    │  └──────────┬───────────┘                                        │
  11635.    │             │                                                    │
  11636.    │        ┌────────┐                                               │
  11637.    │        │   End   │                                               │
  11638.    │        └─────────┘                                               │
  11639.    └──────────────────────────────────────────────────────────────────┘
  11640.  
  11641.    Figure 6.2  Program Flow of Control with RESUME NEXT
  11642.  
  11643.    Another variant of RESUME is RESUME line, where line is a line number or
  11644.    line label outside any SUB...END SUB, FUNCTION...END FUNCTION, or DEF
  11645.    FN...END DEF block. Because line must be outside these blocks, a RESUME
  11646.    line statement can produce unexpected effects if it appears in an
  11647.    error-handling routine inside a SUB or FUNCTION procedure or a DEF FN
  11648.    function. It should generally be avoided in favor of RESUME or RESUME
  11649.    NEXT.
  11650.  
  11651.  
  11652.  6.2  Event Trapping
  11653.  
  11654.    Section 6.2.1 below compares two methods your BASIC programs can use to
  11655.    detect events: polling and trapping. Sections 6.2.2-6.2.4 then discuss
  11656.    the different events BASIC can trap, how to set and activate a trap, and
  11657.    how to suspend or deactivate the trap. Sections 6.2.5-6.2.7 provide more
  11658.    detailed information on trapping keystrokes and music events.
  11659.  
  11660.  6.2.1  Detecting Events by Polling
  11661.  
  11662.    One way to detect an event and reroute program control to the appropriate
  11663.    routine is to use "event polling." In polling, your program stops whatever
  11664.    it is currently doing and explicitly checks for an event. For example, the
  11665.    following loop keeps checking the keyboard until the user presses either
  11666.    the Q or N keys:
  11667.  
  11668.    DO
  11669.       Test$ = UCASE$(INKEY$)
  11670.    LOOP UNTIL Test$ = "N" OR Test$ = "Q"
  11671.  
  11672.    Polling works well when you know ahead of time exactly where in the flow
  11673.    of the program you want to check for an event.
  11674.  
  11675.  6.2.2  Detecting Events by Trapping
  11676.  
  11677.    But suppose you don't want your program to pause, or you would like it to
  11678.    check between every statement (that is, check continuously). In these
  11679.    cases, polling is unwieldy or impossible, and trapping becomes the better
  11680.    alternative.
  11681.  
  11682.    Example
  11683.  
  11684.    The following example shows how to use event trapping:
  11685.  
  11686.    ' Alert the program that it should branch to "KeySub"
  11687.    ' whenever the user presses the F1 function key:
  11688.    ON KEY(1) GOSUB KeySub
  11689.  
  11690.    ' Turn on trapping for the F1 key. BASIC now checks in the
  11691.    ' background for this event until the end of the program,
  11692.    ' or until trapping is disabled with KEY(1) OFF
  11693.    ' or suspended with KEY(1) STOP:
  11694.    KEY(1) ON
  11695.    OPEN "Data" FOR INPUT AS #1
  11696.    OPEN "Data.Out" FOR OUTPUT AS #2
  11697.  
  11698.    DO UNTIL EOF(1)
  11699.       LINE INPUT #1, LineBuffer$
  11700.       PRINT #2, LineBuffer$
  11701.    LOOP
  11702.  
  11703.    KeySub:         ' When the user presses F1, the program
  11704.       .            ' branches to this procedure.
  11705.       .
  11706.       .
  11707.    RETURN
  11708.  
  11709.  6.2.3  Specifying the Event to Trap and Activating Event Trapping
  11710.  
  11711.    As you can see from the preceding example, three steps are necessary for
  11712.    event trapping:
  11713.  
  11714.    1. Define a target subroutine that is known as an "event-handling
  11715.       subroutine."
  11716.  
  11717.    2. Tell the program to branch to the event-handling subroutine when the
  11718.       event takes place with an ON event GOSUB statement.
  11719.  
  11720.    3. Activate trapping of that event with an ON event GOSUB statement.
  11721.  
  11722.    Your program cannot trap a given event until it encounters both an event
  11723.    ON and an ON event GOSUB statement.
  11724.  
  11725.    An event-handling routine is an ordinary BASIC GOSUB routine: control
  11726.    passes to the first line of the routine whenever the event is detected and
  11727.    returns to the main level of the module containing the routine with a
  11728.    RETURN statement.
  11729.  
  11730.    Note the following important differences between the syntax of error
  11731.    trapping and the syntax of event trapping:
  11732.  
  11733.    Error Trapping                       Event Trapping
  11734.    ──────────────────────────────────────────────────────────────────────────
  11735.    Activated with the statement ON      Activated with an event ON statement;
  11736.    ERROR GOTO, which also specifies     a separate statement, ON event GOSUB,
  11737.    the first line of the error-         specifies the first line of the
  11738.    handling routine                     event-handling subroutine
  11739.  
  11740.    Returns control from the error       Returns control from the event
  11741.    routine with one or more RESUME,     subroutine with one or more RETURN
  11742.    RESUME NEXT, or RESUME line          statements
  11743.    statements
  11744.    ──────────────────────────────────────────────────────────────────────────
  11745.  
  11746.  6.2.4  Events That BASIC Can Trap
  11747.  
  11748.    You can trap the following events within a BASIC program:
  11749.  
  11750.    BASIC Statement          Event Trapped
  11751.    ──────────────────────────────────────────────────────────────────────────
  11752.    COM(portnumber)          Data from one of the serial ports (1 or 2)
  11753.                             appearing in the communications buffer (the
  11754.                             intermediate storage area for data sent to or
  11755.                             received from the serial port)
  11756.  
  11757.    KEY(keynumber)           The user pressing the given key
  11758.  
  11759.    PEN                      The user activating the light pen
  11760.  
  11761.    PLAY(queuelimit)         The number of notes remaining to be played in the
  11762.                             background dropping below queuelimit
  11763.  
  11764.    STRIG(triggernumber)     The user squeezing the trigger of the joystick
  11765.  
  11766.    TIMER(interval)          The passage of interval seconds
  11767.    ──────────────────────────────────────────────────────────────────────────
  11768.  
  11769.  6.2.5  Suspending or Disabling Event Trapping
  11770.  
  11771.    You can turn off detection and trapping of any event with the event OFF
  11772.    statement. Events occurring after an event OFF statement has been executed
  11773.    are ignored. If you want to suspend trapping a given event but continue
  11774.    detecting it, use the event STOP statement.
  11775.  
  11776.    After event STOP, if the event occurs, there is no branch to the
  11777.    event-handling routine. However, your program remembers that the event
  11778.    occurred, and as soon as trapping is turned back on with event ON,
  11779.    branching to the event routine occurs immediately.
  11780.  
  11781.    Event-handling routines execute an implicit event STOP statement for a
  11782.    given event whenever program control is in the routine; this is followed
  11783.    by an implicit event ON for that event when program control returns from
  11784.    the routine. For example, if a key-handling routine is processing a
  11785.    keystroke, trapping the same key is suspended until the previous keystroke
  11786.    is completely processed by the routine. If the user presses the same key
  11787.    during this time, this new keystroke is remembered and trapped after
  11788.    control returns from the key-handling routine.
  11789.  
  11790.    Example
  11791.  
  11792.    An event trap interrupts whatever is happening in the program at the
  11793.    moment the event occurs. Therefore, if you have a block of statements that
  11794.    you do not want interrupted, precede them with event STOP and follow them
  11795.    with event ON, as in this example:
  11796.  
  11797.    ' Once every minute (60 seconds),
  11798.    ' branch to the ShowTime subroutine:
  11799.    ON TIMER(60) GOSUB ShowTime
  11800.  
  11801.    ' Activate trapping of the 60-second event:
  11802.    TIMER ON
  11803.    .
  11804.    .
  11805.    .
  11806.    TIMER STOP      ' Suspend trapping.
  11807.    .       ' A sequence of lines you don't want interrupted,
  11808.    .       ' even if 60 or more seconds elapse
  11809.    .
  11810.  
  11811.    TIMER ON        ' Reactivate trapping.
  11812.    .
  11813.    .
  11814.    .
  11815.    END
  11816.  
  11817.    ShowTime:
  11818.  
  11819.       ' Get the current row and column position of the cursor,
  11820.       ' and store them in the variables Row and Column:
  11821.       Row    = CSRLIN
  11822.       Column = POS(0)
  11823.  
  11824.       ' Go to the 24th row, 20th column, and print the time:
  11825.       LOCATE 24, 20
  11826.       PRINT TIME$
  11827.  
  11828.       ' Restore the cursor to its former position
  11829.       ' and return to the main program:
  11830.       LOCATE Row, Column
  11831.    RETURN
  11832.  
  11833.  6.2.6  Trapping Keystrokes
  11834.  
  11835.    To detect a keystroke and route program control to a key-press routine,
  11836.    you need both of the following statements in your program:
  11837.  
  11838.    ON KEY(keynumber) GOSUB line
  11839.    KEY(keynumber) ON
  11840.  
  11841.    Here, the keynumber value corresponds to the following keys:
  11842.  
  11843.    Value                    Key
  11844.    ──────────────────────────────────────────────────────────────────────────
  11845.    1-10                     Function keys F1-F10 (sometimes called "soft
  11846.                             keys")
  11847.  
  11848.    11                       The UP direction key
  11849.  
  11850.    12                       The LEFT direction key
  11851.  
  11852.    13                       The RIGHT direction key
  11853.  
  11854.    14                       The DOWN direction key
  11855.  
  11856.    15-25                    User-defined keys (see Sections 6.2.6.1-6.2.6.2)
  11857.  
  11858.    30                       The F11 function key (101-key keyboard only)
  11859.  
  11860.    31                       The F12 function key (101-key keyboard only)
  11861.    ──────────────────────────────────────────────────────────────────────────
  11862.  
  11863.    Examples
  11864.  
  11865.    The following two lines cause the program to branch to the KeySub routine
  11866.    each time the F2 function key is pressed:
  11867.  
  11868.    ON KEY(2) GOSUB KeySub
  11869.    KEY(2) ON
  11870.    .
  11871.    .
  11872.    .
  11873.  
  11874.    The following four lines cause the program to branch to the DownKey
  11875.    routine when the DOWN direction key is pressed and to the UpKey routine
  11876.    when the UP direction key is pressed:
  11877.  
  11878.    ON KEY(11) GOSUB UpKey
  11879.    ON KEY(14) GOSUB DownKey
  11880.    KEY(11) ON
  11881.    KEY(14) ON
  11882.    .
  11883.    .
  11884.    .
  11885.  
  11886.    6.2.6.1  Trapping User-Defined Keys
  11887.  
  11888.    In addition to providing the preassigned key numbers 1-14 (plus 30 and 31
  11889.    with the 101-key keyboard), BASIC allows you to assign the numbers 15-25
  11890.    to any of the remaining keys on the keyboard. To define your own key to
  11891.    trap, use these three statements:
  11892.  
  11893.    KEY keynumber, CHR$(0) + CHR$(scancode)
  11894.    ON KEY(keynumber) GOSUB line
  11895.    KEY(keynumber) ON
  11896.  
  11897.    Here, keynumber is a value from 15 to 25, and scancode is the scan code
  11898.    for that key. (See the first column of the "Keyboard Scan Codes" table in
  11899.    Appendix D for these codes.) For example, the following lines cause the
  11900.    program to branch to the TKey routine each time the user presses T:
  11901.  
  11902.    ' Define key 15 (the scan code for "t" is decimal 20):
  11903.    KEY 15, CHR$(0) + CHR$(20)
  11904.  
  11905.    ' Define the trap (where to go when "t" is pressed):
  11906.    ON KEY(15) GOSUB TKey
  11907.  
  11908.    KEY(15) ON                 ' Turn on detection of key 15.
  11909.  
  11910.    PRINT "Press q to end."
  11911.  
  11912.    DO                         ' Idle loop: wait for user to
  11913.    LOOP UNTIL INKEY$ = "q"    ' press "q".
  11914.  
  11915.    END
  11916.  
  11917.    TKey:                      ' Key-handling subroutine
  11918.       PRINT "Pressed t."
  11919.    RETURN
  11920.  
  11921.    6.2.6.2  Trapping User-Defined Shifted Keys
  11922.  
  11923.    You can also set a trap for "shifted" keys. A key is said to be shifted
  11924.    when you press it simultaneously with one or more of the special keys
  11925.    SHIFT, CTRL, or ALTor if you press it after toggling on the keys NUM LOCK
  11926.    or CAPS LOCK.
  11927.  
  11928.    This is how to trap the following key combinations:
  11929.  
  11930.    KEY keynumber, CHR$(keyboardflag) + CHR$(scancode)
  11931.    ON KEY(keynumber) GOSUB line
  11932.    KEY(keynumber) ON
  11933.  
  11934.    Here, keynumber is a value from 15 to 25; scancode is the scan code for
  11935.    the primary key; and keyboardflag is the sum of the individual codes for
  11936.    the special keys pressed, as shown in the following list:
  11937.  
  11938.    Key                                  Code for keyboardflag
  11939.    ──────────────────────────────────────────────────────────────────────────
  11940.    SHIFT                                1, 2, or 3
  11941.                                         Key trapping assumes the left and
  11942.                                         right shift keys are the same, so you
  11943.                                         can trap the SHIFT key with 1 (left),
  11944.                                         2 (right), or 3 (left + right).
  11945.  
  11946.    CTRL                                 4
  11947.  
  11948.    ALT                                  8
  11949.  
  11950.    NUM LOCK                             32
  11951.  
  11952.    CAPS LOCK                            64
  11953.  
  11954.    Any extended key on the 101-key      128
  11955.    keyboard (in other words, a key
  11956.    such as LEFT or DELETE that is not
  11957.    on the numeric keypad)
  11958.    ──────────────────────────────────────────────────────────────────────────
  11959.  
  11960.    For example, the following statements turn on trapping of CTRL+S. Note
  11961.    these statements are designed to trap both the CTRL+S (lowercase) and
  11962.    CTRL+SHIFT+S (uppercase) key combinations. To trap the uppercase S, your
  11963.    program must recognize capital letters produced by holding down the SHIFT
  11964.    key, as well as those produced when the CAPS LOCK key is active, as shown
  11965.    here:
  11966.  
  11967.    ' 31 = scan code for S key
  11968.    '  4 = code for CTRL key
  11969.    KEY 15, CHR$(4) + CHR$(31)     ' Trap CTRL+S.
  11970.  
  11971.    '  5 = code for CTRL key + code for SHIFT key
  11972.    KEY 16, CHR$(5) + CHR$(31)     ' Trap CTRL+SHIFT+S.
  11973.  
  11974.    ' 68 = code for CTRL key + code for CAPSLOCK
  11975.    KEY 17, CHR$(68) + CHR$(31)    ' Trap CTRL+CAPSLOCK+S.
  11976.  
  11977.    ON KEY (15) GOSUB CtrlSTrap    ' Tell program where to
  11978.    ON KEY (16) GOSUB CtrlSTrap    ' branch (note: same
  11979.    ON KEY (17) GOSUB CtrlSTrap    ' subroutine for each key).
  11980.  
  11981.    KEY (15) ON                    ' Activate key detection for
  11982.    KEY (16) ON                    ' all three combinations.
  11983.    KEY (17) ON
  11984.    .
  11985.    .
  11986.    .
  11987.  
  11988.    The following statements turn on trapping of CTRL+ALT+DEL:
  11989.  
  11990.    ' 12 = 4 + 8 = (code for CTRL key) + (code for ALT key)
  11991.    ' 83 = scan code for DEL key
  11992.    KEY 20, CHR$(12) + CHR$(83)
  11993.    ON KEY(20) GOSUB KeyHandler
  11994.    KEY(20) ON
  11995.    .
  11996.    .
  11997.    .
  11998.  
  11999.    Note in the preceding example that the BASIC event trap overrides the
  12000.    normal effect of CTRL+ALT+DEL (system reset). Using this trap in your
  12001.    program is a handy way to prevent the user from accidentally rebooting
  12002.    while a program is running.
  12003.  
  12004.    If you use a 101-key keyboard, you can trap any of the keys on the
  12005.    dedicated keypad by assigning the string
  12006.  
  12007.    CHR$(128) + CHR$(scancode)
  12008.  
  12009.    to any of the keynumber values from 15 to 25.
  12010.  
  12011.    The next example shows how to trap the LEFT direction keys on both the
  12012.    dedicated cursor keypad and the numeric keypad.
  12013.  
  12014.    ' 128 = keyboard flag for keys on the
  12015.    '       dedicated cursor keypad
  12016.    '  75 = scan code for LEFT arrow key
  12017.  
  12018.    KEY 15, CHR$(128) + CHR$(75)    ' Trap LEFT key on
  12019.    ON KEY(15) GOSUB CursorPad      ' the dedicated
  12020.    KEY(15) ON                      ' cursor keypad.
  12021.  
  12022.    ON KEY(12) GOSUB NumericPad     ' Trap LEFT key on
  12023.    KEY(12) ON                      ' the numeric keypad.
  12024.  
  12025.    DO: LOOP UNTIL INKEY$ = "q"     ' Start idle loop.
  12026.    END
  12027.  
  12028.    CursorPad:
  12029.       PRINT "Pressed LEFT key on cursor keypad."
  12030.    RETURN
  12031.  
  12032.    NumericPad:
  12033.       PRINT "Pressed LEFT key on numeric keypad."
  12034.    RETURN
  12035.  
  12036.    ──────────────────────────────────────────────────────────────────────────
  12037.    IMPORTANT
  12038.      For compatibility, QuickBASIC adopts many conventions of BASICA. One of
  12039.      these has to do with the way FUNCTION keys are trapped.
  12040.      If you initiate FUNCTION key trapping with an ON KEY (n) GOSUB
  12041.      statement, both BASICA and QuickBASIC trap Fn regardless of whether a
  12042.      shift key (CTRL, ALT, SHIFT) is also pressed. This means that
  12043.      user-defined traps for shifted versions of that FUNCTION key are
  12044.      ignored.
  12045.      Therefore, if you wish to trap a FUNCTION key in both its shifted and
  12046.      unshifted states, you should create a user definition for each state.
  12047.      Keys that are only used unshifted can continue to use the ON KEY (n)
  12048.      GOSUB statement.
  12049.    ──────────────────────────────────────────────────────────────────────────
  12050.  
  12051.  6.2.7  Trapping Music Events
  12052.  
  12053.    When you use the PLAY statement to play music, you can choose whether the
  12054.    music plays in the foreground or in the background. If you choose
  12055.    foreground music (which is the default) nothing else can happen until the
  12056.    music finishes playing. However, if you use the MB (Music Background)
  12057.    option in a PLAY music string, the tune plays in the background while
  12058.    subsequent statements in your program continue executing.
  12059.  
  12060.    The PLAY statement plays music in the background by feeding up to 32 notes
  12061.    at a time into a buffer, then playing the notes in the buffer while the
  12062.    program does other things. A "music trap" works by checking the number of
  12063.    notes currently left to be played in the buffer. As soon as this number
  12064.    drops below the limit you set in the trap, the program branches to the
  12065.    first line of the specified routine.
  12066.  
  12067.    To set a music trap in your program, you need the following statements:
  12068.  
  12069.    ON PLAY(limit) GOSUB line
  12070.    PLAY ON
  12071.    PLAY "MB"
  12072.    .
  12073.    .
  12074.    .
  12075.    PLAY musicstring
  12076.    [[PLAY musicstring]]
  12077.    .
  12078.    .
  12079.    .
  12080.  
  12081.    Here, limit is a number between 1 and 32. For example, this fragment
  12082.    causes the program to branch to the MusicTrap subroutine whenever the
  12083.    number of notes remaining to be played in the music buffer goes from eight
  12084.    to seven:
  12085.  
  12086.    ON PLAY(8) GOSUB MusicTrap
  12087.    PLAY ON
  12088.    .
  12089.    .
  12090.    .
  12091.    PLAY "MB"       ' Play subsequent notes in the background.
  12092.    PLAY "o1 A# B# C-"
  12093.    .
  12094.    .
  12095.    .
  12096.    MusicTrap:
  12097.       ' Music-trap subroutine
  12098.       .
  12099.       .
  12100.       .
  12101.    RETURN
  12102.  
  12103.    ──────────────────────────────────────────────────────────────────────────
  12104.    IMPORTANT
  12105.      A music trap is triggered only when the number of notes goes from limit
  12106.      to limit-1. For example, if the music buffer in the preceding example
  12107.      never contained more than seven notes, the trap would never occur. In
  12108.      the example, the trap happens only when the number of notes drops from
  12109.      eight to seven.
  12110.    ──────────────────────────────────────────────────────────────────────────
  12111.  
  12112.    You can use a music-trap subroutine to play the same piece of music
  12113.    repeatedly while your program executes, as shown in the next example:
  12114.  
  12115.    ' Turn on trapping of background music events:
  12116.    PLAY ON
  12117.  
  12118.    ' Branch to the Refresh subroutine when there are fewer than
  12119.    ' two notes in the background music buffer:
  12120.    ON PLAY(2) GOSUB Refresh
  12121.  
  12122.    PRINT "Press any key to start, q to end."
  12123.    Pause$ = INPUT$(1)
  12124.  
  12125.    ' Select the background music option for PLAY:
  12126.    PLAY "MB"
  12127.  
  12128.    ' Start playing the music, so notes will be put in the
  12129.    ' background music buffer:
  12130.    GOSUB Refresh
  12131.  
  12132.    I = 0
  12133.  
  12134.    DO
  12135.  
  12136.       ' Print the numbers from 0 to 10,000 over and over until
  12137.       ' the user presses the "q" key. While this is happening,
  12138.       ' the music will repeat in the background:
  12139.       PRINT I
  12140.       I = (I + 1) MOD 10001
  12141.    LOOP UNTIL INKEY$ = "q"
  12142.  
  12143.    END
  12144.  
  12145.    Refresh:
  12146.  
  12147.       ' Plays the opening motive of
  12148.       ' Beethoven's Fifth Symphony:
  12149.       Listen$ = "t180 o2 p2 p8 L8 GGG L2 E-"
  12150.       Fate$   = "p24 p8 L8 FFF L2 D"
  12151.       PLAY Listen$ + Fate$
  12152.    RETURN
  12153.  
  12154.  
  12155.  6.3  Error and Event Trapping in SUB or FUNCTION Procedures
  12156.  
  12157.    The most important thing to remember when using error or event trapping
  12158.    with BASIC procedures is that either of the following statements can
  12159.    appear within a SUB...END SUB or FUNCTION...END FUNCTION block:
  12160.  
  12161.    ON ERROR GOTO line ON event GOSUB line
  12162.  
  12163.    However, the line referred to in each case must identify a line in the
  12164.    module-level code, not another line within the SUB or FUNCTION.
  12165.  
  12166.    Example
  12167.  
  12168.    The following example shows where to put an error-handling routine that
  12169.    processes errors trapped within a SUB procedure:
  12170.  
  12171.    CALL ShortSub
  12172.    END
  12173.  
  12174.    CatchError:
  12175.       ' Put the CatchError routine at the module level,
  12176.       ' outside the subprogram:
  12177.       PRINT "Error" ERR "caught by error handler."
  12178.    RESUME NEXT
  12179.  
  12180.    SUB ShortSub STATIC
  12181.       ON ERROR GOTO CatchError
  12182.       ERROR 62
  12183.    END SUB
  12184.  
  12185.    Output
  12186.  
  12187.    Error 62 caught by error handler.
  12188.  
  12189.  
  12190.  6.4  Trapping across Multiple Modules
  12191.  
  12192.    Prior to QuickBASIC 4.5, only events could be trapped across modules. Once
  12193.    an event-handling routine was defined and an event trap was activated in
  12194.    one module, an occurrence of that event during program execution in any
  12195.    other module triggered a branch to the routine.
  12196.  
  12197.    Errors could not be trapped across modules. If an error occurred in a
  12198.    module lacking an active error handler, program execution would halt, even
  12199.    if there were a handler in another module that could have taken care of
  12200.    the problem.
  12201.  
  12202.    QuickBASIC 4.5 expands the scope of error trapping. Errors, as well as
  12203.    events, can be trapped across modules. The next two sections explain how
  12204.    this works and the slight remaining differences between event and error
  12205.    trapping.
  12206.  
  12207.  6.4.1  Event Trapping across Modules
  12208.  
  12209.    The output from the following program shows that a trap set for the F1
  12210.    function key in the main module is triggered even when program control is
  12211.    in another module:
  12212.  
  12213.    ' =========================================================
  12214.    '                      MODULE
  12215.    ' =========================================================
  12216.    ON KEY (1) GOSUB GotF1Key
  12217.    KEY (1) ON
  12218.    PRINT "In main module. Press c to continue."
  12219.  
  12220.    DO: LOOP UNTIL INKEY$ = "c"
  12221.  
  12222.    CALL SubKey
  12223.  
  12224.    PRINT "Back in main module. Press q to end."
  12225.    DO : LOOP UNTIL INKEY$ = "q"
  12226.    END
  12227.  
  12228.    GotF1Key:
  12229.       PRINT "Handled F1 keystroke in main module."
  12230.    RETURN
  12231.  
  12232.    ' =========================================================
  12233.    '                      SUBKEY MODULE
  12234.    ' =========================================================
  12235.    SUB SubKey STATIC
  12236.       PRINT "In module with SUBKEY. Press r to return."
  12237.  
  12238.       ' Pressing F1 here still invokes the GotF1Key
  12239.       ' subroutine in the MAIN module:
  12240.       DO: LOOP UNTIL INKEY$ = "r"
  12241.    END SUB
  12242.  
  12243.    Output
  12244.  
  12245.    In main module. Press c to continue.
  12246.    Handled F1 keystroke in main module.
  12247.    In module with SUBKEY. Press r to return.
  12248.    Handled F1 keystroke in main module.
  12249.    Back in main module. Press q to end.
  12250.    Handled F1 keystroke in main module.
  12251.  
  12252.  6.4.2  Error Trapping across Modules
  12253.  
  12254.    Errors can be trapped across multiple modules. If there is no active error
  12255.    handler in the module where the error occurred, BASIC looks for one in the
  12256.    module from which the active module was invoked, continuing back through
  12257.    the sequence of modules called until it finds a module with an active
  12258.    error handler. If it cannot find one, an error message is displayed and
  12259.    program execution halts.
  12260.  
  12261.    Note that BASIC does not search through all modules──only the ones that
  12262.    were in the path of invocation leading to the code that produced the
  12263.    error.
  12264.  
  12265.    An ON ERROR statement must be executed before an error occurs in order for
  12266.    BASIC to look for a handler. Therefore, you must put the ON ERROR GOTO
  12267.    statement where the flow of a program's control can reach it; for example,
  12268.    place it inside a procedure called from the main module (see the examples
  12269.    that follow).
  12270.  
  12271.    Examples
  12272.  
  12273.    The following example shows how to trap errors for a procedure in a Quick
  12274.    library. The AdapterType procedure in this library tries all possible
  12275.    SCREEN statements to see which graphics screen modes your computer's
  12276.    hardware supports. (See Appendix H, "Creating and Using Quick Libraries,"
  12277.    for more information on Quick libraries.)
  12278.  
  12279.    ' =========== MODULE-LEVEL CODE IN QUICK LIBRARY ==========
  12280.    ' The error-handling routines for procedures in this
  12281.    ' library must be defined at this level. This level is
  12282.    ' executed only when there is an error in the procedures.
  12283.    ' =========================================================
  12284.  
  12285.    DEFINT A-Z
  12286.  
  12287.    CONST FALSE = 0, TRUE = NOT FALSE
  12288.  
  12289.    .
  12290.    .
  12291.    .
  12292.    CALL AdapterType
  12293.    .
  12294.    .
  12295.    .
  12296.    END
  12297.  
  12298.    DitchMe:                        ' Error-handling routine
  12299.       DisplayError = TRUE
  12300.       RESUME NEXT
  12301.  
  12302.    ' ========== PROCEDURE-LEVEL CODE IN QUICK LIBRARY ========
  12303.    '          Error trapping is activated at this level.
  12304.    ' =========================================================
  12305.  
  12306.    SUB AdapterType STATIC
  12307.  
  12308.       SHARED DisplayError          ' DisplayError variable is
  12309.                                    ' shared with DitchMe error
  12310.                                    ' handler in code above.
  12311.       DIM DisplayType(1 TO 13)     ' Dimension DisplayType
  12312.                                    ' array.
  12313.  
  12314.       J = 1                        ' Initialize subscript
  12315.                                    ' counter for DisplayType
  12316.                                    ' array.
  12317.  
  12318.    ON ERROR GOTO DitchMe   ' Set up the error trap.
  12319.  
  12320.    FOR Test = 13 TO 1 STEP -1
  12321.          SCREEN Test               ' Try a SCREEN statement to
  12322.                                    ' see if it causes error.
  12323.          IF NOT DisplayError THEN  ' No error, so this is a
  12324.                                    ' valid screen mode.
  12325.              DisplayType(J) = Test ' Store mode in array.
  12326.              J = J + 1             ' Increment the subscript
  12327.                                    ' counter.
  12328.          ELSE
  12329.              DisplayError = FALSE  ' Error; reset DisplayError.
  12330.          END IF
  12331.       NEXT Test
  12332.  
  12333.       SCREEN 0, 0                  ' Set 80-column text mode.
  12334.       WIDTH 80
  12335.       LOCATE 5, 10
  12336.       PRINT "Your computer supports these screen modes:"
  12337.       PRINT
  12338.  
  12339.       FOR I = 1 TO J               ' Print modes not causing
  12340.                                    ' errors.
  12341.          PRINT TAB(20); "SCREEN"; DisplayType(I)
  12342.       NEXT I
  12343.  
  12344.       LOCATE 20, 10
  12345.       PRINT "Press any key to continue..."
  12346.  
  12347.       DO: LOOP WHILE INKEY$ = ""
  12348.  
  12349.    END SUB
  12350.  
  12351.    If you want the error-handling routine in each module to do the exactly
  12352.    the same thing, you can have each routine invoke a common error-processing
  12353.    SUB procedure, as shown in the next example:
  12354.  
  12355.    ' =========================================================
  12356.    '                       MAIN MODULE
  12357.    ' =========================================================
  12358.  
  12359.    DECLARE SUB GlobalHandler (ModuleName$)
  12360.    DECLARE SUB ShortSub ()
  12361.  
  12362.    ON ERROR GOTO LocalHandler
  12363.    ERROR 57                ' Simulate occurrence of error 57
  12364.                            ' ("Device I/O error").
  12365.    ShortSub                ' Call the ShortSub SUB.
  12366.    END
  12367.  
  12368.    LocalHandler:
  12369.       ModuleName$ = "MAIN"
  12370.       CALL GlobalHandler(ModuleName$)  ' Call the
  12371.                                        ' GlobalHandler SUB.
  12372.    RESUME NEXT
  12373.  
  12374.    ' =========================================================
  12375.    '                     SHORTSUB MODULE
  12376.    ' =========================================================
  12377.  
  12378.    DECLARE SUB GlobalHandler (ModuleName$)
  12379.  
  12380.    LocalHandler:
  12381.       ModuleName$ = "SHORTSUB"
  12382.       GlobalHandler ModuleName$    ' Call GlobalHandler.
  12383.    RESUME NEXT
  12384.  
  12385.    SUB ShortSub STATIC
  12386.       ON ERROR GOTO LocalHandler
  12387.       ERROR 13                     ' Simulate a "Type mismatch" error.
  12388.    END SUB
  12389.  
  12390.  
  12391.    ' =========================================================
  12392.    '                    GLOBALHANDLER MODULE
  12393.    ' =========================================================
  12394.  
  12395.    SUB GlobalHandler (ModuleName$) STATIC
  12396.       PRINT "Trapped error";ERR;"in";ModuleName$;"module"
  12397.    END SUB
  12398.  
  12399.    Output
  12400.  
  12401.    Trapped error 57 in MAIN module.
  12402.    Trapped error 13 in SHORTSUB module.
  12403.  
  12404.  
  12405.  6.5  Trapping Errors and Events in Programs Compiled with BC
  12406.  
  12407.    If both of the following statements apply to your program, then you must
  12408.    use the appropriate BC command-line option listed below when compiling
  12409.    your program:
  12410.  
  12411.    ■ You are developing the program outside the QuickBASIC environment──that
  12412.      is, you are using another text editor to enter your BASIC source code,
  12413.      then creating a stand-alone executable program from this source code
  12414.      with the commands BC and LINK.
  12415.  
  12416.    ■ Your program contains any of the statements listed in the second column
  12417.      below.
  12418.  
  12419.    Table 6.1  BC Command-Line Options for Error and Event Trapping
  12420. ╓┌─┌──────────────┌────────────────────────────┌─────────────────────────────╖
  12421.    Command-Line   Statements                   Explanation
  12422.    Option
  12423.    ──────────────────────────────────────────────────────────────────────────
  12424.    /E             ON ERROR GOTO                The /E option tells the
  12425.                   RESUME line                  compiler your program does its
  12426.                                                own error trapping with ON
  12427.                                                ERROR GOTO and RESUME
  12428.                                                statements.
  12429.  
  12430.    /V             ON event GOSUB               The /V option tells the
  12431.                   event ON                     program to check between each
  12432.                                                statement to see if the given
  12433.                                                event has taken place
  12434.    Command-Line   Statements                   Explanation
  12435.    Option
  12436.    ──────────────────────────────────────────────────────────────────────────
  12437.                                               event has taken place
  12438.                                                (contrast this with the effect
  12439.                                                of /W).
  12440.  
  12441.    /W             ON event GOSUB               The /W option tells the
  12442.                   event ON                     program to check between each
  12443.                                                line to see if the given event
  12444.                                                has taken place (contrast this
  12445.                                                with the effect of /V).
  12446.                                                Since BASIC allows multiple
  12447.                                                statements on a single line,
  12448.                                                programs compiled with /W may
  12449.                                                check less frequently than
  12450.                                                those compiled with /V.
  12451.  
  12452.    /X             RESUME                       The /X option tells the
  12453.                   RESUME NEXT                  compiler you have used one of
  12454.                   RESUME 0                     the preceding forms of RESUME
  12455.    Command-Line   Statements                   Explanation
  12456.    Option
  12457.    ──────────────────────────────────────────────────────────────────────────
  12458.                  RESUME 0                     the preceding forms of RESUME
  12459.                                                in your program to return
  12460.                                                control from an error-handling
  12461.                                                routine.
  12462.    ──────────────────────────────────────────────────────────────────────────
  12463.  
  12464.  
  12465.    Example
  12466.  
  12467.    The following DOS command lines compile and link a BASIC module named
  12468.    RMTAB.BAS, creating a stand-alone program RMTAB.EXE. (As this program is
  12469.    compiled without the /O option, it requires the BRUN45.LIB run-time
  12470.    library in order to run. See Appendix G, "Compiling and Linking from
  12471.    DOS," for more information on compiling and linking.) Since this module
  12472.    contains ON ERROR GOTO and RESUME NEXT statements, the /E and /X options
  12473.    are required when compiling.
  12474.  
  12475.    BC RMTAB , , /E /X;
  12476.    LINK RMTAB;
  12477.  
  12478.  
  12479.  6.6  Sample Application: Trapping File-Access Errors (FILERR.BAS)
  12480.  
  12481.    The following program gets as input both a file name and a string to
  12482.    search for in the file. It then lists all lines in the given file
  12483.    containing the specified string. If a file-access error occurs, it is
  12484.    trapped and dealt with in the ErrorProc routine.
  12485.  
  12486.    Statements and Functions Used
  12487.  
  12488.    This program demonstrates the use of the following error-handling
  12489.    statements and functions:
  12490.  
  12491.    ■ ERR
  12492.  
  12493.    ■ ON ERROR GOTO
  12494.  
  12495.    ■ RESUME
  12496.  
  12497.    ■ RESUME NEXT
  12498.  
  12499.    Program Listing
  12500.  
  12501.    ' Declare symbolic constants:
  12502.    CONST FALSE = 0, TRUE = NOT FALSE
  12503.  
  12504.    DECLARE FUNCTION GetFileName$ ()
  12505.  
  12506.    ' Set up the ERROR trap and specify
  12507.    ' the name of the error-handling routine:
  12508.    ON ERROR GOTO ErrorProc
  12509.  
  12510.    DO
  12511.       Restart = FALSE
  12512.       CLS
  12513.  
  12514.       FileName$ = GetFileName$     ' Input file name.
  12515.  
  12516.       IF FileName$ = "" THEN
  12517.          END                       ' End if <ENTER> pressed.
  12518.       ELSE
  12519.  
  12520.          ' Otherwise, open the file, assigning it
  12521.          ' the next available file number:
  12522.          FileNum = FREEFILE
  12523.          OPEN FileName$ FOR INPUT AS FileNum
  12524.       END IF
  12525.  
  12526.    IF NOT Restart THEN
  12527.  
  12528.          ' Input search string:
  12529.          LINE INPUT "Enter string to locate:", LocString$
  12530.          LocString$ = UCASE$(LocString$)
  12531.  
  12532.          ' Loop through the lines in the file,
  12533.          ' printing them if they contain the search string:
  12534.          LineNum = 1
  12535.          DO WHILE NOT EOF(FileNum)
  12536.  
  12537.             ' Input line from file:
  12538.             LINE INPUT #FileNum, LineBuffer$
  12539.  
  12540.             ' Check for string, printing the line
  12541.             ' and its number if found:
  12542.             IF INSTR(UCASE$(LineBuffer$), LocString$) <> 0 THEN
  12543.                PRINT USING "#### &"; LineNum, LineBuffer$
  12544.             END IF
  12545.  
  12546.             LineNum = LineNum + 1
  12547.          LOOP
  12548.  
  12549.          CLOSE FileNum             ' Close the file.
  12550.  
  12551.       END IF
  12552.    LOOP WHILE Restart = TRUE
  12553.  
  12554.    END
  12555.  
  12556.    ErrorProc:
  12557.  
  12558.       SELECT CASE ERR
  12559.  
  12560.          CASE 64:                  ' Bad file name
  12561.             PRINT "** ERROR - Invalid file name"
  12562.  
  12563.             ' Get a new file name and try again:
  12564.             FileName$ = GetFileName$
  12565.  
  12566.             ' Resume at the statement that caused the error:
  12567.             RESUME
  12568.  
  12569.    CASE 71:                  ' Disk not ready.
  12570.             PRINT "** ERROR - Disk drive not ready"
  12571.             PRINT "Press C to continue, R to restart, Q to quit: "
  12572.             DO
  12573.               Char$ = UCASE$(INPUT$(1))
  12574.               IF Char$ = "C" THEN
  12575.                  RESUME           ' Resume where you left off.
  12576.  
  12577.               ELSEIF Char$ = "R" THEN
  12578.                  Restart = TRUE   ' Resume at beginning.
  12579.                  RESUME NEXT
  12580.  
  12581.               ELSEIF Char$ = "Q" THEN
  12582.                   END              ' Don't resume at all.
  12583.                   END IF
  12584.             LOOP
  12585.  
  12586.          CASE 53, 76:              ' File or path not found.
  12587.             PRINT "** ERROR - File or path not found"
  12588.             FileName$ = GetFileName$
  12589.             RESUME
  12590.  
  12591.          CASE ELSE:                ' Unforeseen error.
  12592.  
  12593.             ' Disable error trapping and
  12594.             ' print standard system message:
  12595.             ON ERROR GOTO 0
  12596.       END SELECT
  12597.  
  12598.    ' ===================== GETFILENAME$ =======================
  12599.    '           Returns a file name from user input
  12600.    ' ==========================================================
  12601.  
  12602.    FUNCTION GetFileName$ STATIC
  12603.       INPUT "Enter file to search (or ENTER to quit):", FTemp$
  12604.       GetFileName$ = FTemp$
  12605.    END FUNCTION
  12606.  
  12607.  
  12608.  
  12609.  ────────────────────────────────────────────────────────────────────────────
  12610.  Chapter 7  Programming with Modules
  12611.  
  12612.    This chapter shows how you can gain more control over your programming
  12613.    projects by dividing them into "modules." Modules provide a powerful
  12614.    organizing function by letting you divide a program into logically related
  12615.    parts (rather than keeping all the code in one file).
  12616.  
  12617.    This chapter will show you how to use modules to:
  12618.  
  12619.    ■ Write and test new procedures separately from the rest of the program
  12620.  
  12621.    ■ Create libraries of your own SUB and FUNCTION procedures that can be
  12622.      added to any new program
  12623.  
  12624.    ■ Combine routines from other languages (such as C or MASM) with your
  12625.      BASIC programs
  12626.  
  12627.  
  12628.  7.1  Why Use Modules?
  12629.  
  12630.    A module is a file that contains an executable part of your program. A
  12631.    complete program can be contained in a single module, or it can be divided
  12632.    among two or more modules.
  12633.  
  12634.    In dividing up a program into modules, logically related sections are
  12635.    placed in separate files. This organization can speed and simplify the
  12636.    process of writing, testing, and debugging.
  12637.  
  12638.    Dividing your program into modules has these advantages:
  12639.  
  12640.    ■ Modules allow procedures to be written separately from the rest of the
  12641.      program, then combined with it. This arrangement is especially useful
  12642.      for testing the procedures, since they can then be checked outside the
  12643.      environment of the program.
  12644.  
  12645.    ■ Two or more programmers can work on different parts of the same program
  12646.      without interference. This is especially helpful in managing complex
  12647.      programming projects.
  12648.  
  12649.    ■ As you create procedures that meet your own specific programming needs,
  12650.      you can add these procedures to their own module. They can then be
  12651.      reused in new programs simply by loading that module.
  12652.  
  12653.    ■ Multiple modules simplify software maintenance. A procedure used by many
  12654.      programs can be in one library module; if changes are needed, it only
  12655.      has to be modified once.
  12656.  
  12657.  
  12658.  7.2  Main Modules
  12659.  
  12660.    The module containing the first executable statement of a program is
  12661.    called the "main module." This statement is never part of a procedure,
  12662.    because execution cannot begin within a procedure.
  12663.  
  12664.    Everything in a module except SUB and FUNCTION procedures is said to be
  12665.    "module-level code." In QuickBASIC, the module-level code is every
  12666.    statement that can be accessed without switching to a procedure-editing
  12667.    window. Figure 7.1 illustrates the relationship between these elements.
  12668.  
  12669.  
  12670.  7.3  Modules Containing Only Procedures
  12671.  
  12672.    A module need not contain module-level code; a module can consist of
  12673.    nothing but SUB and FUNCTION procedures. Indeed, this is the most
  12674.    important use of modules.
  12675.  
  12676.    Modules are often used to "split off" the procedures from the body of the
  12677.    program. This makes it easy to divide a project among programmers, for
  12678.    example. Also, as you create general-purpose procedures that are useful in
  12679.    a variety of programs (such as procedures that evaluate matrices, send
  12680.    binary data to a COM port, alter strings, or handle errors), these can be
  12681.    stored in modules, then used in new programs simply by loading the
  12682.    appropriate module into QuickBASIC.
  12683.  
  12684.    ──────────────────────────────────────────────────────────────────────────
  12685.    NOTE
  12686.      If a procedure in a procedures-only module needs an error- or
  12687.      event-handling routine or a COMMON SHARED statement, these are inserted
  12688.      at module level.
  12689.    ──────────────────────────────────────────────────────────────────────────
  12690.  
  12691.  
  12692.    ┌───────────────────────────────────────────────────────────────────────┐
  12693.    │             Program execution begins here                             │
  12694.    │       ┌─ ┌────────────────────────────────────────────┐ ─┐            │
  12695.    │       │  │  declarations and definitions              │  │            │
  12696.    │       │  │  executable program statement 1            │  │            │
  12697.    │       │  │  executable program statement 2            │  │            │
  12698.    │       │  │  .                                         │  ├─ Module-   │
  12699.    │       │  │  .                                         │  │ level code │
  12700.    │       │  │  .                                         │  │            │
  12701.    │       │  │  END                                       │  │            │
  12702.    │       │  │  error-handling routines                   │  │            │
  12703.    │       │  └────────────────────────────────────────────┘ ─┘            │
  12704.    │       │  ┌────────────────────────────────────────────┐ ─┐            │
  12705.    │       │  │  SUB                                       │  │            │
  12706.    │       │  │   statements in first SUB procedure        │  │            │
  12707.    │       │  │  ENDSUB                                    │  │            │
  12708.    │       │  └────────────────────────────────────────────┘  │            │
  12709.    │       │  ┌────────────────────────────────────────────┐  │            │
  12710.    │ Main ─┤  │  SUB                                       │  │            │
  12711.    │module │  │   statements in second SUB procedure       │  │            │
  12712.    │       │  │  ENDSUB                                    │  │            │
  12713.    │       │  └────────────────────────────────────────────┘  │            │
  12714.    │       │     .                                            │            │
  12715.    │       │     .                                            ├─Procedures │
  12716.    │       │     .                                            │            │
  12717.    │       │  ┌────────────────────────────────────────────┐  │            │
  12718.    │       │  │  FUNCTION                                  │  │            │
  12719.    │       │  │   statements in first FUNCTION procedure   │  │            │
  12720.    │       │  │  ENDFUNCTION                               │  │            │
  12721.    │       │  └────────────────────────────────────────────┘  │            │
  12722.    │       │  ┌────────────────────────────────────────────┐  │            │
  12723.    │       │  │  FUNCTION                                  │  │            │
  12724.    │       │  │   statements in second FUNCTION procedure  │  │            │
  12725.    │       │  │  ENDFUNCTION                               │  │            │
  12726.    │       │  └────────────────────────────────────────────┘  │            │
  12727.    │       │     .                                            │            │
  12728.    │       │     .                                            │            │
  12729.    │       │     .                                            │            │
  12730.    │       └─                                                ─┘            │
  12731.    │                                                                       │
  12732.    └───────────────────────────────────────────────────────────────────────┘
  12733.  
  12734.    Figure 7.1  Main Module Showing Module-Level Code and Procedures
  12735.  
  12736.  
  12737.  7.4  Creating a Procedures-Only Module
  12738.  
  12739.    It's easy to create a module that contains only procedures. You can enter
  12740.    new procedures in a separate file, or you can move procedures from one
  12741.    file to another.
  12742.  
  12743.    To create a new module:
  12744.  
  12745.    1. Invoke QuickBASIC without opening or loading any files.
  12746.  
  12747.    2. Write all the SUB and FUNCTION procedures you wish, but don't enter any
  12748.       module-level code. (Any error- or event-trapping routines and BASIC
  12749.       declarations needed are exceptions.)
  12750.  
  12751.    3. Use the Save As command to name and save this module.
  12752.  
  12753.    To move procedures from one module to another:
  12754.  
  12755.    1. Load the files containing the procedures you want to move.
  12756.  
  12757.    2. If the destination file already exists, use the Load File command from
  12758.       the File menu to load it, too. If it doesn't exist, use the Create File
  12759.       option from the File menu to make the new file.
  12760.  
  12761.    3. Choose the SUBs command from the View menu and use its Move feature to
  12762.       transfer the procedures from the old to the new file. This transfer is
  12763.       made final when you quit QuickBASIC and respond Yes to the dialog box
  12764.       that asks whether you want to save the modified files; otherwise, the
  12765.       procedures remain where they were when you started.
  12766.  
  12767.  
  12768.  7.5  Loading Modules
  12769.  
  12770.    In QuickBASIC, you can load as many modules as you wish (limited only by
  12771.    the available memory) using the Load File command from the File menu. All
  12772.    the procedures in all the loaded modules can be called from any other
  12773.    procedure or from module-level code. If a module happens to contain a
  12774.    procedure that is never called, no harm occurs.
  12775.  
  12776.    Any or all of the loaded modules can contain module-level code. QuickBASIC
  12777.    normally begins execution with the module-level code of the first module
  12778.    loaded. If you want execution to begin in a different module, use the Set
  12779.    Main Module command from the Run menu. Execution normally halts at the end
  12780.    of the designated main module; by design, QuickBASIC does not continue
  12781.    execution with the module-level code from other modules.
  12782.  
  12783.    The ability to choose which module-level code gets executed is useful when
  12784.    comparing two versions of the same program. For example, you might want to
  12785.    test different user interfaces by putting each in a separate module. You
  12786.    can also place test code in a module containing only procedures, then use
  12787.    the Set Main Module command to switch between the program and the tests.
  12788.  
  12789.    You do not have to keep track of which modules your program uses. Whenever
  12790.    you use the Save All command, QuickBASIC creates (or updates) a .MAK file,
  12791.    which lists all the modules currently loaded. The next time the main
  12792.    module is loaded with the Open Program command, QuickBASIC consults this
  12793.    .MAK file and automatically loads the modules listed in it.
  12794.  
  12795.  
  12796.  7.6  Using the DECLARE Statement with Multiple Modules
  12797.  
  12798.    The DECLARE statement has several important functions in QuickBASIC. Using
  12799.    a DECLARE statement will
  12800.  
  12801.    1. Specify the sequence and data types of a procedure's parameters
  12802.  
  12803.    2. Enable type-checking, which confirms, each time a procedure is called,
  12804.       that the arguments agree with the parameters in both number and data
  12805.       type
  12806.  
  12807.    3. Identify a FUNCTION procedure's name as a procedure name, not a
  12808.       variable name
  12809.  
  12810.    4. Most important of all, enable the main module to call procedures
  12811.       located in other modules (or Quick libraries)
  12812.  
  12813.    QuickBASIC has its own system for automatically inserting the required
  12814.    DECLARE statements into your modules. Section 2.5.4, "Checking Arguments
  12815.    with the DECLARE Statement," explains the features and limitations of this
  12816.    system.
  12817.  
  12818.    Despite QuickBASIC's automatic insertion of the DECLARE statement, you may
  12819.    wish to create a separate include file that contains all the DECLARE
  12820.    statements required for a program. You can update this file manually as
  12821.    you add and delete procedures or modify your argument lists.
  12822.  
  12823.    If you write your programs with a text editor (rather than the QuickBASIC
  12824.    programming environment) and compile with BC, you must insert DECLARE
  12825.    statements manually.
  12826.  
  12827.  
  12828.  7.7  Accessing Variables from Two or More Modules
  12829.  
  12830.    You can use the SHARED attribute to make variables accessible both at
  12831.    module level and within that module's procedures. If these procedures are
  12832.    moved to another module, however, these variables are no longer shared.
  12833.  
  12834.    You could pass these variables to each procedure through its argument
  12835.    list. This may be inconvenient, though, if you need to pass a large number
  12836.    of variables.
  12837.  
  12838.    One solution is to use COMMON statements, which enable two or more modules
  12839.    to access the same group of variables. Section 2.6, "Sharing Variables
  12840.    with SHARED," explains how to do this.
  12841.  
  12842.    Another solution is to use a TYPE...END TYPE statement to combine all the
  12843.    variables you wish to pass into a single structure. The argument and
  12844.    parameter lists then have to include only one variable name, no matter how
  12845.    many variables are passed.
  12846.  
  12847.    If you are simply splitting up a program and its procedures into separate
  12848.    modules, either of these approaches works well. If, on the other hand, you
  12849.    are adding a procedure to a module (for use in other programs), you should
  12850.    avoid using a COMMON statement. Modules are supposed to make it easy to
  12851.    add existing procedures to new programs; COMMON statements complicate the
  12852.    process. If a procedure needs a large group of variables, it may not
  12853.    belong in a separate module.
  12854.  
  12855.  
  12856.  7.8  Using Modules During Program Development
  12857.  
  12858.    When you start a new programming project, you should first look through
  12859.    existing modules to see if there are procedures that can be reused in your
  12860.    new software. If any of these procedures aren't already in a separate
  12861.    module, you should consider moving them to one.
  12862.  
  12863.    As your program takes shape, newly written procedures automatically become
  12864.    part of the program file (that is, the main module). You can move them to
  12865.    a separate module for testing or perhaps add them to one of your own
  12866.    modules along with other general-purpose procedures that are used in other
  12867.    programs.
  12868.  
  12869.    Your program may need procedures written in other languages. (For example,
  12870.    MASM is ideal for direct interface with the hardware, FORTRAN has almost
  12871.    any math function you could want, Pascal allows the creation of
  12872.    sophisticated data structures, and C provides both structured code and
  12873.    direct memory access.) These procedures are compiled and linked into a
  12874.    Quick library for use in your program. You can also write a separate
  12875.    module to test Quick library procedures the same way you would test other
  12876.    procedures.
  12877.  
  12878.  
  12879.  7.9  Compiling and Linking Modules
  12880.  
  12881.    The end product of your programming efforts is usually a stand-alone .EXE
  12882.    file. You can create one in QuickBASIC by loading all of a program's
  12883.    modules, then selecting the Make EXE File command from the Run menu.
  12884.  
  12885.    You can also compile modules with the BC command-line compiler, then use
  12886.    LINK to combine the object code. Object files from code written in other
  12887.    languages can be linked at the same time.
  12888.  
  12889.    ──────────────────────────────────────────────────────────────────────────
  12890.    NOTE
  12891.      When you use the Make EXE File command, all the module-level code and
  12892.      every procedure currently loaded is included in the .EXE file, whether
  12893.      or not the program uses this code. If you want your program to be as
  12894.      compact as possible, you must unload all unneeded module-level code and
  12895.      all unneeded procedures before compiling. The same rule applies when
  12896.      using BC to compile from the command line; all unused code should be
  12897.      removed from the files.
  12898.    ──────────────────────────────────────────────────────────────────────────
  12899.  
  12900.  
  12901.  7.10  Quick Libraries
  12902.  
  12903.    Although Microsoft Quick libraries are not modules, it is important that
  12904.    you understand their relationship with modules.
  12905.  
  12906.    A Quick library contains nothing but procedures. These procedures can be
  12907.    written not only in QuickBASIC, but also in other Microsoft languages as
  12908.    well (C, Pascal, FORTRAN, and MASM).
  12909.  
  12910.    A Quick library contains only compiled code. (Modules contain QuickBASIC
  12911.    source code.) A Quick library is created by linking compiled object code
  12912.    (.OBJ files). The code in a Quick library can come from any combination of
  12913.    Microsoft languages. Appendix H, "Creating and Using Quick Libraries,"
  12914.    explains how to create Quick libraries from object code and how to add new
  12915.    object code to existing Quick libraries.
  12916.  
  12917.    Quick libraries have several uses:
  12918.  
  12919.    ■ They provide an interface between QuickBASIC and other languages.
  12920.  
  12921.    ■ They allow designers to hide proprietary software. Updates and utilities
  12922.      can be distributed as Quick libraries without revealing the source code.
  12923.  
  12924.    ■ They load faster and are usually smaller than modules. If a large
  12925.      program with many modules loads slowly, converting the nonmain modules
  12926.      into a Quick library will improve loading performance.
  12927.  
  12928.    Note, however, that modules are the easiest way to work on procedures
  12929.    during development because modules are immediately ready to run after each
  12930.    edit; you don't have to recreate the Quick library. If you want to put
  12931.    your QuickBASIC procedures in a Quick library, wait until the procedures
  12932.    are complete and thoroughly debugged.
  12933.  
  12934.    When a Quick library is created, any module-level code in the file it was
  12935.    created from is automatically included. However, other modules cannot
  12936.    access this code, so it just wastes space. Before converting a module to a
  12937.    Quick library, be sure that all module-level statements (except any error
  12938.    or event handlers and declarations that are used by the procedures) have
  12939.    been removed.
  12940.  
  12941.    ──────────────────────────────────────────────────────────────────────────
  12942.    NOTE
  12943.      Quick libraries are not included in .MAK files and must be loaded with
  12944.      the / L option when you run QuickBASIC. A Quick library has the file
  12945.      extension .QLB. During the process of creating the Quick library,
  12946.      another library file with the extension .LIB is created. This file
  12947.      contains the same code as the Quick library but in a form that allows it
  12948.      to be linked with the rest of the program to create a stand-alone
  12949.      application.
  12950.  
  12951.      If you use Quick libraries to distribute proprietary code
  12952.      (data-manipulation procedures, for example), be sure to include the .LIB
  12953.      files so that your customers can create stand-alone applications that
  12954.      use these procedures. Otherwise, they will be limited to running
  12955.      applications within the QuickBASIC environment.
  12956.    ──────────────────────────────────────────────────────────────────────────
  12957.  
  12958.  7.10.1  Creating Quick Libraries
  12959.  
  12960.    You can create a Quick library of QuickBASIC procedures with the Make
  12961.    Library command from the Run menu. The Quick library created contains
  12962.    every procedure currently loaded, whether or not your program calls it.
  12963.    (It also contains all the module-level code.) If you want the Quick
  12964.    library to be compact, be sure to remove all unused procedures and all
  12965.    unnecessary module-level code first.
  12966.  
  12967.    You can create as many Quick libraries as you like, containing whatever
  12968.    combination of procedures you wish. However, only one Quick library can be
  12969.    loaded into QuickBASIC at a time. (You would generally create
  12970.    application-specific Quick libraries, containing only the procedures a
  12971.    particular program needs.) Large Quick libraries can be created by loading
  12972.    many modules, then using the Make Library command.
  12973.  
  12974.    You can also compile one or more modules with the BC command, then link
  12975.    the object code files to create a Quick library. Quick libraries of
  12976.    procedures written
  12977.  
  12978.    in other languages are created the same way. In linking, you are not
  12979.    limited to one language; the object-code files from any number of
  12980.    Microsoft languages can be combined in one Quick library. Appendix H,
  12981.    "Creating and Using Quick Libraries," explains how to convert object-code
  12982.    (.OBJ) files into Quick libraries.
  12983.  
  12984.  
  12985.  7.11  Tips for Good Programming with Modules
  12986.  
  12987.    You can use modules in any way you think will improve your program or help
  12988.    organize your work. The following suggestions are offered as a guide.
  12989.  
  12990.    1. Think and organize first.
  12991.  
  12992.       When you start on a new project, make a list of the operations you want
  12993.       to be performed by procedures. Then look through your own procedure
  12994.       library to see if there are any you can use, either as-is or with
  12995.       slight modifications. Don't waste time "reinventing the wheel."
  12996.  
  12997.    2. Write generalized procedures with broad application.
  12998.  
  12999.       Try to write procedures that are useful in a wide variety of programs.
  13000.       Don't, however, make the procedure needlessly complex. A good procedure
  13001.       is a simple, finely honed tool, not a Swiss army knife.
  13002.  
  13003.       It is sometimes useful to alter an existing procedure to work in a new
  13004.       program. This might require modifying programs you've already written,
  13005.       but it's worth the trouble if the revised procedure is more powerful or
  13006.       has broader application.
  13007.  
  13008.    3. When creating your own procedure modules, keep logically separate
  13009.       procedures in separate modules.
  13010.  
  13011.       It makes sense to put string-manipulation procedures in one module,
  13012.       matrix-handling procedures in another, and data-communication
  13013.       procedures in a third. This arrangement avoids confusion and makes it
  13014.       easy to find the procedure you need.
  13015.  
  13016.  
  13017.  
  13018.  ────────────────────────────────────────────────────────────────────────────
  13019.  PART 2  HEART OF BASIC
  13020.  ────────────────────────────────────────────────────────────────────────────
  13021.  
  13022.    Part 2 provides a quick-reference guide to all statements and functions
  13023.    used in this version of BASIC.
  13024.  
  13025.    Chapter 8 gives a brief summary of the action of each statement or
  13026.    function──organized alphabetically by keyword──and includes syntax lines
  13027.    that identify the statement's correct form. Use it when programming to
  13028.    remind yourself how each one works.
  13029.  
  13030.    Chapter 9 is made up of reference tables that organize commonly used
  13031.    statements and functions by programming topic. These tables follow the
  13032.    same organization as the first six chapters of this book. Use these tables
  13033.    to identify alternative ways to approach particular programming
  13034.    objectives.
  13035.  
  13036.  
  13037.  
  13038.  ────────────────────────────────────────────────────────────────────────────
  13039.  Chapter 8  Statement and Function Summary
  13040.  
  13041.    This chapter summarizes QuickBASIC statements and functions. Each
  13042.    statement or function name is followed by an action description and a
  13043.    syntax line. The syntax line shows exactly what you must enter to use the
  13044.    statement.
  13045.  
  13046.    Complete details of the typographic conventions used in syntax lines are
  13047.    given in the introduction to this manual. In general, items you must type
  13048.    exactly as shown are in boldface type; placeholders for items of
  13049.    information you must supply are in Italic type. Square brackets indicate
  13050.    optional items.
  13051.  
  13052.    The QB Advisor (QuickBASIC's on-line language help) provides for each
  13053.    statement or function:
  13054.  
  13055.    ■ A summary of the statement's action and syntax (the QuickSCREEN)
  13056.  
  13057.    ■ Complete details of how to use the statement, including explanations of
  13058.      the placeholders
  13059.  
  13060.    ■ One of more program examples illustrating statement use
  13061.  
  13062.    You can access this information by putting the cursor on any BASIC keyword
  13063.    displayed in the QuickBASIC View window and pressing F1.
  13064.  
  13065.    The statements and functions in this chapter are grouped by topic in
  13066.    Chapter 9, "Quick-Reference Tables." Use Chapter 9 to find out what
  13067.    statements are available for a particular programming task.
  13068.  
  13069.  
  13070.  ABS Function
  13071.  
  13072.    Returns the absolute value of a numeric expression
  13073.  
  13074.    SYNTAX  ABS(numeric-expression)
  13075.  
  13076.  
  13077.  ASC Function
  13078.  
  13079.    Returns a numeric value that is the ASCII code for the first character in
  13080.    a string expression
  13081.  
  13082.    SYNTAX  ASC(stringexpression)
  13083.  
  13084.  
  13085.  ATN Function
  13086.  
  13087.    Returns the arctangent of a numeric expression (the angle whose tangent is
  13088.    equal to the numeric expression)
  13089.  
  13090.    SYNTAX  ATN(numeric-expression)
  13091.  
  13092.  
  13093.  BEEP Statement
  13094.  
  13095.    Sounds the speaker
  13096.  
  13097.    SYNTAX  BEEP
  13098.  
  13099.  
  13100.  BLOAD Statement
  13101.  
  13102.    Loads a memory-image file, created by BSAVE, into memory from an input
  13103.    file or device
  13104.  
  13105.    SYNTAX  BLOAD filespec [[,offset]]
  13106.  
  13107.  
  13108.  BSAVE Statement
  13109.  
  13110.    Transfers the contents of an area of memory to an output file or device
  13111.  
  13112.    SYNTAX  BSAVE filespec,offset,length
  13113.  
  13114.  
  13115.  CALL Statement (BASIC Procedures)
  13116.  
  13117.    Transfers control to a BASIC SUB
  13118.  
  13119.    SYNTAX 1  CALL name[[(argumentlist )]]
  13120.  
  13121.    SYNTAX 2  name[[argumentlist]]
  13122.  
  13123.  
  13124.  CALL, CALLS Statement (Non-BASIC Procedures)
  13125.  
  13126.    Transfers control to a procedure written in another language
  13127.  
  13128.    SYNTAX 1  CALL name [[(call-argumentlist )]]
  13129.  
  13130.    SYNTAX 2  name [[call-argumentlist]]
  13131.  
  13132.    SYNTAX 3  CALLS name [[(calls-argumentlist )]]
  13133.  
  13134.  
  13135.  CALL INT86OLD Statements
  13136.  
  13137.    Allows programs to perform DOS system calls
  13138.  
  13139.    SYNTAX  CALL INT86OLD (int_no,in_array(),out_array())
  13140.            CALL INT86XOLD (int_no,in_array(),out_array())
  13141.  
  13142.  
  13143.  CALL ABSOLUTE Statement
  13144.  
  13145.    Transfers control to a machine-language procedure
  13146.  
  13147.    SYNTAX  CALL ABSOLUTE ([[argumentlist,]]integervariable)
  13148.  
  13149.  
  13150.  CALL INTERRUPT Statements
  13151.  
  13152.    Allows BASIC programs to perform DOS system calls
  13153.  
  13154.    SYNTAX  CALL INTERRUPT (interruptnum, inregs, outregs)
  13155.            CALL INTERRUPTX (interruptnum, inregs, outregs)
  13156.  
  13157.  
  13158.  CDBL Function
  13159.  
  13160.    Converts a numeric expression to a double-precision number
  13161.  
  13162.    SYNTAX  CDBL(numeric-expression)
  13163.  
  13164.  
  13165.  CHAIN Statement
  13166.  
  13167.    Transfers control from the current program to another program
  13168.  
  13169.    SYNTAX  CHAIN filespec
  13170.  
  13171.  
  13172.  CHDIR Statement
  13173.  
  13174.    Changes the current default directory for the specified drive
  13175.  
  13176.    SYNTAX  CHDIR pathspec
  13177.  
  13178.  
  13179.  CHR$ Function
  13180.  
  13181.    Returns a one-character string whose ASCII code is the argument
  13182.  
  13183.    SYNTAX  CHR$(code)
  13184.  
  13185.  
  13186.  CINT Function
  13187.  
  13188.    Converts a numeric expression to an integer by rounding the fractional
  13189.    part of the expression
  13190.  
  13191.    SYNTAX  CINT(numeric-expression)
  13192.  
  13193.  
  13194.  CIRCLE Statement
  13195.  
  13196.    Draws an ellipse or circle with a specified center and radius
  13197.  
  13198.    SYNTAX  CIRCLE[[STEP]]
  13199.            (x,y),radius[[,[[color]][[,[[start]][[,[[end]][[,aspect]]]]]]]]
  13200.  
  13201.  
  13202.  CLEAR Statement
  13203.  
  13204.    Reinitializes all program variables, closes files, and sets the stack size
  13205.  
  13206.    SYNTAX  CLEAR[[,,stack]]
  13207.  
  13208.  
  13209.  CLNG Function
  13210.  
  13211.    Converts a numeric expression to a long (4-byte) integer by rounding the
  13212.    fractional part of the expression
  13213.  
  13214.    SYNTAX  CLNG(numeric-expression)
  13215.  
  13216.  
  13217.  CLOSE Statement
  13218.  
  13219.    Concludes I/O to a file or device
  13220.  
  13221.    SYNTAX  CLOSE[[[[#]] filenumber [[,[[#]] filenumber]]... ]]
  13222.  
  13223.  
  13224.  CLS Statement
  13225.  
  13226.    Clears the screen
  13227.  
  13228.    SYNTAX  CLS[[{0| 1| 2}]]
  13229.  
  13230.  
  13231.  COLOR Statement
  13232.  
  13233.    Selects display colors
  13234.  
  13235.    SYNTAX  COLOR[[foreground]][[,[[background]][[,border]]]]  Screen mode 0
  13236.            COLOR[[background]][[,palette]]                    Screen mode 1
  13237.            COLOR[[foreground]][[,background]]                 Screen modes
  13238.                                                               7-10
  13239.            COLOR[[foreground]]                                Screen modes
  13240.                                                               12-13
  13241.  
  13242.  
  13243.  COM Statements
  13244.  
  13245.    Enables, disables, or inhibits event trapping of communications activity
  13246.    on a specified port
  13247.  
  13248.    SYNTAX  COM(n) ON COM(n) OFF COM(n) STOP
  13249.  
  13250.  
  13251.  COMMAND$ Function
  13252.  
  13253.    Returns the command line used to invoke the program
  13254.  
  13255.    SYNTAX  COMMAND$
  13256.  
  13257.  
  13258.  COMMON Statement
  13259.  
  13260.    Defines global variables for sharing between modules or for chaining to
  13261.    another program
  13262.  
  13263.    SYNTAX  COMMON[[SHARED]][[/blockname/]] variablelist
  13264.  
  13265.  
  13266.  CONST Statement
  13267.  
  13268.    Declares symbolic constants to use in place of numeric or string values
  13269.  
  13270.    SYNTAX  CONST constantname = expression [[,constantname = expression]]...
  13271.  
  13272.  
  13273.  COS Function
  13274.  
  13275.    Returns the cosine of an angle given in radians
  13276.  
  13277.    SYNTAX  COS(numeric-expression)
  13278.  
  13279.  
  13280.  CSNG Function
  13281.  
  13282.    Converts a numeric expression to a single-precision value
  13283.  
  13284.    SYNTAX  CSNG(numeric-expression)
  13285.  
  13286.  
  13287.  CSRLIN Function
  13288.  
  13289.    Returns the current line (row) position of the cursor
  13290.  
  13291.    SYNTAX  CSRLIN
  13292.  
  13293.  
  13294.  CVI, CVS, CVL, CVD Functions
  13295.  
  13296.    Convert strings containing numeric values to numbers
  13297.  
  13298.    SYNTAX  CVI(2-byte-string)
  13299.            CVS(4-byte-string)
  13300.            CVL(4-byte-string)
  13301.            CVD(8-byte-string)
  13302.  
  13303.  
  13304.  CVSMBF, CVDMBF Functions
  13305.  
  13306.    Convert strings containing Microsoft Binary format numbers to IEEE-format
  13307.    numbers
  13308.  
  13309.    SYNTAX  CVSMBF (4-byte-string)
  13310.            CVDMBF (8-byte-string)
  13311.  
  13312.  
  13313.  DATA Statement
  13314.  
  13315.    Stores the numeric and string constants used by a program's READ
  13316.    statements
  13317.  
  13318.    SYNTAX  DATA constant1 [[,constant2]]...
  13319.  
  13320.  
  13321.  DATE$ Function
  13322.  
  13323.    Returns a string containing the current date
  13324.  
  13325.    SYNTAX  DATE$
  13326.  
  13327.  
  13328.  DATE$ Statement
  13329.  
  13330.    Sets the current date
  13331.  
  13332.    SYNTAX  DATE$ = stringexpression
  13333.  
  13334.  
  13335.  DECLARE Statement (BASIC Procedures)
  13336.  
  13337.    Declares references to BASIC procedures and invokes argument type checking
  13338.  
  13339.    SYNTAX  DECLARE{FUNCTION | SUB } name [[([[parameterlist]])]]
  13340.  
  13341.  
  13342.  DECLARE Statement (Non-BASIC Procedures)
  13343.  
  13344.    Declares calling sequences for external procedures written in other
  13345.    languages
  13346.  
  13347.    SYNTAX 1  DECLARE FUNCTION name [[CDECL]]
  13348.              [[ALIAS "aliasname"]][[([[parameterlist]])]]
  13349.  
  13350.    SYNTAX 2  DECLARE SUB name [[CDECL]] [[ALIAS
  13351.              "aliasname"]][[([[parameterlist]])]]
  13352.  
  13353.  
  13354.  DEF FN Statement
  13355.  
  13356.    Defines and names a function
  13357.  
  13358.    SYNTAX 1  DEF FNname[[(parameterlist)]] = expression
  13359.  
  13360.    SYNTAX 2  DEF FNname[[(parameterlist)]]
  13361.              .
  13362.              .
  13363.              .
  13364.              FNname = expression
  13365.              .
  13366.              .
  13367.              .
  13368.              END DEF
  13369.  
  13370.  
  13371.  DEF SEG Statement
  13372.  
  13373.    Sets the current segment address for a subsequent PEEK function or a
  13374.    BLOAD, BSAVE, CALL ABSOLUTE, or POKE statement
  13375.  
  13376.    SYNTAX  DEF SEG[[=address]]
  13377.  
  13378.  
  13379.  DEFtype Statements
  13380.  
  13381.    Set the default data type for variables, DEF FN functions, and FUNCTION
  13382.    procedures
  13383.  
  13384.    SYNTAX  DEFINT letterrange [[,letterrange]]...
  13385.            DEFSNG letterrange [[,letterrange]]...
  13386.            DEFDBL letterrange [[,letterrange]]...
  13387.            DEFLNG letterrange [[,letterrange]]...
  13388.            DEFSTR letterrange [[,letterrange]]...
  13389.  
  13390.  
  13391.  DIM Statement
  13392.  
  13393.    Declares a variable and allocates storage space
  13394.  
  13395.    SYNTAX  DIM[[SHARED]] variable[[(subscripts)]] [[AS type]]
  13396.            [[,variable[[(subscripts)]] [[AStype]]]]...
  13397.  
  13398.  
  13399.  DO...LOOP Statements
  13400.  
  13401.    Repeats a block of statements while a condition is true or until a
  13402.    condition becomes true
  13403.  
  13404.    SYNTAX 1  DO     [[statementblock]]
  13405.              LOOP[[{WHILE| UNTIL} booleanexpression]]
  13406.  
  13407.    SYNTAX 2  DO[[{WHILE| UNTIL} booleanexpression]]
  13408.                   [[statementblock]]
  13409.              LOOP
  13410.  
  13411.  
  13412.  DRAW Statement
  13413.  
  13414.    Draws an object defined by stringexpression
  13415.  
  13416.    SYNTAX  DRAW stringexpression
  13417.  
  13418.  
  13419.  END Statement
  13420.  
  13421.    Ends a BASIC program, procedure, or block
  13422.  
  13423.    SYNTAX  END[[{DEF| FUNCTION | IF| SELECT| SUB | TYPE}]]
  13424.  
  13425.  
  13426.  ENVIRON$ Function
  13427.  
  13428.    Retrieves an environment string from the DOS environment-string table
  13429.  
  13430.    SYNTAX  ENVIRON$ (environmentstring)
  13431.            ENVIRON$ (n)
  13432.  
  13433.  
  13434.  ENVIRON Statement
  13435.  
  13436.    Modifies a parameter in the DOS environment-string table
  13437.  
  13438.    SYNTAX  ENVIRON stringexpression
  13439.  
  13440.  
  13441.  EOF Function
  13442.  
  13443.    Tests for the end-of-file condition
  13444.  
  13445.    SYNTAX  EOF(filenumber)
  13446.  
  13447.  
  13448.  ERASE Statement
  13449.  
  13450.    Reinitializes the elements of static arrays; deallocates dynamic arrays
  13451.  
  13452.    SYNTAX  ERASE arrayname [[,arrayname...]]
  13453.  
  13454.  
  13455.  ERDEV, ERDEV$ Functions
  13456.  
  13457.    Provides device-specific status information after an error
  13458.  
  13459.    SYNTAX  ERDEV
  13460.            ERDEV$
  13461.  
  13462.  
  13463.  ERR, ERL Functions
  13464.  
  13465.    Return error status
  13466.  
  13467.    SYNTAX  ERR
  13468.            ERL
  13469.  
  13470.  
  13471.  ERROR Statement
  13472.  
  13473.    Simulates the occurrence of a BASIC error or allows the user to define
  13474.    error codes
  13475.  
  13476.    SYNTAX  ERROR integerexpression
  13477.  
  13478.  
  13479.  EXIT Statement
  13480.  
  13481.    Exits a DEF FN function, DO...LOOP or FOR...NEXT loop, FUNCTION, or SUB
  13482.  
  13483.    SYNTAX  EXIT{DEF| DO| FOR| FUNCTION| SUB}
  13484.  
  13485.  
  13486.  EXP Function
  13487.  
  13488.    Calculates the exponential function
  13489.  
  13490.    SYNTAX  EXP(x)
  13491.  
  13492.  
  13493.  FIELD Statement
  13494.  
  13495.    Allocates space for variables in a random-access file buffer
  13496.  
  13497.    SYNTAX  FIELD[[#]]filenumber, fieldwidth AS stringvariable...
  13498.  
  13499.  
  13500.  FILEATTR Function
  13501.  
  13502.    Returns information about an open file
  13503.  
  13504.    SYNTAX  FILEATTR(filenumber,attribute)
  13505.  
  13506.  
  13507.  FILES Statement
  13508.  
  13509.    Prints the names of files residing on the specified disk
  13510.  
  13511.    SYNTAX  FILES[[filespec]]
  13512.  
  13513.  
  13514.  FIX Function
  13515.  
  13516.    Returns the truncated integer part of x
  13517.  
  13518.    SYNTAX  FIX(x)
  13519.  
  13520.  
  13521.  FOR...NEXT Statement
  13522.  
  13523.    Repeats a group of instructions a specified number of times
  13524.  
  13525.    SYNTAX  FOR counter = start TO end [[STEP increment]]
  13526.            .
  13527.            .
  13528.            .
  13529.            NEXT[[counter[[,counter...]]]]
  13530.  
  13531.  
  13532.  FRE Function
  13533.  
  13534.    Returns the amount of available memory
  13535.  
  13536.    SYNTAX 1  FRE(numeric-expression)
  13537.  
  13538.    SYNTAX 2  FRE(stringexpression)
  13539.  
  13540.  
  13541.  FREEFILE Function
  13542.  
  13543.    Returns the next free BASIC file number
  13544.  
  13545.    SYNTAX  FREEFILE
  13546.  
  13547.  
  13548.  FUNCTION Statement
  13549.  
  13550.    Declares the name, the parameters, and the code that form the body of a
  13551.    FUNCTION procedure
  13552.  
  13553.    SYNTAX  FUNCTION name [[(parameter-list)]][[STATIC]]
  13554.            .
  13555.            .
  13556.            .
  13557.            name = expression
  13558.            .
  13559.            .
  13560.            .
  13561.            END FUNCTION
  13562.  
  13563.  
  13564.  GET Statement──File I/O
  13565.  
  13566.    Reads from a disk file into a random-access buffer or variable
  13567.  
  13568.    SYNTAX  GET[[#]]filenumber[[,[[recordnumber]][[,variable]]]]
  13569.  
  13570.  
  13571.  GET Statement──Graphics
  13572.  
  13573.    Stores graphic images from the screen
  13574.  
  13575.    SYNTAX  GET[[STEP]](x1,y1) -[[STEP]](x2,y2),arrayname[[(indices)]]
  13576.  
  13577.  
  13578.  GOSUB...RETURN Statements
  13579.  
  13580.    Branches to, and returns from, a subroutine
  13581.  
  13582.    SYNTAX  GOSUB{linelabel1| linenumber1 }
  13583.            .
  13584.            .
  13585.            .
  13586.            RETURN[[linelabel2| linenumber2 ]]
  13587.  
  13588.  
  13589.  GOTO Statement
  13590.  
  13591.    Branches unconditionally to the specified line
  13592.  
  13593.    SYNTAX  GOTO{linelabel| linenumber}
  13594.  
  13595.  
  13596.  HEX$ Function
  13597.  
  13598.    Returns a string that represents the hexadecimal value of the decimal
  13599.    argument expression
  13600.  
  13601.    SYNTAX  HEX$(expression)
  13602.  
  13603.  
  13604.  IF...THEN...ELSE Statements
  13605.  
  13606.    Allows conditional execution, based on the evaluation of a Boolean
  13607.    expression
  13608.  
  13609.    SYNTAX 1 (SINGLE LINE)  IF booleanexpression THEN thenpart [[ELSE
  13610.                            elsepart]]
  13611.  
  13612.    SYNTAX 2 (BLOCK)   IF booleanexpression1 THEN
  13613.                            [[statementblock-1]]
  13614.                       [[ELSEIF booleanexpression2 THEN
  13615.                            [[statementblock-2]]]]
  13616.                       .
  13617.                       .
  13618.                       .
  13619.                       [[ELSE
  13620.                            [[statement-blockn]]]]
  13621.                       END IF
  13622.  
  13623.  
  13624.  INKEY$ Function
  13625.  
  13626.    Reads a character from the keyboard
  13627.  
  13628.    SYNTAX  INKEY$
  13629.  
  13630.  
  13631.  INP Function
  13632.  
  13633.    Returns the byte read from an I/O port
  13634.  
  13635.    SYNTAX  INP(port)
  13636.  
  13637.  
  13638.  INPUT$ Function
  13639.  
  13640.    Returns a string of characters read from the specified file
  13641.  
  13642.    SYNTAX  INPUT$(n[[,[[#]]filenumber]])
  13643.  
  13644.  
  13645.  INPUT Statement
  13646.  
  13647.    Allows input from the keyboard during program execution
  13648.  
  13649.    SYNTAX  INPUT[[;]][["promptstring"{; | ,}]] variablelist
  13650.  
  13651.  
  13652.  INPUT # Statement
  13653.  
  13654.    Reads data items from a sequential device or file and assigns them to
  13655.    variables
  13656.  
  13657.    SYNTAX  INPUT # filenumber, variablelist
  13658.  
  13659.  
  13660.  INSTR Function
  13661.  
  13662.    Returns the character position of the first occurrence of a string in
  13663.    another string
  13664.  
  13665.    SYNTAX  INSTR([[start,]]stringexpression1,stringexpression2)
  13666.  
  13667.  
  13668.  INT Function
  13669.  
  13670.    Returns the largest integer less than or equal to numeric-expression
  13671.  
  13672.    SYNTAX  INT(numeric-expression)
  13673.  
  13674.  
  13675.  IOCTL$ Function
  13676.  
  13677.    Receives a control data string from a device driver
  13678.  
  13679.    SYNTAX  IOCTL$ ([[#]]filenumber)
  13680.  
  13681.  
  13682.  IOCTL Statement
  13683.  
  13684.    Transmits a control data string to a device driver
  13685.  
  13686.    SYNTAX  IOCTL[[#]]filenumber, string
  13687.  
  13688.  
  13689.  KEY Statements
  13690.  
  13691.    Assign soft-key string values to function keys, then display the values
  13692.    and enable or disable the FUNCTION key display line
  13693.  
  13694.    SYNTAX  KEY n, stringexpression
  13695.            KEY LIST
  13696.            KEY ON
  13697.            KEY OFF
  13698.  
  13699.  
  13700.  KEY(n) Statements
  13701.  
  13702.    Start or stop trapping of specified keys
  13703.  
  13704.    SYNTAX  KEY(n) ON
  13705.            KEY(n) OFF
  13706.            KEY(n) STOP
  13707.  
  13708.  
  13709.  KILL Statement
  13710.  
  13711.    Deletes a file from disk
  13712.  
  13713.    SYNTAX  KILL filespec
  13714.  
  13715.  
  13716.  LBOUND Function
  13717.  
  13718.    Returns the lower bound (smallest available subscript) for the indicated
  13719.    dimension of an array
  13720.  
  13721.    SYNTAX  LBOUND(array[[,dimension]])
  13722.  
  13723.  
  13724.  LCASE$ Function
  13725.  
  13726.    Returns a string expression with all letters in lower-case
  13727.  
  13728.    SYNTAX  LCASE$ (stringexpression)
  13729.  
  13730.  
  13731.  LEFT$ Function
  13732.  
  13733.    Returns a string consisting of the leftmost n characters of a string
  13734.  
  13735.    SYNTAX  LEFT$(stringexpression,n)
  13736.  
  13737.  
  13738.  LEN Function
  13739.  
  13740.    Returns the number of characters in a string or the number of bytes
  13741.    required by a variable
  13742.  
  13743.    SYNTAX  LEN(stringexpression)
  13744.            LEN(variable)
  13745.  
  13746.  
  13747.  LET Statement
  13748.  
  13749.    Assigns the value of an expression to a variable
  13750.  
  13751.    SYNTAX  [[LET]]variable=expression
  13752.  
  13753.  
  13754.  LINE Statement
  13755.  
  13756.    Draws a line or box on the screen
  13757.  
  13758.    SYNTAX  LINE[[[[STEP]] (x1,y1)]] -[[STEP]]
  13759.            (x2,y2)[[,[[color]][[,[[B[[F]]]][[,style]]]]]]
  13760.  
  13761.  
  13762.  LINE INPUT Statement
  13763.  
  13764.    Inputs an entire line (up to 255 characters) to a string variable, without
  13765.    the use of delimiters
  13766.  
  13767.    SYNTAX  LINE INPUT[[;]] [["promptstring";]] stringvariable
  13768.  
  13769.  
  13770.  LINE INPUT # Statement
  13771.  
  13772.    Reads an entire line without delimiters from a sequential file to a string
  13773.    variable
  13774.  
  13775.    SYNTAX  LINE INPUT #filenumber,stringvariable
  13776.  
  13777.  
  13778.  LOC Function
  13779.  
  13780.    Returns the current position within the file
  13781.  
  13782.    SYNTAX  LOC(filenumber)
  13783.  
  13784.  
  13785.  LOCATE Statement
  13786.  
  13787.    Moves the cursor to the specified position
  13788.  
  13789.    SYNTAX  LOCATE[[row]][[,[[column]][[,[[cursor]][[,[[start,stop]]]]]]]]
  13790.  
  13791.  
  13792.  LOCK...UNLOCK Statement
  13793.  
  13794.    Controls access by other processes to all or part of an opened file
  13795.  
  13796.    SYNTAX  LOCK[[#]] filenumber [[,{record | [[start]] TO end}]]
  13797.            .
  13798.            .
  13799.            .
  13800.            UNLOCK[[#]] filenumber [[,{record | [[start]] TO end}]]
  13801.  
  13802.  
  13803.  LOF Function
  13804.  
  13805.    Returns the length of the named file in bytes
  13806.  
  13807.    SYNTAX  LOF(filenumber)
  13808.  
  13809.  
  13810.  LOG Function
  13811.  
  13812.    Returns the natural logarithm of a numeric expression
  13813.  
  13814.    SYNTAX  LOG(n)
  13815.  
  13816.  
  13817.  LPOS Function
  13818.  
  13819.    Returns the current position of the line printer's print head within the
  13820.    printer buffer
  13821.  
  13822.    SYNTAX  LPOS(n)
  13823.  
  13824.  
  13825.  LPRINT, LPRINT USING Statements
  13826.  
  13827.    Prints data on the printer LPT1:
  13828.  
  13829.    SYNTAX 1  LPRINT[[expressionlist]] [[{;|,}]]
  13830.  
  13831.    SYNTAX 2  LPRINT USING formatstring; expression-list [[{;|,}]]
  13832.  
  13833.  
  13834.  LSET Statement
  13835.  
  13836.    Moves data from memory to a random-access file buffer (in preparation for
  13837.    a PUT statement), copies one record variable to another, or left-justifies
  13838.    the value of a string in a string variable
  13839.  
  13840.    SYNTAX
  13841.            LSET{stringvariable=stringexpression|stringexpression1=stringexpre
  13842.            ssion2}
  13843.  
  13844.  
  13845.  LTRIM$ Function
  13846.  
  13847.    Returns a copy of a string with leading spaces removed
  13848.  
  13849.    SYNTAX  LTRIM$(stringexpression)
  13850.  
  13851.  
  13852.  MID$ Function
  13853.  
  13854.    Returns a substring of a string
  13855.  
  13856.    SYNTAX  MID$(stringexpression,start[[,length]])
  13857.  
  13858.  
  13859.  MID$ Statement
  13860.  
  13861.    Replaces a portion of a string variable with another string
  13862.  
  13863.    SYNTAX  MID$(stringvariable,start[[,length]])=stringexpression
  13864.  
  13865.  
  13866.  MKD$, MKI$, MKL$, MKS$ Functions
  13867.  
  13868.    Converts numeric values to string values
  13869.  
  13870.    SYNTAX  MKI$(integerexpression)
  13871.            MKS$(single-precision-expression)
  13872.            MKL$(long-integer-expression)
  13873.            MKD$(double-precision-expression)
  13874.  
  13875.  
  13876.  MKDIR Statement
  13877.  
  13878.    Creates a new directory
  13879.  
  13880.    SYNTAX  MKDIR pathname
  13881.  
  13882.  
  13883.  MKSMBF$, MKDMBF$ Functions
  13884.  
  13885.    Converts an IEEE-format number to a string containing a Microsoft Binary
  13886.    format number
  13887.  
  13888.    SYNTAX  MKSMBF$(single-precision-expression)
  13889.            MKDMBF$(double-precision-expression)
  13890.  
  13891.  
  13892.  NAME Statement
  13893.  
  13894.    Changes the name of a disk file or directory
  13895.  
  13896.    SYNTAX  NAME oldfilename AS newfilename
  13897.  
  13898.  
  13899.  OCT$ Function
  13900.  
  13901.    Returns a string representing the octal value of the numeric argument
  13902.  
  13903.    SYNTAX  OCT$(numeric-expression)
  13904.  
  13905.  
  13906.  ON ERROR Statement
  13907.  
  13908.    Enables error handling and specifies the first line of the error-handling
  13909.    routine
  13910.  
  13911.    SYNTAX  ON ERROR GOTO line
  13912.  
  13913.  
  13914.  ON event Statements
  13915.  
  13916.    Indicates the first line of an event-trapping subroutine
  13917.  
  13918.    SYNTAX  ON event GOSUB{linenumber | linelabel }
  13919.  
  13920.  
  13921.  ON UEVENT GOSUB Statement
  13922.  
  13923.    Defines the event-handler for a user-defined event
  13924.  
  13925.    SYNTAX  ON UEVENT GOSUB { linenumber| linelabel }
  13926.  
  13927.  
  13928.  ON...GOSUB, ON...GOTO Statements
  13929.  
  13930.    Branches to one of several specified lines, depending on the value of an
  13931.    expression
  13932.  
  13933.    SYNTAX 1  ON expression GOSUB{line-number-list | line-label-list }
  13934.  
  13935.    SYNTAX 2  ON expression GOTO{line-number-list | line-label-list }
  13936.  
  13937.  
  13938.  OPEN Statement
  13939.  
  13940.    Enables I/O to a file or device
  13941.  
  13942.    SYNTAX 1  OPEN file[[FOR mode1]] [[ACCESS access]] [[lock]] AS[[#]]
  13943.              filenum[[LEN=reclen]]
  13944.  
  13945.    SYNTAX 2  OPEN mode2,[[#]]filenum, file [[,reclen]]
  13946.  
  13947.  
  13948.  OPEN COM Statement
  13949.  
  13950.    Opens and initializes a communications channel for I/O
  13951.  
  13952.    SYNTAX  OPEN "COMn: optlist1 optlist2" [[FOR mode]] AS[[#]]filenum
  13953.            [[LEN=reclen]]
  13954.  
  13955.  
  13956.  OPTION BASE Statement
  13957.  
  13958.    Declares the default lower bound for array subscripts
  13959.  
  13960.    SYNTAX  OPTION BASE n
  13961.  
  13962.  
  13963.  OUT Statement
  13964.  
  13965.    Sends a byte to a machine I/O port
  13966.  
  13967.    SYNTAX  OUT port, data
  13968.  
  13969.  
  13970.  PAINT Statement
  13971.  
  13972.    Fills a graphics area with the color or pattern specified
  13973.  
  13974.    SYNTAX  PAINT[[STEP]] (x,y)[[,[[paint]] [[,[[bordercolor]]
  13975.            [[,background]]]]]]
  13976.  
  13977.  
  13978.  PALETTE, PALETTE USING Statements
  13979.  
  13980.    Changes one or more of the colors in the palette
  13981.  
  13982.    SYNTAX  PALETTE[[attribute,color]]
  13983.            PALETTE USING array-name [[(array-index)]]
  13984.  
  13985.  
  13986.  PCOPY Statement
  13987.  
  13988.    Copies one screen page to another
  13989.  
  13990.    SYNTAX  PCOPY sourcepage, destinationpage
  13991.  
  13992.  
  13993.  PEEK Function
  13994.  
  13995.    Returns the byte stored at a specified memory location
  13996.  
  13997.    SYNTAX  PEEK(address)
  13998.  
  13999.  
  14000.  PEN Function
  14001.  
  14002.    Reads the lightpen coordinates
  14003.  
  14004.    SYNTAX  PEN(n)
  14005.  
  14006.  
  14007.  PEN ON, OFF, and STOP Statements
  14008.  
  14009.    Enables, disables, or suspends lightpen event trapping
  14010.  
  14011.    SYNTAX  PEN ON
  14012.            PEN OFF
  14013.            PEN STOP
  14014.  
  14015.  
  14016.  PLAY Function
  14017.  
  14018.    Returns the number of notes currently in the background-music queue
  14019.  
  14020.    SYNTAX  PLAY (n)
  14021.  
  14022.  
  14023.  PLAY Statement
  14024.  
  14025.    Plays music as specified by a string
  14026.  
  14027.    SYNTAX  PLAY commandstring
  14028.  
  14029.  
  14030.  PLAY ON, OFF, and STOP Statements
  14031.  
  14032.    PLAY ON enables play event trapping, PLAY OFF disables play event
  14033.    trapping, and PLAY STOP suspends play event trapping.
  14034.  
  14035.    SYNTAX  PLAY ON
  14036.            PLAY OFF
  14037.            PLAY STOP
  14038.  
  14039.  
  14040.  PMAP Function
  14041.  
  14042.    Maps view-coordinate expressions to physical locations, or maps physical
  14043.    expressions to a view-coordinate location
  14044.  
  14045.    SYNTAX  PMAP (expression, function)
  14046.  
  14047.  
  14048.  POINT Function
  14049.  
  14050.    Reads the color number of a pixel from the screen or returns the pixel's
  14051.    coordinates
  14052.  
  14053.    SYNTAX  POINT (x,y)
  14054.            POINT (number)
  14055.  
  14056.  
  14057.  POKE Statement
  14058.  
  14059.    Writes a byte into a memory location
  14060.  
  14061.    SYNTAX  POKE address,byte
  14062.  
  14063.  
  14064.  POS Function
  14065.  
  14066.    Returns the current horizontal position of the cursor
  14067.  
  14068.    SYNTAX  POS(0)
  14069.  
  14070.  
  14071.  PRESET Statement
  14072.  
  14073.    Draws a specified point on the screen
  14074.  
  14075.    SYNTAX  PRESET[[STEP]](xcoordinate,ycoordinate) [[,color]]
  14076.  
  14077.  
  14078.  PRINT Statement
  14079.  
  14080.    Outputs data on the screen
  14081.  
  14082.    SYNTAX  PRINT[[expressionlist]] [[{,| ;}]]
  14083.  
  14084.  
  14085.  PRINT #, PRINT # USING Statements
  14086.  
  14087.    Writes data to a sequential file
  14088.  
  14089.    SYNTAX  PRINT #filenumber,[[USING stringexpression;]] expressionlist [[{,
  14090.            | ;}]]
  14091.  
  14092.  
  14093.  PRINT USING Statement
  14094.  
  14095.    Prints strings or numbers using a specified format
  14096.  
  14097.    SYNTAX  PRINT USING formatstring; expressionlist [[{,| ;}]]
  14098.  
  14099.  
  14100.  PSET Statement
  14101.  
  14102.    Draws a point on the screen
  14103.  
  14104.    SYNTAX  PSET[[STEP]](xcoordinate,ycoordinate) [[,color]]
  14105.  
  14106.  
  14107.  PUT Statement──File I/O
  14108.  
  14109.    Writes from a variable or a random-access buffer to a file
  14110.  
  14111.    SYNTAX  PUT[[#]]filenumber[[,[[recordnumber]][[,variable]]]]
  14112.            PUT[[#]]filenumber[[,{recordnumber|recordnumber,
  14113.            variable|,variable}]]
  14114.  
  14115.  
  14116.  PUT Statement──Graphics
  14117.  
  14118.    Places a graphic image obtained by a GET statement onto the screen
  14119.  
  14120.    SYNTAX  PUT[[STEP]] (x,y), arrayname[[(indices)]] [[,actionverb]]
  14121.  
  14122.  
  14123.  RANDOMIZE Statement
  14124.  
  14125.    Initializes (reseeds) the random-number generator
  14126.  
  14127.    SYNTAX  RANDOMIZE[[expression]]
  14128.  
  14129.  
  14130.  READ Statement
  14131.  
  14132.    Reads values from a DATA statement and assigns the values to variables
  14133.  
  14134.    SYNTAX  READ variablelist
  14135.  
  14136.  
  14137.  REDIM Statement
  14138.  
  14139.    Changes the space allocated to an array that has been declared $DYNAMIC
  14140.  
  14141.    SYNTAX  REDIM[[SHARED]] variable(subscripts)[[AS type]]
  14142.            [[,variable(subscripts)[[AS
  14143.            type]]]]...
  14144.  
  14145.  
  14146.  REM Statement
  14147.  
  14148.    Allows explanatory remarks to be inserted in a program
  14149.  
  14150.    SYNTAX 1  REM remark
  14151.  
  14152.    SYNTAX 2  ' remark
  14153.  
  14154.  
  14155.  RESET Statement
  14156.  
  14157.    Closes all disk files
  14158.  
  14159.    SYNTAX  RESET
  14160.  
  14161.  
  14162.  RESTORE Statement
  14163.  
  14164.    Allows DATA statements to be reread from a specified line
  14165.  
  14166.    SYNTAX  RESTORE[[{linenumber | linelabel }]]
  14167.  
  14168.  
  14169.  RESUME Statement
  14170.  
  14171.    Continues program execution after an error-trapping routine has been
  14172.    invoked
  14173.  
  14174.    SYNTAX  RESUME[[0]]
  14175.            RESUME NEXT
  14176.            RESUME { linenumber| linelabel }
  14177.  
  14178.  
  14179.  RETURN Statement
  14180.  
  14181.    Returns control from a subroutine
  14182.  
  14183.    SYNTAX  RETURN[[{linenumber | linelabel }]]
  14184.  
  14185.  
  14186.  RIGHT$ Function
  14187.  
  14188.    Returns the rightmost n characters of a string
  14189.  
  14190.    SYNTAX  RIGHT$(stringexpression,n)
  14191.  
  14192.  
  14193.  RMDIR Statement
  14194.  
  14195.    Removes an existing directory
  14196.  
  14197.    SYNTAX  RMDIR pathname
  14198.  
  14199.  
  14200.  RND Function
  14201.  
  14202.    Returns a single-precision random number between 0 and 1
  14203.  
  14204.    SYNTAX  RND[[(n)]]
  14205.  
  14206.  
  14207.  RSET Statement
  14208.  
  14209.    Moves data from memory to a random-access file buffer (in preparation for
  14210.    a PUT statement) or right-justifies the value of a string in a string
  14211.    variable
  14212.  
  14213.    SYNTAX  RSET stringvariable=stringexpression
  14214.  
  14215.  
  14216.  RTRIM$ Function
  14217.  
  14218.    Returns a string with trailing (right-hand) spaces removed
  14219.  
  14220.    SYNTAX  RTRIM$(stringexpression)
  14221.  
  14222.  
  14223.  RUN Statement
  14224.  
  14225.    Restarts the program currently in memory or executes a specified program
  14226.  
  14227.    SYNTAX  RUN[[{ linenumber | commandline }]]
  14228.  
  14229.  
  14230.  SADD Function
  14231.  
  14232.    Returns the address of the specified string expression
  14233.  
  14234.    SYNTAX  SADD(stringvariable)
  14235.  
  14236.  
  14237.  SCREEN Function
  14238.  
  14239.    Reads a character's ASCII value or its color from a specified screen
  14240.    location
  14241.  
  14242.    SYNTAX  SCREEN(row,column[[,colorflag]])
  14243.  
  14244.  
  14245.  SCREEN Statement
  14246.  
  14247.    Sets the specifications for the display screen
  14248.  
  14249.    SYNTAX  SCREEN[[mode]] [[,[[colorswitch]] ]][[,[[apage]] ]][[,[[vpage]]]]
  14250.  
  14251.  
  14252.  SEEK Function
  14253.  
  14254.    Returns the current file position
  14255.  
  14256.    SYNTAX  SEEK(filenumber)
  14257.  
  14258.  
  14259.  SEEK Statement
  14260.  
  14261.    Sets the position in a file for the next read or write
  14262.  
  14263.    SYNTAX  SEEK[[#]]filenumber,position
  14264.  
  14265.  
  14266.  SELECT CASE Statement
  14267.  
  14268.    Executes one of several statement blocks depending on the value of an
  14269.    expression
  14270.  
  14271.    SYNTAX  SELECT CASE testexpression
  14272.            CASE expressionlist1
  14273.                 [[statementblock-1]]
  14274.            [[CASE expressionlist2
  14275.                 [[statementblock-2]]]]
  14276.            .
  14277.            .
  14278.            .
  14279.            [[CASE ELSE
  14280.                 [[statementblock-n]]]]
  14281.            END SELECT
  14282.  
  14283.  
  14284.  SETMEM Function
  14285.  
  14286.    Changes the amount of memory used by the far heap──the area where far
  14287.    objects and internal tables are stored
  14288.  
  14289.    SYNTAX  SETMEM(numeric-expression)
  14290.  
  14291.  
  14292.  SGN Function
  14293.  
  14294.    Indicates the sign of a numeric expression
  14295.  
  14296.    SYNTAX  SGN(numeric-expression)
  14297.  
  14298.  
  14299.  SHARED Statement
  14300.  
  14301.    Gives a SUB or FUNCTION procedure access to variables declared at the
  14302.    module level without passing them as parameters
  14303.  
  14304.    SYNTAX  SHARED variable [[AS type]] [[,variable [[AS type]]]]...
  14305.  
  14306.  
  14307.  SHELL Statement
  14308.  
  14309.    Exits the BASIC program, runs a .COM, .EXE, or .BAT program or a DOS
  14310.    command, and returns to the program at the line following the SHELL
  14311.    statement
  14312.  
  14313.    SYNTAX  SHELL[[commandstring]]
  14314.  
  14315.  
  14316.  SIN Function
  14317.  
  14318.    Returns the sine of the angle x, where x is in radians
  14319.  
  14320.    SYNTAX  SIN(x)
  14321.  
  14322.  
  14323.  SLEEP Statement
  14324.  
  14325.    Suspends execution of the calling program
  14326.  
  14327.    SYNTAX  SLEEP[[ seconds ]]
  14328.  
  14329.  
  14330.  SOUND Statement
  14331.  
  14332.    Generates sound through the speaker
  14333.  
  14334.    SYNTAX  SOUND frequency,duration
  14335.  
  14336.  
  14337.  SPACE$ Function
  14338.  
  14339.    Returns a string of spaces of length n
  14340.  
  14341.    SYNTAX  SPACE$(n)
  14342.  
  14343.  
  14344.  SPC Function
  14345.  
  14346.    Skips n spaces in a PRINT statement
  14347.  
  14348.    SYNTAX  SPC(n)
  14349.  
  14350.  
  14351.  SQR Function
  14352.  
  14353.    Returns the square root of n
  14354.  
  14355.    SYNTAX  SQR(n)
  14356.  
  14357.  
  14358.  STATIC Statement
  14359.  
  14360.    Makes simple variables or arrays local to either a DEF FN function, a
  14361.    FUNCTION, or a SUB and preserves values between calls
  14362.  
  14363.    SYNTAX  STATIC variablelist
  14364.  
  14365.  
  14366.  STICK Function
  14367.  
  14368.    Returns the x and y coordinates of the two joysticks
  14369.  
  14370.    SYNTAX  STICK(n)
  14371.  
  14372.  
  14373.  STOP Statement
  14374.  
  14375.    Terminates the program
  14376.  
  14377.    SYNTAX  STOP
  14378.  
  14379.  
  14380.  STR$ Function
  14381.  
  14382.    Returns a string representation of the value of a numeric expression
  14383.  
  14384.    SYNTAX  STR$(numeric-expression)
  14385.  
  14386.  
  14387.  STRIG Function and Statement
  14388.  
  14389.    Returns the status of a specified joystick trigger
  14390.  
  14391.    SYNTAX 1 (FUNCTION)  STRIG(n)
  14392.  
  14393.    SYNTAX 2 (STATEMENT)  STRIG{ON| OFF}
  14394.  
  14395.  
  14396.  STRIG ON, OFF, and STOP Statements
  14397.  
  14398.    Enable, disable, or inhibit trapping of joystick activity
  14399.  
  14400.    SYNTAX  STRIG(n) ON
  14401.            STRIG(n) OFF
  14402.            STRIG(n) STOP
  14403.  
  14404.  
  14405.  STRING$ Function
  14406.  
  14407.    Returns a string whose characters all have a given ASCII code or whose
  14408.    characters are all the first character of a string expression
  14409.  
  14410.    SYNTAX  STRING$(m,n)
  14411.            STRING$(m,stringexpression)
  14412.  
  14413.  
  14414.  SUB Statements
  14415.  
  14416.    Marks the beginning and end of a subprogram
  14417.  
  14418.    SYNTAX  SUB globalname[[(parameterlist)]] [[STATIC]]
  14419.            .
  14420.            .
  14421.            .
  14422.            [[EXIT SUB]]
  14423.            .
  14424.            .
  14425.            .
  14426.            END SUB
  14427.  
  14428.  
  14429.  SWAP Statement
  14430.  
  14431.    Exchanges the values of two variables
  14432.  
  14433.    SYNTAX  SWAP variable1,variable2
  14434.  
  14435.  
  14436.  SYSTEM Statement
  14437.  
  14438.    Closes all open files and returns control to the operating system
  14439.  
  14440.    SYNTAX  SYSTEM
  14441.  
  14442.  
  14443.  TAB Function
  14444.  
  14445.    Moves the print position
  14446.  
  14447.    SYNTAX  TAB(column)
  14448.  
  14449.  
  14450.  TAN Function
  14451.  
  14452.    Returns the tangent of the angle x, where x is in radians
  14453.  
  14454.    SYNTAX  TAN(x)
  14455.  
  14456.  
  14457.  TIME$ Function
  14458.  
  14459.    Returns the current time from the operating system
  14460.  
  14461.    SYNTAX  TIME$
  14462.  
  14463.  
  14464.  TIME$ Statement
  14465.  
  14466.    Sets the time
  14467.  
  14468.    SYNTAX  TIME$=stringexpression
  14469.  
  14470.  
  14471.  TIMER Function
  14472.  
  14473.    Returns the number of seconds elapsed since midnight
  14474.  
  14475.    SYNTAX  TIMER
  14476.  
  14477.  
  14478.  TIMER ON, OFF, and STOP Statements
  14479.  
  14480.    Enables, disables, or inhibits timer event trapping
  14481.  
  14482.    SYNTAX  TIMER ON
  14483.            TIMER OFF
  14484.            TIMER STOP
  14485.  
  14486.  
  14487.  TRON/TROFF Statements
  14488.  
  14489.    Traces the execution of program statements
  14490.  
  14491.    SYNTAX  TRON
  14492.            TROFF
  14493.  
  14494.  
  14495.  TYPE Statement
  14496.  
  14497.    Defines a data type containing one or more elements
  14498.  
  14499.    SYNTAX  TYPE usertype
  14500.               elementname AS    typename
  14501.               elementname AS    typename
  14502.               .
  14503.               .
  14504.               .
  14505.            END TYPE
  14506.  
  14507.  
  14508.  UBOUND Function
  14509.  
  14510.    Returns the upper bound (largest available subscript) for the indicated
  14511.    dimension of an array
  14512.  
  14513.    SYNTAX  UBOUND(array[[,dimension]])
  14514.  
  14515.  
  14516.  UCASE$ Function
  14517.  
  14518.    Returns a string expression with all letters in uppercase
  14519.  
  14520.    SYNTAX  UCASE$ (stringexpression)
  14521.  
  14522.  
  14523.  UEVENT Statement
  14524.  
  14525.    Enables, disables, or suspends event trapping for a user-defined event
  14526.  
  14527.    SYNTAX  UEVENT ON
  14528.            UEVENT OFF
  14529.            UEVENT STOP
  14530.  
  14531.  
  14532.  UNLOCK Statement
  14533.  
  14534.    Releases locks applied to parts of a file
  14535.  
  14536.    SYNTAX  UNLOCK[[#]] filenumber [[,{record | [[start]] TO end}]]
  14537.  
  14538.  
  14539.  VAL Function
  14540.  
  14541.    Returns the numeric value of a string of digits
  14542.  
  14543.    SYNTAX  VAL(stringexpression)
  14544.  
  14545.  
  14546.  VARPTR, VARSEG Functions
  14547.  
  14548.    Return the address of a variable
  14549.  
  14550.    SYNTAX  VARPTR(variablename)
  14551.            VARSEG(variablename)
  14552.  
  14553.  
  14554.  VARPTR$ Function
  14555.  
  14556.    Returns a string representation of a variable's address for use in DRAW
  14557.    and PLAY statements
  14558.  
  14559.    SYNTAX  VARPTR$(variablename)
  14560.  
  14561.  
  14562.  VIEW Statement
  14563.  
  14564.    Defines screen limits for graphics output
  14565.  
  14566.    SYNTAX  VIEW[[[[SCREEN]] (x1,y1)-(x2,y2)[[,[[color]] [[,border]]]]]]
  14567.  
  14568.  
  14569.  VIEW PRINT Statement
  14570.  
  14571.    Sets the boundaries of the screen text viewport
  14572.  
  14573.    SYNTAX  VIEW PRINT[[topline TO bottomline]]
  14574.  
  14575.  
  14576.  WAIT Statement
  14577.  
  14578.    Suspends program execution while monitoring the status of a machine input
  14579.    port
  14580.  
  14581.    SYNTAX  WAIT portnumber,and-expression[[,xor-expression]]
  14582.  
  14583.  
  14584.  WHILE...WEND Statement
  14585.  
  14586.    Executes a series of statements in a loop, as long as a given condition is
  14587.    true
  14588.  
  14589.    SYNTAX  WHILE condition
  14590.            .
  14591.            .
  14592.            .
  14593.            [[statements]]
  14594.            .
  14595.            .
  14596.            .
  14597.            WEND
  14598.  
  14599.  
  14600.  WIDTH Statement
  14601.  
  14602.    Assigns an output-line width to a file or device or changes the number of
  14603.    columns and lines displayed on the screen
  14604.  
  14605.    SYNTAX  WIDTH[[columns]][[,lines]]
  14606.            WIDTH{# filenumber | device} , width
  14607.            WIDTH LPRINT width
  14608.  
  14609.  
  14610.  WINDOW Statement
  14611.  
  14612.    Defines the logical dimensions of the current viewport
  14613.  
  14614.    SYNTAX  WINDOW[[[[SCREEN]] (x1,y1)-(x2,y2)]]
  14615.  
  14616.  
  14617.  WRITE Statement
  14618.  
  14619.    Sends data to the screen
  14620.  
  14621.    SYNTAX  WRITE[[expressionlist]]
  14622.  
  14623.  
  14624.  WRITE # Statement
  14625.  
  14626.    Writes data to a sequential file
  14627.  
  14628.    SYNTAX  WRITE #filenumber,expressionlist
  14629.  
  14630.  
  14631.  
  14632.  ────────────────────────────────────────────────────────────────────────────
  14633.  Chapter 9  Quick-Reference Tables
  14634.  
  14635.    Each section in this chapter summarizes a group of statements or functions
  14636.    that you typically use together. Each group is presented in a table, which
  14637.    lists the type of task performed (for example, looping or searching), the
  14638.    statement or function name, and the statement action.
  14639.  
  14640.    The following topics are summarized in tabular form:
  14641.  
  14642.    ■ Control-flow statements
  14643.  
  14644.    ■ Statements used in BASIC procedures
  14645.  
  14646.    ■ Standard I/O statements
  14647.  
  14648.    ■ File I/O statements
  14649.  
  14650.    ■ String-processing statements and functions
  14651.  
  14652.    ■ Graphics statements and functions
  14653.  
  14654.    ■ Trapping statements and functions
  14655.  
  14656.    You can use these tables both as a reference guide to what each statement
  14657.    or function does and as a way to identify related statements.
  14658.  
  14659.  
  14660.  9.1  Summary of Control-Flow Statements
  14661.  
  14662.    Table 9.1 lists the BASIC statements used to control the flow of a
  14663.    program's execution.
  14664.  
  14665.    Table 9.1  Statements Used in Looping and Decision-Making
  14666. ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
  14667.    Task                 Statement            Action
  14668.    ──────────────────────────────────────────────────────────────────────────
  14669.    Looping              FOR...NEXT           Repeats statements between FOR
  14670.                                              and NEXT a specific number of
  14671.                                              times.
  14672.  
  14673.                         EXIT FOR             Provides an alternative way to
  14674.                                              exit a FOR...NEXT loop.
  14675.  
  14676.                         DO...LOOP            Repeats statements between DO
  14677.                                              and LOOP, either until a given
  14678.                                              condition is true (DO...LOOP
  14679.                                              UNTIL condition), or while a
  14680.                                              given condition is true
  14681.    Task                 Statement            Action
  14682.    ──────────────────────────────────────────────────────────────────────────
  14683.                                             given condition is true
  14684.                                              (DO...LOOP WHILE condition).
  14685.  
  14686.                         EXIT DO              Provides an alternative way to
  14687.                                              exit a DO...LOOP loop.
  14688.  
  14689.                         WHILE...WEND         Repeats statements between WHILE
  14690.                                              and WEND while a given condition
  14691.                                              is true (similar to DO WHILE
  14692.                                              condition...LOOP).
  14693.  
  14694.    Making decisions     IF...THEN...ELSE     Conditionally executes or
  14695.                                              branches to different
  14696.                                              statements.
  14697.  
  14698.                         SELECT CASE          Conditionally executes different
  14699.                                              statements.
  14700.    ──────────────────────────────────────────────────────────────────────────
  14701.  
  14702.    Task                 Statement            Action
  14703.    ──────────────────────────────────────────────────────────────────────────
  14704. 
  14705.  
  14706.  
  14707.  9.2  Summary of Statements Used in BASIC Procedures
  14708.  
  14709.    Table 9.2 lists the statements used in BASIC to define, declare, call,
  14710.    and pass arguments to BASIC procedures. Table 9.2 also lists the
  14711.    statements used to share variables among procedures, modules, and separate
  14712.    programs in a chain.
  14713.  
  14714.    Table 9.2  Statements Used in Procedures
  14715. ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
  14716.    Task                 Statement            Action
  14717.    ──────────────────────────────────────────────────────────────────────────
  14718.    Defining a procedure FUNCTION...END       Mark the beginning and end,
  14719.                         FUNCTION             respectively, of a FUNCTION
  14720.                                              procedure.
  14721.  
  14722.                         SUB...END SUB        Mark the beginning and end,
  14723.    Task                 Statement            Action
  14724.    ──────────────────────────────────────────────────────────────────────────
  14725.                        SUB...END SUB        Mark the beginning and end,
  14726.                                              respectively, of a SUB
  14727.                                              procedure.
  14728.  
  14729.    Calling a procedure  CALL                 Transfers control to a BASIC SUB
  14730.                                              procedure, or to a procedure
  14731.                                              written in another programming
  14732.                                              language and compiled
  14733.                                              separately. (The CALL keyword is
  14734.                                              optional.)
  14735.  
  14736.    Exiting from a       EXIT FUNCTION        Provides another way to exit a
  14737.    procedure                                 FUNCTION procedure.
  14738.  
  14739.                         EXIT SUB             Provides an alternative way to
  14740.                                              exit a SUB procedure.
  14741.  
  14742.    Referencing a        DECLARE              Declares a FUNCTION or SUB and,
  14743.    procedure before it                       optionally, specifies the number
  14744.    Task                 Statement            Action
  14745.    ──────────────────────────────────────────────────────────────────────────
  14746.   procedure before it                       optionally, specifies the number
  14747.    is defined                                and type of its parameters.
  14748.  
  14749.    Sharing variables    COMMON               Shares variables among separate
  14750.    among modules,                            modules. When used with the
  14751.    procedures, or                            SHARED attribute, it shares
  14752.    programs                                  variables among different
  14753.                                              procedures in the same module.
  14754.                                              Also, passes variable values
  14755.                                              from current program to new
  14756.                                              program when control is
  14757.                                              transferred with the CHAIN
  14758.                                              statement.
  14759.  
  14760.                         SHARED               When used with the COMMON, DIM,
  14761.                                              or REDIM statement at the module
  14762.                                              level (for example, DIM SHARED),
  14763.                                              shares variables with every SUB
  14764.                                              or FUNCTION in a single module.
  14765.    Task                 Statement            Action
  14766.    ──────────────────────────────────────────────────────────────────────────
  14767.                                             or FUNCTION in a single module.
  14768.  
  14769.                                              When used by itself within a
  14770.                                              procedure, shares variables
  14771.                                              between that procedure and the
  14772.                                              module-level code.
  14773.  
  14774.    Preserving variable  STATIC               Forces variables to be local to
  14775.    values                                    a procedure or DEF FN function
  14776.                                              and preserves the value stored
  14777.                                              in the variable if the procedure
  14778.                                              or function is exited, then
  14779.                                              called again.
  14780.  
  14781.    Defining a multiline DEF FN...END DEF     Mark the beginning and end,
  14782.    function                                  respectively, of a multiline DEF
  14783.                                              FN function. (This is the old
  14784.                                              style for functions in BASIC──
  14785.                                              FUNCTION procedures provide a
  14786.    Task                 Statement            Action
  14787.    ──────────────────────────────────────────────────────────────────────────
  14788.                                             FUNCTION procedures provide a
  14789.                                              powerful alternative.)
  14790.  
  14791.    Exiting from a       EXIT DEF             Provides an alternative way to
  14792.    multiline function                        exit a multiline DEF FN
  14793.                                              function.
  14794.  
  14795.    Calling a BASIC      GOSUB                Transfers control to a specific
  14796.    subroutine                                line in a module. Control is
  14797.                                              returned from the subroutine to
  14798.                                              the line following the GOSUB
  14799.                                              statement with a RETURN
  14800.                                              statement. (This is the old
  14801.                                              style for subroutines in BASIC──
  14802.                                              SUB procedures provide a
  14803.                                              powerful alternative.)
  14804.  
  14805.    Transferring to      CHAIN                Transfers control from current
  14806.    another program                           program in memory to another
  14807.    Task                 Statement            Action
  14808.    ──────────────────────────────────────────────────────────────────────────
  14809.   another program                           program in memory to another
  14810.                                              program; use COMMON to pass
  14811.                                              variables to the new program.
  14812.    ──────────────────────────────────────────────────────────────────────────
  14813.  
  14814.  
  14815.  
  14816.  9.3  Summary of Standard I/O Statements
  14817.  
  14818.    Table 9.3 lists the statements and functions used in BASIC for standard
  14819.    I/O (typically, input from the keyboard and output to the screen).
  14820.  
  14821.    Table 9.3  Statements and Functions Used for Standard I/O
  14822. ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
  14823.                         Statement or
  14824.    Task                 Function             Action
  14825.    ──────────────────────────────────────────────────────────────────────────
  14826.    Printing text on the PRINT                Outputs text to the screen.
  14827.    screen                                    Using PRINT with no arguments
  14828.                         Statement or
  14829.    Task                 Function             Action
  14830.    ──────────────────────────────────────────────────────────────────────────
  14831.   screen                                    Using PRINT with no arguments
  14832.                                              creates a blank line.
  14833.  
  14834.                         PRINT USING          Outputs formatted text to the
  14835.                                              screen.
  14836.  
  14837.    Changing the width   WIDTH                Changes the width of the screen
  14838.    of the output line                        to either 40 columns or 80
  14839.                                              columns and, on computers with
  14840.                                              an EGA or VGA, controls the
  14841.                                              number of lines on the screen
  14842.                                              (25 or 43).
  14843.  
  14844.                         WIDTH "SCRN:"        Assigns a maximum length to
  14845.                                              lines output to the screen when
  14846.                                              used before an OPEN "SCRN:"
  14847.                                              statement.
  14848.  
  14849.                         Statement or
  14850.    Task                 Function             Action
  14851.    ──────────────────────────────────────────────────────────────────────────
  14852. 
  14853.    Getting input from   INKEY$               Reads a character from the
  14854.    the keyboard                              keyboard (or a null string if no
  14855.                                              character is waiting).
  14856.  
  14857.                         INPUT$               Reads a specified number of
  14858.                                              characters from the keyboard and
  14859.                                              stores them in a single string
  14860.                                              variable.
  14861.  
  14862.                         INPUT                Reads input from the keyboard
  14863.                                              and stores it in a list of
  14864.                                              variables.
  14865.  
  14866.                         LINE INPUT           Reads a line of input from the
  14867.                                              keyboard and stores it in a
  14868.                                              single string variable.
  14869.  
  14870.                         Statement or
  14871.    Task                 Function             Action
  14872.    ──────────────────────────────────────────────────────────────────────────
  14873. 
  14874.    Positioning the      LOCATE               Moves the cursor to a specified
  14875.    cursor on the screen                      row and column.
  14876.  
  14877.                         SPC                  Skips spaces in printed output.
  14878.  
  14879.                         TAB                  Displays printed output in a
  14880.                                              given column.
  14881.  
  14882.    Getting information  CSRLIN               Tells which row or line position
  14883.    on cursor location                        the cursor is in.
  14884.  
  14885.                         POS(n)               Tells which column the cursor is
  14886.                                              in.
  14887.  
  14888.    Creating a text      VIEW PRINT           Sets the top and bottom rows for
  14889.    viewport                                  displaying text output.
  14890.    ──────────────────────────────────────────────────────────────────────────
  14891.                         Statement or
  14892.    Task                 Function             Action
  14893.    ──────────────────────────────────────────────────────────────────────────
  14894.   ──────────────────────────────────────────────────────────────────────────
  14895.  
  14896.  
  14897.  
  14898.  9.4  Summary of File I/O Statements
  14899.  
  14900.    Table 9.4 lists the statements and functions used in BASIC data-file
  14901.    programming.
  14902.  
  14903.    Table 9.4  Statements and Functions Used for Data-File I/O
  14904. ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
  14905.                         Statement or
  14906.    Task                 Function             Action
  14907.    ──────────────────────────────────────────────────────────────────────────
  14908.    Creating a new file  OPEN                 Opens a file for retrieving or
  14909.    or accessing an                           storing records (I/O).
  14910.    existing file
  14911.    Closing a file       CLOSE                Ends I/O to a file.
  14912.                         Statement or
  14913.    Task                 Function             Action
  14914.    ──────────────────────────────────────────────────────────────────────────
  14915.   Closing a file       CLOSE                Ends I/O to a file.
  14916.    Storing data in a    PRINT #              Stores a list of variables as
  14917.    file                                      record fields in a previously
  14918.                                              opened file.
  14919.                         PRINT USING #        Similar to PRINT #, except PRINT
  14920.                                              USING # formats the record
  14921.                                              fields.
  14922.                         WRITE #              Stores a list of variables as
  14923.                                              record fields in a previously
  14924.                                              opened file.
  14925.                         WIDTH                Specifies a standard length for
  14926.                                              each record in a file.
  14927.                         PUT                  Stores the contents of a
  14928.                                              user-defined variable in a
  14929.                                              previously opened file.
  14930.    Retrieving data from INPUT #              Reads fields from a record and
  14931.    a file                                    assigns each field in the record
  14932.                                              to a program variable.
  14933.                         Statement or
  14934.    Task                 Function             Action
  14935.    ──────────────────────────────────────────────────────────────────────────
  14936.                                             to a program variable.
  14937.                         INPUT$               Reads a string of characters
  14938.                                              from a file.
  14939.                         LINE INPUT #         Reads a record and stores it in
  14940.                                              a single string variable.
  14941.                         GET                  Reads data from a file and
  14942.                                              assigns the data to elements of
  14943.                                              a user-defined variable.
  14944.    Managing files on    FILES                Prints a listing of the files in
  14945.    disk                                      a specified directory.
  14946.                         FREEFILE             Returns the next available file
  14947.                                              number.
  14948.                         KILL                 Deletes a file from the disk.
  14949.                         NAME                 Changes a file's name.
  14950.    Getting information  EOF                  Tests whether all of the data
  14951.    about a file                              have been read from a file.
  14952.                         FILEATTR             Returns the number assigned by
  14953.                                              the operating system to an open
  14954.                         Statement or
  14955.    Task                 Function             Action
  14956.    ──────────────────────────────────────────────────────────────────────────
  14957.                                             the operating system to an open
  14958.                                              file and a number that indicates
  14959.                                              the mode in which the file was
  14960.                                              opened (INPUT, OUTPUT, APPEND,
  14961.                                              BINARY, or RANDOM).
  14962.                         LOC                  Gives the current position
  14963.                                              within a file. With binary
  14964.                                              access, this is the byte
  14965.                                              position. With sequential
  14966.                                              access, this is the byte
  14967.                                              position divided by 128. With
  14968.                                              random access, this is the
  14969.                                              record number of the last record
  14970.                                              read or written.
  14971.                         LOF                  Gives the number of bytes in an
  14972.                                              open file.
  14973.                         SEEK (function)      Gives the location where the
  14974.                                              next I/O operation will take
  14975.                         Statement or
  14976.    Task                 Function             Action
  14977.    ──────────────────────────────────────────────────────────────────────────
  14978.                                             next I/O operation will take
  14979.                                              place. With random access, this
  14980.                                              is the number of the next record
  14981.                                              to be read or written. With all
  14982.                                              other kinds of file access, this
  14983.                                              is the byte position of the next
  14984.                                              byte to be read or written.
  14985.    Moving around in a   SEEK (statement)     Sets the byte position for the
  14986.    file                                      next read or write operation in
  14987.                                              an open file.
  14988.    ──────────────────────────────────────────────────────────────────────────
  14989.  
  14990.  
  14991.  
  14992.  9.5  Summary of String-Processing Statements and Functions
  14993.  
  14994.    Table 9.5 lists the statements and functions available in BASIC for
  14995.    working with strings.
  14996.  
  14997.    Table 9.5  Statements and Functions Used for Processing Strings
  14998. ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
  14999.                         Statement or
  15000.    Task                 Function             Action
  15001.    ──────────────────────────────────────────────────────────────────────────
  15002.    Getting part of a    LEFT$                Returns a given number of
  15003.    string                                    characters from the left side of
  15004.                                              a string.
  15005.  
  15006.                         RIGHT$               Returns a given number of
  15007.                                              characters from the right side
  15008.                                              of a string.
  15009.  
  15010.                         LTRIM$               Returns a copy of a string with
  15011.                                              leading blank spaces stripped
  15012.                                              away.
  15013.  
  15014.                         RTRIM$               Returns a copy of a string with
  15015.                                              trailing blank spaces stripped
  15016.                                              away.
  15017.                         Statement or
  15018.    Task                 Function             Action
  15019.    ──────────────────────────────────────────────────────────────────────────
  15020.                                             away.
  15021.  
  15022.                         MID$ (function)      Returns a given number of
  15023.                                              characters from anywhere in a
  15024.                                              string.
  15025.  
  15026.    Searching strings    INSTR                Searches for a string within
  15027.                                              another string.
  15028.  
  15029.    Converting to        LCASE$               Returns a copy of a string with
  15030.    uppercase or                              all uppercase letters (A-Z)
  15031.    lowercase letters                         converted to lower-case letters
  15032.                                              (a-z); leaves lowercase letters
  15033.                                              and other characters unchanged.
  15034.  
  15035.                         UCASE$               Returns a copy of a string with
  15036.                                              all lowercase letters (a-z)
  15037.                                              converted to upper-case letters
  15038.                         Statement or
  15039.    Task                 Function             Action
  15040.    ──────────────────────────────────────────────────────────────────────────
  15041.                                             converted to upper-case letters
  15042.                                              (A-Z); leaves uppercase letters
  15043.                                              and other characters unchanged.
  15044.  
  15045.    Changing strings     MID$ (statement)     Replaces part of a string with
  15046.                                              another string.
  15047.  
  15048.                         LSET                 Left justifies a string within a
  15049.                                              fixed-length string.
  15050.  
  15051.                         RSET                 Right justifies a string within
  15052.                                              a fixed-length string.
  15053.  
  15054.    Converting between   STR$                 Returns the string
  15055.    numbers and strings                       representation of the value of a
  15056.                                              numeric expression.
  15057.  
  15058.                         VAL                  Returns the numeric value of a
  15059.                         Statement or
  15060.    Task                 Function             Action
  15061.    ──────────────────────────────────────────────────────────────────────────
  15062.                        VAL                  Returns the numeric value of a
  15063.                                              string expression.
  15064.  
  15065.    Converting numbers   CVtype               Changes numbers stored as
  15066.    to data-file                              strings back to Microsoft Binary
  15067.    strings, and                              format numbers in programs
  15068.    data-file strings to                      working with random-access files
  15069.    numbers                                  created with older versions of
  15070.                                              BASIC.
  15071.  
  15072.                         CVtypeMBF            Changes numbers stored as
  15073.                                              Microsoft Binary format strings
  15074.                                              to IEEE-format numbers.
  15075.  
  15076.                         MKtype$              Changes Microsoft Binary format
  15077.                                              numbers to strings suitable for
  15078.                                              storing in random-access files
  15079.                                              created with older versions of
  15080.                         Statement or
  15081.    Task                 Function             Action
  15082.    ──────────────────────────────────────────────────────────────────────────
  15083.                                             created with older versions of
  15084.                                              BASIC.
  15085.  
  15086.                         MKtypeMBF$           Changes IEEE-format numbers to
  15087.                                              Microsoft Binary format strings.
  15088.  
  15089.    Creating strings of  SPACE$               Returns a string of blank
  15090.    repeating characters                      characters of a specified
  15091.                                              length.
  15092.  
  15093.                         STRING$              Returns a string consisting of
  15094.                                              one repeated character.
  15095.  
  15096.    Getting the length   LEN                  Tells how many characters are in
  15097.    of a string                               a string.
  15098.  
  15099.    Working with ASCII   ASC                  Returns the ASCII value of the
  15100.    values                                    given character.
  15101.                         Statement or
  15102.    Task                 Function             Action
  15103.    ──────────────────────────────────────────────────────────────────────────
  15104.   values                                    given character.
  15105.  
  15106.                         CHR$                 Returns the character with the
  15107.                                              given ASCII value.
  15108.    ──────────────────────────────────────────────────────────────────────────
  15109.  
  15110.  
  15111.  
  15112.  9.6  Summary of Graphics Statements and Functions
  15113.  
  15114.  Table 9.6 lists the statements and functions used in BASIC for pixel-based
  15115.  graphics.
  15116.  
  15117.    Table 9.6  Statements and Functions Used for Graphics Output
  15118. ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
  15119.                         Statement or
  15120.    Task                 Function             Action
  15121.    ──────────────────────────────────────────────────────────────────────────
  15122.                         Statement or
  15123.    Task                 Function             Action
  15124.    ──────────────────────────────────────────────────────────────────────────
  15125.    Setting              SCREEN               Specifies a BASIC screen mode,
  15126.    screen-display                            which determines screen
  15127.    characteristics                           characteristics such as
  15128.                                              resolution and ranges for color
  15129.                                              numbers.
  15130.  
  15131.    Plotting or erasing  PSET                 Gives a pixel on the screen a
  15132.    a single point                            specified color using the
  15133.                                              screen's foreground color by
  15134.                                              default.
  15135.  
  15136.                         PRESET               Gives a pixel on the screen a
  15137.                                              specified color using the
  15138.                                              screen's background color by
  15139.                                              default, effectively erasing the
  15140.                                              pixel.
  15141.  
  15142.    Drawing shapes       LINE                 Draws a straight line or a box.
  15143.                         Statement or
  15144.    Task                 Function             Action
  15145.    ──────────────────────────────────────────────────────────────────────────
  15146.   Drawing shapes       LINE                 Draws a straight line or a box.
  15147.  
  15148.                         CIRCLE               Draws a circle or ellipse.
  15149.  
  15150.                         DRAW                 Combines many of the features of
  15151.                                              other BASIC graphics statements
  15152.                                              (drawing lines, moving the
  15153.                                              graphics cursor, scaling images)
  15154.                                              into an all-in-one graphics
  15155.                                              macro language.
  15156.  
  15157.    Defining screen      VIEW                 Specifies a rectangle on the
  15158.    coordinates                               screen (or viewport) as the area
  15159.                                              for graphics output.
  15160.  
  15161.                         WINDOW               Allows the user to choose new
  15162.                                              view coordinates for a viewport
  15163.                                              on the screen.
  15164.                         Statement or
  15165.    Task                 Function             Action
  15166.    ──────────────────────────────────────────────────────────────────────────
  15167.                                             on the screen.
  15168.  
  15169.                         PMAP                 Maps physical pixel coordinates
  15170.                                              to view coordinates specified by
  15171.                                              the user in the current window,
  15172.                                              or vice versa.
  15173.  
  15174.                         POINT(number)        Returns the current physical or
  15175.                                              view coordinates of the graphics
  15176.                                              cursor, depending on the value
  15177.                                              for number.
  15178.  
  15179.    Using color          COLOR                Sets the default colors used in
  15180.                                              graphics output.
  15181.  
  15182.                         PALETTE              Assigns different colors to
  15183.                                              color numbers. Works only on
  15184.                                              systems equipped with an EGA or
  15185.                         Statement or
  15186.    Task                 Function             Action
  15187.    ──────────────────────────────────────────────────────────────────────────
  15188.                                             systems equipped with an EGA or
  15189.                                              VGA.
  15190.  
  15191.                         POINT(x, y)          Returns the color number of a
  15192.                                              single pixel whose screen
  15193.                                              coordinates are x and y.
  15194.  
  15195.    Painting enclosed    PAINT                Fills an area on the screen with
  15196.    shapes                                    a color or pattern.
  15197.  
  15198.    Animating            GET                  Copies a rectangular area on the
  15199.                                              screen by translating the image
  15200.                                              to numeric data and storing the
  15201.                                              data in a numeric array.
  15202.  
  15203.                         PUT                  Displays an image on the screen
  15204.                                              that was previously copied with
  15205.                                              GET.
  15206.                         Statement or
  15207.    Task                 Function             Action
  15208.    ──────────────────────────────────────────────────────────────────────────
  15209.                                             GET.
  15210.  
  15211.                         PCOPY                Copies one screen page to
  15212.                                              another.
  15213.    ──────────────────────────────────────────────────────────────────────────
  15214.  
  15215.  
  15216.  
  15217.  9.7  Summary of Trapping Statements and Functions
  15218.  
  15219.    Table 9.7 lists the statements and functions used by BASIC to trap and
  15220.    process errors and events.
  15221.  
  15222.    Table 9.7  Statements and Functions Used in Error and Event Trapping
  15223. ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
  15224.    Task                 Statement or         Action
  15225.                         Function
  15226.    ──────────────────────────────────────────────────────────────────────────
  15227.    Task                 Statement or         Action
  15228.                         Function
  15229.    ──────────────────────────────────────────────────────────────────────────
  15230.    Trapping errors      ON ERROR GOTO line   Causes a program to branch to
  15231.    while a program is                        the given line, where line
  15232.    running                                   refers either to a line number
  15233.                                              or line label. Branching takes
  15234.                                              place whenever an error occurs
  15235.                                              during execution.
  15236.  
  15237.                         RESUME               Returns control to the program
  15238.                                              after executing an
  15239.                                              error-handling routine. The
  15240.                                              program resumes at either the
  15241.                                              statement causing the error
  15242.                                              (RESUME [[0]]), the statement
  15243.                                              after the one causing the error
  15244.                                              (RESUME NEXT), or the line
  15245.                                              identified by line (RESUME
  15246.                                              line).
  15247.  
  15248.    Task                 Statement or         Action
  15249.                         Function
  15250.    ──────────────────────────────────────────────────────────────────────────
  15251. 
  15252.    Getting error-status ERR                  Returns the code for an error
  15253.    data                                      that occurs at run time.
  15254.  
  15255.                         ERL                  Returns the number of the line
  15256.                                              on which an error occurred (if
  15257.                                              program has line numbers).
  15258.  
  15259.                         ERDEV                Returns a device-specific error
  15260.                                              code for the last device (such
  15261.                                              as a printer) for which DOS
  15262.                                              detected an error.
  15263.  
  15264.                         ERDEV$               Returns the name of the last
  15265.                                              device for which DOS detected an
  15266.                                              error.
  15267.  
  15268.    Defining your own    ERROR                Simulates the occurrence of a
  15269.    Task                 Statement or         Action
  15270.                         Function
  15271.    ──────────────────────────────────────────────────────────────────────────
  15272.   Defining your own    ERROR                Simulates the occurrence of a
  15273.    error codes                               BASIC error; can also be used to
  15274.                                              define an error not trapped by
  15275.                                              BASIC.
  15276.  
  15277.    Trapping events      ON event GOSUB line  Causes a branch to the
  15278.    while a program is                        subroutine starting with line,
  15279.    running                                   where line refers either to a
  15280.                                              line number or line label,
  15281.                                              whenever the given event occurs
  15282.                                              during execution.
  15283.  
  15284.                         event ON             Enables trapping of the given
  15285.                                              event.
  15286.  
  15287.                         event OFF            Disables trapping of the given
  15288.                                              event.
  15289.  
  15290.    Task                 Statement or         Action
  15291.                         Function
  15292.    ──────────────────────────────────────────────────────────────────────────
  15293. 
  15294.                         event STOP           Suspends trapping of the given
  15295.                                              event.
  15296.  
  15297.                         RETURN               Returns control to the program
  15298.                                              after executing an
  15299.                                              event-handling subroutine. The
  15300.                                              program resumes at either the
  15301.                                              statement immediately following
  15302.                                              the place in the program where
  15303.                                              the event occurred (RETURN), or
  15304.                                              the line that is identified by
  15305.                                              line (RETURN line).
  15306.    ──────────────────────────────────────────────────────────────────────────
  15307.  
  15308.  
  15309.  
  15310.  ────────────────────────────────────────────────────────────────────────────
  15311.  Appendix A  Converting BASICA Programs to QuickBASIC
  15312.  
  15313.    QuickBASIC generally accepts BASIC language statements written for the
  15314.    BASIC interpreters used on IBM Personal Computers and compatibles: IBM
  15315.    Advanced Personal Computer BASIC Version A3.00 (BASICA) and Microsoft
  15316.    GW-BASIC(R). However, a few changes are required because of internal
  15317.    differences between QuickBASIC and these BASIC interpreters. Since the
  15318.    changes apply equally to both interpreters, this appendix uses the term
  15319.    BASICA to refer to both GW-BASIC and BASICA.
  15320.  
  15321.    This appendix provides information on:
  15322.  
  15323.    ■ Compatible source-file format
  15324.  
  15325.    ■ Statements and functions prohibited or requiring modification for
  15326.      QuickBASIC use
  15327.  
  15328.    ■ Editor differences in handling tabs
  15329.  
  15330.    The following sections describe only the changes required to compile and
  15331.    run a BASICA program with QuickBASIC Version 4.5. The chapters in this
  15332.    book provide information on how to use QuickBASIC features to enhance your
  15333.    existing BASICA programs.
  15334.  
  15335.  
  15336.  A.1  Source-File Format
  15337.  
  15338.    QuickBASIC Version 4.5 expects the source file to be in ASCII format or in
  15339.    QuickBASIC's own format. If you create a file with BASICA, it must be
  15340.    saved with the ,A option; otherwise, BASICA compresses the text of your
  15341.    program in a special format that QuickBASIC cannot read. If this happens,
  15342.    reload BASICA and resave the file in ASCII format, using the ,A option.
  15343.    For example, the following BASICA command saves the file MYPROG.BAS in
  15344.    ASCII format:
  15345.  
  15346.    SAVE "MYPROG.BAS",A
  15347.  
  15348.  
  15349.  A.2  Statements and Functions Prohibited in QuickBASIC
  15350.  
  15351.    The statements and functions listed below cannot be used in a QuickBASIC
  15352.    program because they perform editing operations on the source file,
  15353.    interfere with program execution, refer to a cassette device (not
  15354.    supported by QuickBASIC), or duplicate support provided by the QuickBASIC
  15355.    environment:
  15356.  
  15357.  
  15358.    ──────────────────────────────────────────────────────────────────────────
  15359.    AUTO                     LIST                    NEW
  15360.  
  15361.    CONT                     LLIST                   RENUM
  15362.  
  15363.    DEFUSR                   LOAD                    SAVE
  15364.  
  15365.    DELETE                   MERGE                   USR
  15366.  
  15367.    EDIT                     MOTOR
  15368.    ──────────────────────────────────────────────────────────────────────────
  15369.  
  15370.  
  15371.  A.3  Statements Requiring Modification
  15372.  
  15373.    If your BASICA program contains any of the statements listed in Table A.1,
  15374.    you probably need to modify your source code before you can run your
  15375.    program in QuickBASIC.
  15376.  
  15377.    Table A.1  Statements Requiring Modification
  15378. ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
  15379.    Statement          Modification
  15380.    ──────────────────────────────────────────────────────────────────────────
  15381.    BLOAD/BSAVE        Memory locations may be different in QuickBASIC.
  15382.  
  15383.    CALL               The argument is the name of the SUB procedure being
  15384.                       called.
  15385.  
  15386.    CHAIN              QuickBASIC does not support the ALL, MERGE, DELETE, or
  15387.                       linenumber options.
  15388.  
  15389.    COMMON             COMMON statements must appear before any executable
  15390.                       statements.
  15391.  
  15392.    DEFtype            DEFtype statements should be moved to the beginning of
  15393.                       the BASICA source file.
  15394.  
  15395.    Statement          Modification
  15396.    ──────────────────────────────────────────────────────────────────────────
  15397. 
  15398.    DIM                All DIM statements declaring static arrays must appear
  15399.                       at the beginning of QuickBASIC programs.
  15400.  
  15401.    DRAW, PLAY         QuickBASIC requires that the VARPTR$ function be used
  15402.                       with embedded variables.
  15403.  
  15404.    RESUME             If an error occurs in a single-line function,
  15405.                       QuickBASIC attempts to resume program execution at the
  15406.                       line containing the function.
  15407.  
  15408.    RUN                For executable files produced by QuickBASIC, the object
  15409.                       of a RUN or CHAIN statement cannot be a .BAS file; it
  15410.                       must be an executable file. The R option in BASICA is
  15411.                       not supported. While in the QuickBASIC environment, the
  15412.                       object of a RUN or CHAIN statement is still a .BAS
  15413.                       file.
  15414.  
  15415.                       RUN{linenumber| linelabel}, however, is supported in
  15416.    Statement          Modification
  15417.    ──────────────────────────────────────────────────────────────────────────
  15418.                      RUN{linenumber| linelabel}, however, is supported in
  15419.                       QuickBASIC; this statement restarts the program at the
  15420.                       specified line.
  15421.    ──────────────────────────────────────────────────────────────────────────
  15422.  
  15423.  
  15424.  
  15425.  A.4  Editor Differences in Handling Tabs
  15426.  
  15427.    QuickBASIC uses individual spaces (rather than the literal tab character,
  15428.    ASCII 9) to represent indentation levels. The Tab Stops option in the
  15429.    Option menu's Display dialog box set the number of spaces per indentation
  15430.    level. (See Chapter 20, "The Options Menu," in Learning to Use Microsoft
  15431.    QuickBASIC for more information.)
  15432.  
  15433.    Some text editors use the literal tab character to represent multiple
  15434.    spaces when storing text files. The QuickBASIC editor treats literal tab
  15435.    characters in such files as follows:
  15436.  
  15437.    1. Literal tab characters inside quoted strings appear as the character
  15438.       shown for ASCII character 9 in the ASCII table in Appendix D,
  15439.       "Keyboard Scan Codes and ASCII Character Codes."
  15440.  
  15441.    2. Outside quoted strings, tab characters indent the text following them
  15442.       to the next indentation level.
  15443.  
  15444.    If you try to change the Tab Stops setting while such a program is loaded,
  15445.    QuickBASIC gives the following error message:
  15446.  
  15447.    Cannot change tab stops while file is loaded
  15448.  
  15449.    This is to prevent you from inadvertently reformatting old source files
  15450.    created with other editors. If you load such a file and then decide you
  15451.    prefer a different indentation, reset the indentation using the following
  15452.    procedure:
  15453.  
  15454.    1. Save your file to preserve any changes, then choose the New Program
  15455.       command from the File menu.
  15456.  
  15457.    2. Choose the Display command from the Options menu and set the Tab Stops
  15458.       option as described above.
  15459.  
  15460.    3. Choose the Open Program command from the File menu and reload your
  15461.       program. When your program is reloaded, the indentations will reflect
  15462.       the new setting of the Tab Stops option.
  15463.  
  15464.    Note that this procedure works only for old programs. Text created within
  15465.    QuickBASIC cannot be reformatted this way.
  15466.  
  15467.  
  15468.  
  15469.  ────────────────────────────────────────────────────────────────────────────
  15470.  Appendix B  Differences from Previous Versions of QuickBASIC
  15471.  
  15472.    QuickBASIC Version 4.5 contains many new features and enhancements over
  15473.    previous versions of QuickBASIC. This appendix describes the differences
  15474.    between Versions 2.0 and 4.5 of QuickBASIC. Unless otherwise stated,
  15475.    differences between Versions 2.0 and 4.5 also apply as differences between
  15476.    Versions 3.0 and 4.5. Differences between Versions 4.0 and 4.5 are
  15477.    primarily in the QuickBASIC environment.
  15478.  
  15479.    This appendix provides information on the following improvements in
  15480.    QuickBASIC Version 4.5:
  15481.  
  15482.    ■ Product capabilities and features
  15483.  
  15484.    ■ Environment enhancements
  15485.  
  15486.    ■ Improvements in compiling and debugging capabilities
  15487.  
  15488.    ■ Language changes
  15489.  
  15490.    ■ File compatibility
  15491.  
  15492.  
  15493.  B.1  QuickBASIC Features
  15494.  
  15495.    This section compares the features of Microsoft QuickBASIC Versions 4.5
  15496.    with those of previous versions. The features are listed in Table B.1 and
  15497.    described below.
  15498.  
  15499.    Table B.1  Features of Microsoft QuickBASIC Version 4.5
  15500. ╓┌─┌───────────────────────────────┌─────────┌──────────┌─────────┌──────────╖
  15501.                                            QuickBASIC Version
  15502.    Feature                         2.0       3.0        4.0       4.5
  15503.    ──────────────────────────────────────────────────────────────────────────
  15504.    On-line QB Advisor (detailed    No        No         No        Yes
  15505.    reference)
  15506.  
  15507.    Selectable right mouse button   No        No         No        Yes
  15508.    function
  15509.  
  15510.    Instant Watches for variables   No        No         No        Yes
  15511.    and expressions
  15512.  
  15513.    Set default search paths        No        No         No        Yes
  15514.  
  15515.    User-defined types              No        No         Yes       Yes
  15516.  
  15517.    IEEE format, math coprocessor   No        Yes        Yes       Yes
  15518.    support
  15519.  
  15520.    On-line help                    No        No         Yes       Yes
  15521.                                            QuickBASIC Version
  15522.    Feature                         2.0       3.0        4.0       4.5
  15523.    ──────────────────────────────────────────────────────────────────────────
  15524.   On-line help                    No        No         Yes       Yes
  15525.  
  15526.    Symbol help                     No        No         No        Yes
  15527.  
  15528.    Long (32-bit) integers          No        No         Yes       Yes
  15529.  
  15530.    Fixed-length strings            No        No         Yes       Yes
  15531.  
  15532.    Syntax checking on entry        No        No         Yes       Yes
  15533.  
  15534.    Binary file I/O                 No        No         Yes       Yes
  15535.  
  15536.    FUNCTION procedures             No        No         Yes       Yes
  15537.  
  15538.    CodeView(R) support             No        No         Yes       Yes
  15539.  
  15540.    Compatibility with other        No        No         Yes       Yes
  15541.    languages
  15542.                                            QuickBASIC Version
  15543.    Feature                         2.0       3.0        4.0       4.5
  15544.    ──────────────────────────────────────────────────────────────────────────
  15545.   languages
  15546.  
  15547.    Multiple modules in memory      No        No         Yes       Yes
  15548.  
  15549.    ProKey TM, SideKick(R), and     No        Yes        Yes       Yes
  15550.    SuperKey(R) compatibility
  15551.  
  15552.    Insert/overtype modes           No        Yes        Yes       Yes
  15553.  
  15554.    WordStar(R)-style keyboard      No        No         Yes       Yes
  15555.    interface
  15556.  
  15557.    Recursion                       No        No         Yes       Yes
  15558.  
  15559.    Error listings during separate  No        Yes        Yes       Yes
  15560.    compilation
  15561.  
  15562.    Assembly-language listings      No        Yes        Yes       Yes
  15563.                                            QuickBASIC Version
  15564.    Feature                         2.0       3.0        4.0       4.5
  15565.    ──────────────────────────────────────────────────────────────────────────
  15566.   Assembly-language listings      No        Yes        Yes       Yes
  15567.    during separate compilation
  15568.    ──────────────────────────────────────────────────────────────────────────
  15569.  
  15570.  
  15571.  B.1.1  Features New to QuickBASIC 4.5
  15572.  
  15573.    You can now access on-line help for QuickBASIC's keywords, commands, and
  15574.    menus, as well as general topics and your own variables. Examples shown on
  15575.    help screens can be copied and pasted directly into your own program,
  15576.    reducing development time.
  15577.  
  15578.    For mouse users, you can now set the function of the right mouse button
  15579.    with the Right Mouse command from the Options menu. Use the function that
  15580.    best suits your needs. For more information see Chapter 19, "The Calls
  15581.    Menu," in Learning to Use Microsoft QuickBASIC.
  15582.  
  15583.    For faster debugging, QuickBASIC now offers an Instant Watch command for
  15584.    immediately identifying the value of a variable or the condition (true or
  15585.    false) of an expression. For more information see Chapter 18, "The Debug
  15586.    Menu," in Learning to Use Microsoft QuickBASIC.
  15587.  
  15588.    Version 4.5 also lets you set default search paths to specific types of
  15589.    files. This lets you organize your files by type and keep them in separate
  15590.    directories. QuickBASIC will search the correct directory after you set
  15591.    the new default search path. You can set default paths for executable,
  15592.    include, library, and help files.
  15593.  
  15594.  B.1.2  Features Introduced in QuickBASIC 4.0
  15595.  
  15596.    If you are new to QuickBASIC or unfamiliar with Version 4.0, you will want
  15597.    to review the following features introduced in QuickBASIC 4.0 and
  15598.    supported in the current version.
  15599.  
  15600.    B.1.2.1  User-Defined Types
  15601.  
  15602.    The TYPE statement allows you to create composite data types from simple
  15603.    data elements. Such data types are similar to C-language structures.
  15604.    User-defined types are discussed in Chapter 3, "File and Device I/O."
  15605.  
  15606.    B.1.2.2  IEEE Format and Math-Coprocessor Support
  15607.  
  15608.    Microsoft QuickBASIC provides IEEE-format numbers and math-coprocessor
  15609.    support. When no coprocessor is present, QuickBASIC emulates the
  15610.    coprocessor.
  15611.  
  15612.    Calculations done by programs compiled with QuickBASIC are generally more
  15613.    accurate and may produce results different from programs run under BASICA
  15614.    or versions of QuickBASIC prior to 4.0. Single-precision IEEE-format
  15615.    numbers provide an additional decimal digit of accuracy. When compared to
  15616.    Microsoft Binary format double-precision numbers, IEEE-format
  15617.    double-precision numbers provide an additional one to two digits in the
  15618.    mantissa and extend the range of the exponent.
  15619.  
  15620.    There are two ways to use QuickBASIC 4.0 and 4.5 with your old programs
  15621.    and existing data:
  15622.  
  15623.    1. Use the /MBF option. This way, you can use your old programs and data
  15624.       files without rewriting your programs or changing your files.
  15625.  
  15626.    2. Modify your data files and use the new QuickBASIC to recompile your
  15627.       programs. In the long run, this ensures compatibility with future
  15628.       versions of QuickBASIC and may produce faster programs. Only
  15629.       random-access files containing binary format real numbers need to be
  15630.       changed. Files containing only integers or string data can be used
  15631.       without modification. More information on these options is provided
  15632.       below.
  15633.  
  15634.    ──────────────────────────────────────────────────────────────────────────
  15635.    NOTE
  15636.      If assembly-language procedures that use real numbers are called from
  15637.      your program, they must be written so that they use IEEE-format numbers.
  15638.      This is the default for Microsoft Macro Assembler (MASM) Version 5.0 and
  15639.      later versions. With earlier versions, be sure to use the /R
  15640.      command-line option or the 8087 assembler directive.
  15641.    ──────────────────────────────────────────────────────────────────────────
  15642.  
  15643.    B.1.2.3  Ranges of IEEE-Format Numbers
  15644.  
  15645.    IEEE-format numbers have a wider range than Microsoft Binary format
  15646.    numbers, as shown in the following list:
  15647.  
  15648.    Type of Number           Range of Values
  15649.    ──────────────────────────────────────────────────────────────────────────
  15650.    Single precision         -3.37 * 10^38 to -8.43 * 10^-37
  15651.                             True zero
  15652.  
  15653.                             8.43 * 10^-37 to 3.37 * 10^38
  15654.  
  15655.    Double precision         -1.67 * 10^308 to -4.19 * 10^-307
  15656.                             True zero
  15657.  
  15658.                             4.19 * 10^-307 to 1.67 * 10^308
  15659.    ──────────────────────────────────────────────────────────────────────────
  15660.  
  15661.    Single-precision values are accurate to approximately seven digits.
  15662.    Double-precision values are accurate to either 15 or 16 digits.
  15663.  
  15664.    Note that double-precision values may have three digits in the exponent.
  15665.    This may cause problems in PRINT USING statements.
  15666.  
  15667.    B.1.2.4  PRINT USING and IEEE-Format Numbers
  15668.  
  15669.    Because double-precision IEEE-format numbers can have larger exponents
  15670.    than Microsoft Binary format double-precision numbers, you may need to use
  15671.    a special exponential format in PRINT USING statements. Use the new format
  15672.    if your program prints values with three-digit exponents. To print numbers
  15673.    with three-digit exponents, use five carets (^^^^^) instead of four carets
  15674.    to indicate exponential format:
  15675.  
  15676.    PRINT USING "+#.######^^^^^", Circumference#
  15677.  
  15678.    If an exponent is too large for a field, QuickBASIC replaces the first
  15679.    digit with a percent sign (%) to indicate the problem.
  15680.  
  15681.  B.1.3  Recompiling Old Programs with /MBF
  15682.  
  15683.    Old programs and files work with QuickBASIC Version 4.5 without
  15684.    modification if you recompile the programs with the /MBF command-line
  15685.    option. For example, to compile the program named multrgrs.bas, enter the
  15686.    following at the DOS prompt:
  15687.  
  15688.    BC multrgrs /MBF;
  15689.  
  15690.    Then link the program as you usually do. To recompile using the Make EXE
  15691.    File command, be sure to use the /MBF option when you start QuickBASIC.
  15692.    Then compile as you normally would.
  15693.  
  15694.    The /MBF option converts Microsoft Binary format numbers to IEEE format as
  15695.    they are read from a random-access file and converts them back to
  15696.    Microsoft Binary format before writing them to a file. This lets you do
  15697.    calculations with IEEE-format numbers while keeping the numbers in
  15698.    Microsoft Binary format in your files.
  15699.  
  15700.  B.1.4  Converting Files and Programs
  15701.  
  15702.    If you decide to convert your programs and data files rather than use the
  15703.    /MBF command-line option, you need to do two things:
  15704.  
  15705.    1. Recompile your programs.
  15706.  
  15707.    2. Convert your data files.
  15708.  
  15709.    Your old QuickBASIC programs should compile without modification. However,
  15710.    do not use the /MBF option when recompiling. Your program will not work
  15711.    with your new data files if you use the /MBF option.
  15712.  
  15713.    Data files containing real numbers need to be converted so that real
  15714.    numbers are stored in IEEE format. QuickBASIC Version 4.5 includes eight
  15715.    functions that help you do this.
  15716.  
  15717.    ──────────────────────────────────────────────────────────────────────────
  15718.    NOTE
  15719.      You do not need to convert your data files if they contain only integer
  15720.      and string data. Only files containing real numbers must be converted.
  15721.    ──────────────────────────────────────────────────────────────────────────
  15722.  
  15723.    Version 4.5 has the familiar CVS, CVD, MKS$, and MKD$ functions for
  15724.    reading and writing real numbers from or to random-access files. However,
  15725.    these functions now handle real numbers stored in your files in IEEE
  15726.    format, not Microsoft Binary format. To handle numbers in Microsoft Binary
  15727.    format, Version 4.5 includes the functions CVSMBF, CVDMBF, MKSMBF$, and
  15728.    MKDMBF$.
  15729.  
  15730.    With these functions, you can write a short program that reads records
  15731.    from the old file (using Microsoft Binary format as necessary), converts
  15732.    the real-number fields to IEEE format, places the fields in a new record,
  15733.    and writes out the new record.
  15734.  
  15735.    Examples
  15736.  
  15737.    The following program copies an old data file to a new file, making the
  15738.    necessary conversions:
  15739.  
  15740.    ' Define types for old and new file buffers:
  15741.    TYPE Oldbuf
  15742.       ObsId AS STRING * 20
  15743.       XPos AS STRING * 4
  15744.       YPos AS STRING * 4
  15745.       FuncVal AS STRING * 8
  15746.    END TYPE
  15747.  
  15748.    TYPE NewBuf
  15749.       ObsId AS STRING * 20
  15750.       XPos AS SINGLE
  15751.       YPos AS SINGLE
  15752.       FuncVal AS DOUBLE
  15753.    END TYPE
  15754.  
  15755.    ' Declare buffers:
  15756.    DIM OldFile AS Oldbuf, NewFile AS NewBuf
  15757.  
  15758.    ' Open the old and new data files:
  15759.    OPEN "OLDMBF.DAT" FOR RANDOM AS #1 LEN=LEN(OldFile)
  15760.    OPEN "NEWIEEE.DAT" FOR RANDOM AS #2 LEN=LEN(NewFile)
  15761.  
  15762.    I=1
  15763.  
  15764.    ' Read the first old record:
  15765.    GET #1,I,OldFile
  15766.  
  15767.    DO UNTIL EOF(1)
  15768.  
  15769.    ' Move the fields to the new record fields, converting
  15770.    ' the real-number fields:
  15771.       NewFile.ObsId=OldFile.ObsId
  15772.       NewFile.XPos=CVSMBF(OldFile.XPos)
  15773.       NewFile.YPos=CVSMBF(OldFile.YPos)
  15774.       NewFile.FuncVal=CVDMBF(OldFile.FuncVal)
  15775.  
  15776.    ' Write the converted fields to the new file:
  15777.       PUT #2,I,NewFile
  15778.       I=I+1
  15779.  
  15780.    ' Read next record from the old file:
  15781.       GET #1,I,OldFile
  15782.    LOOP
  15783.  
  15784.    CLOSE #1, #2
  15785.  
  15786.    Each record in the two files has four fields: an identifier field, two
  15787.    fields containing single-precision real numbers, and a final field
  15788.    containing a double-precision real number.
  15789.  
  15790.    Most of the conversion work is done with the functions CVDMBF and CVSMBF.
  15791.    For example, the following program line converts the double-precision
  15792.    field:
  15793.  
  15794.    NewFile.FuncVal=CVDMBF(OldFile.FuncVal)
  15795.  
  15796.    The eight bytes in the record field OldFile.FuncVal are converted from a
  15797.    Microsoft Binary format double-precision value to an IEEE-format
  15798.    double-precision value by the function CVDMBF. This value is stored in the
  15799.    corresponding field in the new record, which is later written to the new
  15800.    file by the PUT statement.
  15801.  
  15802.  B.1.5  Other QuickBASIC Features
  15803.  
  15804.    QuickBASIC 4.0 introduced the following features and tools that made
  15805.    QuickBASIC a development package appreciated by the professional without
  15806.    overwhelming the novice. QuickBASIC 4.5 supports all these same features,
  15807.    along with some additional refinements.
  15808.  
  15809.    B.1.5.1  Long (32-Bit) Integers
  15810.  
  15811.    Long (32-bit) integers eliminate rounding errors in calculations with
  15812.    numbers in the range -2,147,483,648 to 2,147,483,647, and they provide
  15813.    much faster whole-number calculations in this range than do floating-point
  15814.    types.
  15815.  
  15816.    B.1.5.2  Fixed-Length Strings
  15817.  
  15818.    Fixed-length strings let you incorporate string data into user-defined
  15819.    types. See Chapter 4, "String Processing," for more information.
  15820.  
  15821.    B.1.5.3  Syntax Checking on Entry
  15822.  
  15823.    If syntax checking is turned on, QuickBASIC checks each line as you enter
  15824.    it for syntax and duplicate-definition errors. See Chapter 12, "Using the
  15825.    Editor," in Learning to Use Microsoft QuickBASIC for an explanation of
  15826.    syntax checking and other smart-editor features.
  15827.  
  15828.    B.1.5.4  Binary File I/O
  15829.  
  15830.    Versions 4.0 and 4.5 provide binary access to files. This is useful for
  15831.    reading and modifying files saved in non-ASCII format. The major benefit
  15832.    of binary access is that it does not force you to treat a file as a
  15833.    collection of records. If a file is opened in binary mode, you can move
  15834.    forward or backward to any byte position in the file, then read or write
  15835.    as many bytes as you want. Thus, different I/O operations on the same file
  15836.    can GET or PUT a varying number of bytes──unlike with random access, where
  15837.    the number of bytes is fixed by the predefined length of a single record.
  15838.  
  15839.    See Chapter 3, "File and Device I/O," for more information about
  15840.    accessing binary files.
  15841.  
  15842.    B.1.5.5  FUNCTION Procedures
  15843.  
  15844.    FUNCTION procedures allow you to place a function in one module and call
  15845.    it from a different module. See Chapter 2, "SUB and FUNCTION Procedures,"
  15846.    for more information about using FUNCTION procedures.
  15847.  
  15848.    In versions prior to 4.0, a SUB procedure and a variable could have the
  15849.    same name. Now, SUB and FUNCTION procedure names must be unique.
  15850.  
  15851.    B.1.5.6  Support for the CodeView(R) Debugger
  15852.  
  15853.    You can use the command-line tools BC.EXE and LINK.EXE to create
  15854.    executable files compatible with the Microsoft CodeView debugger, a
  15855.    powerful tool included with the Microsoft Macro Assembler (Version 5.0 or
  15856.    later) and with Microsoft C (Version 5.0 or later). Modules compiled with
  15857.    BC can be linked with modules compiled with other Microsoft languages in
  15858.    such a way that the final executable file can be debugged using the
  15859.    CodeView debugger. See Appendix G, "Compiling and Linking from DOS," for
  15860.    more information.
  15861.  
  15862.    B.1.5.7  Other-Language Compatibility
  15863.  
  15864.    QuickBASIC Version 4.5 allows you to call routines written in other
  15865.    Microsoft languages using C or Pascal calling conventions. Arguments are
  15866.    passed by NEAR or FAR reference, or by value. Other-language code may be
  15867.    placed in Quick libraries or linked into executable files.
  15868.  
  15869.    The PTR86 routine is not supported in QuickBASIC, Version 4.5; use the
  15870.    VARPTR and VARSEG functions instead.
  15871.  
  15872.    B.1.5.8  Multiple Modules in Memory
  15873.  
  15874.    You can load multiple program modules into memory simultaneously. Versions
  15875.    previous to 4.0 permitted only one module to be in memory at a time. Now
  15876.    you can edit, execute, and debug multiple-module programs within the
  15877.    QuickBASIC environment. See Chapter 2, "SUB and FUNCTION Procedures," and
  15878.    Chapter 7, "Programming with Modules," for more information about using
  15879.    multiple modules.
  15880.  
  15881.    B.1.5.9  ProKey TM, SideKick(R), and SuperKey(R) Compatibility
  15882.  
  15883.    You can use ProKey, SideKick, and SuperKey within the QuickBASIC
  15884.    environment. Other keyboard-reprogramming or desktop software may not work
  15885.    with QuickBASIC. Check with the suppliers or manufacturers of other
  15886.    products to find out about the product's compatibility with QuickBASIC
  15887.    Version 4.5.
  15888.  
  15889.    B.1.5.10  Insert and Overtype Modes
  15890.  
  15891.    Pressing INS toggles the editing mode between insert and overtype. When
  15892.    overtype mode is on, the cursor changes from a blinking underline to a
  15893.    block. Note that INS replaces the CTRL+O insert/overtype toggle in Version
  15894.    3.0.
  15895.  
  15896.    In insert mode, the editor inserts a typed character at the cursor
  15897.    position. In overtype mode, the editor replaces the character under the
  15898.    cursor with the character you type. Insert mode is the default mode.
  15899.  
  15900.    B.1.5.11  WordStar(R)-Style Keyboard Commands
  15901.  
  15902.    QuickBASIC supports many of the key sequences familiar to WordStar users.
  15903.    A complete list of WordStar-style key commands appears in Chapter 12,
  15904.    "Using the Editor," in Learning to Use Microsoft QuickBASIC.
  15905.  
  15906.    B.1.5.12  Recursion
  15907.  
  15908.    QuickBASIC Versions 4.0 and 4.5 support recursion, which is the ability of
  15909.    a procedure to call itself. Recursion is useful for solving certain
  15910.    problems, such as sorting. See Chapter 2, "SUB and FUNCTION Procedures,"
  15911.    for more information about using recursion.
  15912.  
  15913.    B.1.5.13  Error Listings during Separate Compilation
  15914.  
  15915.    QuickBASIC displays descriptive error messages when you compile programs
  15916.    using the BC command. Using BC, you can redirect the error messages to a
  15917.    file or device to get a copy of the compilation errors. See Appendix G,
  15918.    "Compiling and Linking from DOS," for more information about the BC
  15919.    command.
  15920.  
  15921.    Examples
  15922.  
  15923.    The following examples show how to use the BC command line for error
  15924.    display:
  15925.  
  15926.    Command Line             Action
  15927.    ──────────────────────────────────────────────────────────────────────────
  15928.    BC TEST.BAS;             Compiles the file named TEST.BAS and displays
  15929.                             errors on the screen
  15930.  
  15931.    BC TEST.BAS; > TEST.ERR  Compiles the file TEST.BAS and redirects error
  15932.                             messages to the file named TEST.ERR
  15933.    ──────────────────────────────────────────────────────────────────────────
  15934.  
  15935.    B.1.5.14  Assembly-Language Listings during Separate Compilation
  15936.  
  15937.    The BC command's /A option produces a listing of the assembly-language
  15938.    code produced by the compiler. See Appendix G, "Compiling and Linking
  15939.    from DOS," for more information.
  15940.  
  15941.  
  15942.  B.2  Differences in the Environment
  15943.  
  15944.    The QuickBASIC programming environment now provides more flexible command
  15945.    selection, additional window options, and more menu commands. Sections
  15946.    B.2.1-B.2.5 describes the differences in the programming environment
  15947.    between Version 4.5 and earlier versions.
  15948.  
  15949.  B.2.1  Choosing Commands and Options
  15950.  
  15951.    QuickBASIC Version 4.5 gives you flexibility in how you choose commands
  15952.    from menus and options from dialog boxes.
  15953.  
  15954.    Version 4.5 allows you to select any menu by pressing the ALT key followed
  15955.    by a mnemonic key. Each menu command and dialog box option also has its
  15956.    own mnemonic key, which immediately executes the command or selects the
  15957.    item. The mnemonic keys appear in intense video.
  15958.  
  15959.    In Version 4.5 the ENTER key functions the same way as the SPACEBAR did in
  15960.    versions 3.0 and earlier. You can press ENTER to execute a command from a
  15961.    dialog box.
  15962.  
  15963.  B.2.2  Windows
  15964.  
  15965.    Version 4.5 allows up to two work-area windows (referred to as View
  15966.    windows), a Help window, and a separate Immediate window. Versions prior
  15967.    to 4.0 supported only two windows: one work area and the error-message
  15968.    window.
  15969.  
  15970.  B.2.3  New Menu
  15971.  
  15972.    QuickBASIC Version 4.5 has a new menu, the Options menu. The Options menu
  15973.    accesses special QuickBASIC controls that manipulate the screen display
  15974.    attributes, the function of the right mouse button, the default path to
  15975.    specific file types, syntax checking, and Full Menus control.
  15976.  
  15977.  B.2.4  Menu Commands
  15978.  
  15979.    The Debug and Help menus, which appeared in earlier versions of
  15980.    QuickBASIC, have some new commands. Table B.2 lists the new commands in
  15981.    these menus, as well as the commands from the new Options menu.
  15982.  
  15983.    Table B.2  Menus with New Commands in QuickBASIC Version 4.5
  15984. ╓┌─┌───────────┌────────────────────────┌────────────────────────────────────╖
  15985.    Menu        Command                  Description
  15986.    ──────────────────────────────────────────────────────────────────────────
  15987.    Debug       Add Watch                Adds variable or expression to Watch
  15988.                                         window
  15989.  
  15990.                Instant Watch (New)      Immediately checks the value of a
  15991.                                         variable or expression
  15992.  
  15993.                Watchpoint               Adds a watchpoint to the Watch window
  15994.  
  15995.                Delete Watch             Selectively removes item from Watch
  15996.                                         window
  15997.  
  15998.                Delete All Watch         Removes all items from the Watch
  15999.                                         window
  16000.  
  16001.                Trace On                 Toggles tracing on and off
  16002.  
  16003.                History On               Records last 20 executed statements
  16004.    Menu        Command                  Description
  16005.    ──────────────────────────────────────────────────────────────────────────
  16006.               History On               Records last 20 executed statements
  16007.  
  16008.                Toggle Breakpoint        Toggles a breakpoint on the current
  16009.                                         line on and off
  16010.  
  16011.                Clear All Breakpoints    Removes all breakpoints
  16012.  
  16013.                Break on Errors (New)    Halts program execution if an error
  16014.                                         occurs, regardless of any error
  16015.                                         handling
  16016.  
  16017.                Set Next Statement       Sets the next statement to execute
  16018.                                         when a suspended program continues
  16019.                                         running
  16020.  
  16021.    Option      Display (New)            Customizes the screen elements
  16022.    (New)
  16023.                Set Paths (New)          Alters default search paths for
  16024.                                         specific types of files
  16025.    Menu        Command                  Description
  16026.    ──────────────────────────────────────────────────────────────────────────
  16027.                                        specific types of files
  16028.  
  16029.                Right Mouse (New)        Selects the function for the right
  16030.                                         mouse button
  16031.  
  16032.                Syntax Checking          Toggles automatic syntax checking on
  16033.                                         and off
  16034.  
  16035.                Full Menus (New)         Toggles between Full Menus and Easy
  16036.                                         Menus
  16037.  
  16038.    Help        Index (New)              Displays an alphabetical list of
  16039.                                         QuickBASIC keywords and a brief
  16040.                                         description of each
  16041.  
  16042.                Contents (New)           Displays a visual outline of contents
  16043.  
  16044.                Topic                    Provides information on variables,
  16045.                                         keywords
  16046.    Menu        Command                  Description
  16047.    ──────────────────────────────────────────────────────────────────────────
  16048.                                        keywords
  16049.  
  16050.                Help on Help (New)       Describes how to use Help and common
  16051.                                         keyword shortcuts
  16052.    ──────────────────────────────────────────────────────────────────────────
  16053.  
  16054.  
  16055.    The Version 3.0 Debug option is removed from the Run menu. In Version 4.5
  16056.    you can debug at any time, using the debugging commands in the Debug menu.
  16057.  
  16058.  B.2.5  Editing-Key Changes
  16059.  
  16060.    The QuickBASIC keyboard interface has been extended to include editing key
  16061.    sequences similar to those in the WordStar editor. (See Chapter 12, "Using
  16062.    the Editor," and Chapter 13, "The Edit Menu," in Learning to Use Microsoft
  16063.    QuickBASIC for more information about editing.) The functions performed by
  16064.    the QuickBASIC Version 2.0 key sequences listed in Table B.3 are changed
  16065.    in QuickBASIC Versions 4.0 and 4.5.
  16066.  
  16067.    Table B.3  Editing-Key Changes
  16068.                             QuickBASIC              QuickBASIC
  16069.    Function                 2.0 Key                 4.5 Key
  16070.    ──────────────────────────────────────────────────────────────────────────
  16071.    Undo                     SHIFT+ESC               ALT+BKSP
  16072.  
  16073.    Cut                      DEL                     SHIFT+DEL
  16074.  
  16075.    Copy                     F2                      CTRL+INS
  16076.  
  16077.    Paste                    INS                     SHIFT+INS
  16078.  
  16079.    Clear                    ──                      DEL
  16080.  
  16081.    Overtype                 ──                      INS
  16082.    ──────────────────────────────────────────────────────────────────────────
  16083.  
  16084.  
  16085.  B.3  Differences in Compiling and Debugging
  16086.  
  16087.    In the QuickBASIC 4.5 programming environment, compiling and debugging are
  16088.    not separate operations. Your program is always ready to run, and you can
  16089.    debug your code in several ways while you program. This section describes
  16090.    the differences in compiling and debugging features between QuickBASIC
  16091.    Versions 4.0 and 4.5 and previous versions.
  16092.  
  16093.  B.3.1  Command-Line Differences
  16094.  
  16095.    QuickBASIC Versions 4.0 and 4.5 support Version 2.0 command-line options
  16096.    only for the QB command, not the BC command. To compile a program outside
  16097.    of the QuickBASIC environment, use the BC command, which is described in
  16098.    Appendix G, "Compiling and Linking from DOS."
  16099.  
  16100.    Versions 4.0 and 4.5 do not require any of the Compile options listed in
  16101.    Table 4.1 of the Microsoft QuickBASIC Version 2.0 manual. If you attempt
  16102.    to invoke QuickBASIC using these as command-line options, an error message
  16103.    appears. Similarly, it was necessary to choose certain compiler options
  16104.    from the Compile dialog box in Version 3.0; this is now done
  16105.    automatically. Table B.4 describes the way in which QuickBASIC now
  16106.    supports the functionality of these options.
  16107.  
  16108.    Table B.4  QB and BC Options Not Used in QuickBASIC Versions 4.0 or 4.5
  16109.    Version 2.0              Version 4.5
  16110.    ──────────────────────────────────────────────────────────────────────────
  16111.    On Error (/E)            Automatically set whenever an ON ERROR statement
  16112.                             is present.
  16113.  
  16114.    Debug (/D)               Always on when you run a program within the
  16115.                             QuickBASIC environment. When producing executable
  16116.                             programs on disk or Quick libraries, use the
  16117.                             Produce Debug Code option.
  16118.  
  16119.    Checking between         Automatically set whenever an ON event statement
  16120.    Statements (/V) and      is present.
  16121.    Event Trapping (/W)
  16122.  
  16123.    Resume Next (/X)         Automatically set whenever a RESUME NEXT
  16124.                             statement is present.
  16125.  
  16126.    Arrays in Row Order (/R) Available only when compiling with BC.
  16127.  
  16128.    Minimize String Data     The default for QB. To turn off this option, you
  16129.    (/S)                     must compile from the command line with BC.
  16130.    ──────────────────────────────────────────────────────────────────────────
  16131.  
  16132.    The options listed in Table B.5 are now available for the QB and BC
  16133.    commands.
  16134.  
  16135.    Table B.5  Options Introduced in Version 4.0 for the QB and BC Commands
  16136. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  16137.    Option                   Description
  16138.    ──────────────────────────────────────────────────────────────────────────
  16139.    /AH                      Allows dynamic arrays of records, fixed-length
  16140.                             strings, and numeric data to be larger than 64K
  16141.                             each. If this option is not specified, the
  16142.                             maximum size for each array is 64K. Note that
  16143.                             this option has no effect on the way data items
  16144.                             are passed to procedures. (This option is used
  16145.                             with the QB and BC commands.)
  16146.  
  16147.    /H                       Displays the highest resolution possible on your
  16148.                             hardware. For example, if you have an EGA,
  16149.                             QuickBASIC displays 43 lines and 80 columns of
  16150.                             text. (This option is used only with the QB
  16151.    Option                   Description
  16152.    ──────────────────────────────────────────────────────────────────────────
  16153.                            text. (This option is used only with the QB
  16154.                             command.)
  16155.  
  16156.    /MBF                     Converts Microsoft Binary format numbers to IEEE
  16157.                             format. See Section B.1.2.3 for more information
  16158.                             about this option (used with the QB and BC
  16159.                             commands).
  16160.  
  16161.    /RUN sourcefile          Runs sourcefile immediately, without first
  16162.                             displaying the QuickBASIC programming
  16163.                             environment. (This option is used only with the
  16164.                             QB command.)
  16165.    ──────────────────────────────────────────────────────────────────────────
  16166.  
  16167.  
  16168.  B.3.2  Separate Compilation Differences
  16169.  
  16170.  Versions 4.0 and 4.5 do not allow separate compilation with the QB command.
  16171.  Use the BC command described in Appendix G, "Compiling and Linking from
  16172.  DOS" to compile and link files without entering the programming environment.
  16173.  
  16174.  B.3.3  User Libraries and BUILDLIB
  16175.  
  16176.    User libraries created for previous versions are not compatible with
  16177.    Versions 4.0 and 4.5. You must rebuild the library from the original
  16178.    source files.
  16179.  
  16180.    User libraries are now called Quick libraries. There is no change in their
  16181.    function or use. The file-name extension of these libraries is now .QLB
  16182.    instead of .EXE. The BUILDLIB utility is no longer required. Quick
  16183.    libraries are now created from within the programming environment or from
  16184.    the link command line. See Appendix H, "Creating and Using Quick
  16185.    Libraries," for more information on this topic.
  16186.  
  16187.  B.3.4  Restrictions on Include Files
  16188.  
  16189.    Include files can contain SUB or FUNCTION procedure declarations but not
  16190.    definitions. If you need to use an old include file with procedure
  16191.    definitions in it, use the Merge command from the File menu to insert the
  16192.    include file into the current module. When you merge an include file
  16193.    containing a SUB procedure, the text of the procedure does not appear in
  16194.    the currently active window. To view or edit its text, choose the SUBs
  16195.    command from the View menu, then select the procedure name in the list
  16196.    box. Once the text is merged, you can run the program.
  16197.  
  16198.    Alternatively, you may decide to put your SUB procedure in a separate
  16199.    module. In this case, you must take one of the following two steps for any
  16200.    shared variables (variables declared in a COMMONSHARED or [[RE]]DIM SHARED
  16201.    statement outside the SUB procedure, or in a SHARED statement inside the
  16202.    SUB procedure), because variables declared this way are shared only within
  16203.    a single module:
  16204.  
  16205.    1. Share the variables between the modules by listing them in COMMON
  16206.       statements at the module level in both modules.
  16207.  
  16208.    2. Pass the variables to the SUB procedure in an argument list.
  16209.  
  16210.    See Chapter 2, "SUB and FUNCTION Procedures," and Chapter 7,
  16211.    "Programming with Modules," for additional information on modules and
  16212.    procedures.
  16213.  
  16214.  B.3.5  Debugging
  16215.  
  16216.    QuickBASIC now helps you debug your programs faster by providing the
  16217.    following debugging features:
  16218.  
  16219.    1. Multiple breakpoints
  16220.  
  16221.    2. Watch expressions, watchpoints, and instant watches
  16222.  
  16223.    3. Improved program tracing
  16224.  
  16225.    4. Full-screen window that displays program text during single-stepping
  16226.  
  16227.    5. The ability to change variable values during execution, then continue
  16228.  
  16229.    6. The ability to edit the program, then continue execution without
  16230.       restarting
  16231.  
  16232.    7. History feature
  16233.  
  16234.    8. Calls menu
  16235.  
  16236.    9. Symbol help
  16237.  
  16238.    The debugging function-key sequences listed in Table B.6 are changed from
  16239.    QuickBASIC Version 2.0:
  16240.  
  16241.    Table B.6  Debugging-Key Changes
  16242.                             QuickBASIC              QuickBASIC
  16243.    Function                 Version 2.0 Key         Version 4.5 Key
  16244.    ──────────────────────────────────────────────────────────────────────────
  16245.    Trace                    ALT+F8                  F8
  16246.  
  16247.    Step                     ALT+F9                  F10
  16248.    ──────────────────────────────────────────────────────────────────────────
  16249.  
  16250.    Note that animation is turned on when you toggle on the Trace On command
  16251.    from the Debug menu, then run your program.
  16252.  
  16253.    See Chapter 9, "Debugging While You Program," in Learning to Use Microsoft
  16254.    QuickBASIC for more information.
  16255.  
  16256.  
  16257.  B.4  Changes to the BASIC Language
  16258.  
  16259.    This section describes enhancements and changes to the BASIC language in
  16260.    Version 4.5 and earlier versions of QuickBASIC. Table B.7 lists the
  16261.    keywords affected by these changes and shows which version of QuickBASIC
  16262.    is affected by each change. A more detailed explanation of the changes
  16263.    appears after the table.
  16264.  
  16265.    Table B.7  Changes to the BASIC Language
  16266. ╓┌─┌───────────────────────────────┌─────────┌──────────┌─────────┌──────────╖
  16267.                                            QuickBASIC Version
  16268.    Keyword                         2.0       3.0        4.0       4.5
  16269.    ──────────────────────────────────────────────────────────────────────────
  16270.    AS                              No        No         Yes       Yes
  16271.  
  16272.    CALL                            No        No         Yes       Yes
  16273.  
  16274.    CASE                            No        Yes        Yes       Yes
  16275.  
  16276.    CLEAR                           No        No         Yes       Yes
  16277.                                            QuickBASIC Version
  16278.    Keyword                         2.0       3.0        4.0       4.5
  16279.    ──────────────────────────────────────────────────────────────────────────
  16280.   CLEAR                           No        No         Yes       Yes
  16281.  
  16282.    CLNG                            No        No         Yes       Yes
  16283.  
  16284.    CLS                             No        Yes        Yes       Yes
  16285.  
  16286.    COLOR                           No        No         Yes       Yes
  16287.  
  16288.    CONST                           No        Yes        Yes       Yes
  16289.  
  16290.    CVL                             No        No         Yes       Yes
  16291.  
  16292.    CVSMBF, CVDMBF                  No        Yes        Yes       Yes
  16293.  
  16294.    DECLARE                         No        No         Yes       Yes
  16295.  
  16296.    DEFLNG                          No        No         Yes       Yes
  16297.  
  16298.                                            QuickBASIC Version
  16299.    Keyword                         2.0       3.0        4.0       4.5
  16300.    ──────────────────────────────────────────────────────────────────────────
  16301. 
  16302.    DIM                             No        No         Yes       Yes
  16303.  
  16304.    DO...LOOP                       No        Yes        Yes       Yes
  16305.  
  16306.    EXIT                            No        Yes        Yes       Yes
  16307.  
  16308.    FILEATTR                        No        No         Yes       Yes
  16309.  
  16310.    FREEFILE                        No        No         Yes       Yes
  16311.  
  16312.    FUNCTION                        No        No         Yes       Yes
  16313.  
  16314.    GET                             No        No         Yes       Yes
  16315.  
  16316.    LCASE$                          No        No         Yes       Yes
  16317.  
  16318.    LEN                             No        No         Yes       Yes
  16319.                                            QuickBASIC Version
  16320.    Keyword                         2.0       3.0        4.0       4.5
  16321.    ──────────────────────────────────────────────────────────────────────────
  16322.   LEN                             No        No         Yes       Yes
  16323.  
  16324.    LSET                            No        No         Yes       Yes
  16325.  
  16326.    LTRIM$                          No        No         Yes       Yes
  16327.  
  16328.    MKL$                            No        No         Yes       Yes
  16329.  
  16330.    MKSMBF$, MKDMBF$                No        Yes        Yes       Yes
  16331.  
  16332.    OPEN                            No        No         Yes       Yes
  16333.  
  16334.    ON UEVENT                       No        No         No        Yes
  16335.  
  16336.    PALETTE                         No        No         Yes       Yes
  16337.  
  16338.    PUT                             No        No         Yes       Yes
  16339.  
  16340.                                            QuickBASIC Version
  16341.    Keyword                         2.0       3.0        4.0       4.5
  16342.    ──────────────────────────────────────────────────────────────────────────
  16343. 
  16344.    RTRIM$                          No        No         Yes       Yes
  16345.  
  16346.    SCREEN                          No        No         Yes       Yes
  16347.  
  16348.    SEEK                            No        No         Yes       Yes
  16349.  
  16350.    SELECT CASE                     No        Yes        Yes       Yes
  16351.  
  16352.    SETMEM                          No        No         Yes       Yes
  16353.  
  16354.    SLEEP                           No        No         No        Yes
  16355.  
  16356.    STATIC                          No        No         Yes       Yes
  16357.  
  16358.    TYPE                            No        No         Yes       Yes
  16359.  
  16360.    UCASE$                          No        No         Yes       Yes
  16361.                                            QuickBASIC Version
  16362.    Keyword                         2.0       3.0        4.0       4.5
  16363.    ──────────────────────────────────────────────────────────────────────────
  16364.   UCASE$                          No        No         Yes       Yes
  16365.  
  16366.    UEVENT                          No        No         No        Yes
  16367.  
  16368.    VARPTR                          No        No         Yes       Yes
  16369.  
  16370.    VARSEG                          No        No         Yes       Yes
  16371.  
  16372.    WIDTH                           No        Yes        Yes       Yes
  16373.    ──────────────────────────────────────────────────────────────────────────
  16374.  
  16375.  
  16376.    The following section explains in more detail the differences in the
  16377.    keywords summarized above.
  16378.  
  16379. ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
  16380.    Keywords           Explanation
  16381.    ──────────────────────────────────────────────────────────────────────────
  16382.    Keywords           Explanation
  16383.    ──────────────────────────────────────────────────────────────────────────
  16384.    AS                 The AS clause allows the use of user-defined types in
  16385.                       DIM, COMMON, and SHARED statements and in DECLARE, SUB,
  16386.                       and FUNCTION parameter lists.
  16387.  
  16388.    CALL               The use of CALL is optional for calling subprograms
  16389.                       declared with the DECLARE statement.
  16390.  
  16391.    CLEAR              The CLEAR statement no longer sets the total size of
  16392.                       the stack; it sets only the stack size required by the
  16393.                       program. QuickBASIC sets the stack size to the amount
  16394.                       specified by the CLEAR statement plus what QuickBASIC
  16395.                       itself requires.
  16396.  
  16397.    CLNG               The CLNG function rounds its argument and returns a
  16398.                       long (four-byte) integer that is equal to the argument.
  16399.  
  16400.    CLS                The CLS statement has been modified to give you greater
  16401.                       flexibility in clearing the screen. Note that
  16402.                       QuickBASIC no longer clears the screen automatically at
  16403.    Keywords           Explanation
  16404.    ──────────────────────────────────────────────────────────────────────────
  16405.                      QuickBASIC no longer clears the screen automatically at
  16406.                       the beginning of each program, as was true in earlier
  16407.                       versions.
  16408.  
  16409.    COLOR, SCREEN,     The COLOR, SCREEN, PALETTE, and WIDTH statements are
  16410.    PALETTE, WIDTH     extended to include screen modes available with the IBM
  16411.                       PS/2(R) VGA and Multicolor Graphics Array (MCGA) cards.
  16412.  
  16413.    CONST              The CONST statement lets you define symbolic constants
  16414.                       to improve program readability and ease program
  16415.                       maintenance.
  16416.  
  16417.    CVL                The CVL function is used to read long integers stored
  16418.                       as strings in random-access data files. CVL converts a
  16419.                       four-byte string created with the MKL$ function back to
  16420.                       a long integer for use in your BASIC program.
  16421.  
  16422.    CVSMBF, CVDMBF     The CVSMBF and CVDMBF functions convert strings
  16423.                       containing Microsoft Binary format numbers to
  16424.    Keywords           Explanation
  16425.    ──────────────────────────────────────────────────────────────────────────
  16426.                      containing Microsoft Binary format numbers to
  16427.                       IEEE-format numbers. Although QuickBASIC Version 4.5
  16428.                       supports these statements, they are considered obsolete
  16429.                       since the IEEE-format is now the QuickBASIC standard.
  16430.  
  16431.    DECLARE            The DECLARE statement allows you to call procedures
  16432.                       from different modules, check the number and type of
  16433.                       arguments passed, and call procedures before they are
  16434.                       defined.
  16435.  
  16436.    DEFLNG             The DEFLNG statement declares all variables, DEF FN
  16437.                       functions, and FUNCTION procedures as having the
  16438.                       long-integer type. That is, unless a variable or
  16439.                       function has been declared in an AS type clause, or it
  16440.                       has an explicit type-definition suffix such as % or $,
  16441.                       it is a long integer by default.
  16442.  
  16443.    DIM                The DIM statement's TO clause lets you specify
  16444.                       subscripts of any integer value, giving you greater
  16445.    Keywords           Explanation
  16446.    ──────────────────────────────────────────────────────────────────────────
  16447.                      subscripts of any integer value, giving you greater
  16448.                       flexibility in array declarations.
  16449.  
  16450.    DO...LOOP          Using DO...LOOP statements gives you more powerful
  16451.                       loops that allow you to write programs with better
  16452.                       structure.
  16453.  
  16454.    EXIT               The use of EXIT {DEF | DO | FOR | FUNCTION | SUB}
  16455.                       statements provides convenient exits from loops and
  16456.                       procedures.
  16457.  
  16458.    FREEFILE, FILEATTR The FREEFILE and FILEATTR functions help you write
  16459.                       applications that do file I/O in a multiple-module
  16460.                       environment.
  16461.  
  16462.    FUNCTION           The FUNCTION...END FUNCTION procedure allows you to
  16463.                       define a multiline procedure that you call from within
  16464.                       an expression. These procedures behave much like
  16465.                       intrinsic functions such as ABS or multiline DEF FN
  16466.    Keywords           Explanation
  16467.    ──────────────────────────────────────────────────────────────────────────
  16468.                      intrinsic functions such as ABS or multiline DEF FN
  16469.                       functions from QuickBASIC Versions 1.0-3.0. However,
  16470.                       unlike a DEF FN function, a FUNCTION procedure can be
  16471.                       defined in one module and called from another. Also,
  16472.                       FUNCTION procedures have local variables and support
  16473.                       recursion.
  16474.  
  16475.    GET, PUT           For I/O operations, the syntax of the GET and PUT
  16476.                       statements is expanded to include records defined with
  16477.                       TYPE...END TYPE statements. This makes use of the FIELD
  16478.                       statement unnecessary.
  16479.  
  16480.    LCASE$, UCASE$,    The following string-handling functions are available
  16481.    LTRIM$, RTRIM$     in Version 4.5:
  16482.  
  16483.                       Function          Return Value
  16484.                       LCASE$            A copy of the string with all letters
  16485.                                         converted to lowercase
  16486.                       UCASE$            A copy of the string with all letters
  16487.    Keywords           Explanation
  16488.    ──────────────────────────────────────────────────────────────────────────
  16489.                      UCASE$            A copy of the string with all letters
  16490.                                         converted to uppercase
  16491.                       LTRIM$            A copy of the string with all leading
  16492.                                         blanks removed
  16493.                       RTRIM$            A copy of the string with all
  16494.                                         trailing blanks removed
  16495.                       LEN               The LEN function has been extended to
  16496.                                         return the number of bytes required
  16497.                                         by any scalar or record variable,
  16498.                                         constant, expression, or array
  16499.                                         element.
  16500.  
  16501.    LSET               The LSET statement is extended to include record
  16502.                       variables as well as string variables. This allows you
  16503.                       to assign one record variable to another record
  16504.                       variable even when the records are not similar.
  16505.  
  16506.    MKL$               The MKL$ function is used to convert long integers to
  16507.                       strings that can be stored in random-access data files.
  16508.    Keywords           Explanation
  16509.    ──────────────────────────────────────────────────────────────────────────
  16510.                      strings that can be stored in random-access data files.
  16511.                       Use the CVL function to change the string back to a
  16512.                       long integer.
  16513.  
  16514.    MKSMBF$, MKDMBF$   The MKSMBF$ and MKDMBF$ functions convert IEEE-format
  16515.                       numbers to strings containing a Microsoft Binary format
  16516.                       number. They are obsolete (but supported) in Version
  16517.                       4.5, which uses the IEEE-format.
  16518.  
  16519.    ON UEVENT          The ON UEVENT statement directs the program to a
  16520.                       specified location when a user-defined event (a UEVENT)
  16521.                       occurs. Use it in the same fashion as other
  16522.                       event-handling statements.
  16523.  
  16524.    OPEN               The OPEN statement now opens two files with the same
  16525.                       name for OUTPUT or APPEND as long as the path names are
  16526.                       different. For example, the following is now permitted:
  16527.  
  16528.                       OPEN "SAMPLE" FOR APPEND AS #1
  16529.    Keywords           Explanation
  16530.    ──────────────────────────────────────────────────────────────────────────
  16531.                      OPEN "SAMPLE" FOR APPEND AS #1
  16532.                       OPEN "TMP\SAMPLE" FOR APPEND AS #2
  16533.  
  16534.                       A binary file mode has been added to the OPEN statement
  16535.                       syntax. See Chapter 3, "File and Device I/O," for
  16536.                       information about using this mode.
  16537.  
  16538.    SEEK               The SEEK statement and function allow you to position a
  16539.                       file at any byte or record. See Chapter 3, "File and
  16540.                       Device I/O," for more information.
  16541.  
  16542.    SELECT CASE        The use of SELECT CASE statements provides a way to
  16543.                       simplify complex condition testing. The CASE clause of
  16544.                       the SELECT CASE statement now accepts any expression
  16545.                       (including variable expressions) as an argument; in
  16546.                       previous versions, only constant expressions were
  16547.                       permitted.
  16548.  
  16549.    SETMEM             The SETMEM function facilitates mixed-language
  16550.    Keywords           Explanation
  16551.    ──────────────────────────────────────────────────────────────────────────
  16552.   SETMEM             The SETMEM function facilitates mixed-language
  16553.                       programming by allowing you to decrease the amount of
  16554.                       dynamic memory allocated by BASIC so it can be used by
  16555.                       procedures in other languages.
  16556.  
  16557.    SLEEP              The SLEEP statement causes the program to pause for an
  16558.                       indicated period of time or until the user presses a
  16559.                       key or an enabled event occurs. The optional argument
  16560.                       indicates the length of the pause (in seconds).
  16561.  
  16562.    STATIC             Omitting the STATIC attribute from SUB and FUNCTION
  16563.                       statements causes variables to be allocated when the
  16564.                       procedures are called, instead of when they are
  16565.                       defined. Such variables do not retain their values
  16566.                       between procedure calls.
  16567.  
  16568.    TYPE               The TYPE...END TYPE statement lets you define a data
  16569.                       type containing elements of different fundamental
  16570.                       types. This simplifies defining and accessing
  16571.    Keywords           Explanation
  16572.    ──────────────────────────────────────────────────────────────────────────
  16573.                      types. This simplifies defining and accessing
  16574.                       random-access file records.
  16575.  
  16576.    UEVENT             Enables, suspends, or disables a user-defined event.
  16577.    {ON|STOP|OFF}      The UEVENT statements are used in the same way as other
  16578.                       event-trapping statements.
  16579.  
  16580.    VARPTR             The VARPTR function now returns the 16-bit integer
  16581.                       offset of the BASIC variable or array element. The
  16582.                       offset is from the beginning of the segment that
  16583.                       contains the variable or array element.
  16584.  
  16585.    VARSEG             The VARSEG function returns the segment address of its
  16586.                       argument. This allows you to set DEF SEG appropriately
  16587.                       for use with PEEK, POKE, BLOAD, BSAVE, and CALL
  16588.                       ABSOLUTE. It also permits you to get the appropriate
  16589.                       segment for use with CALL INTERRUPT when executing
  16590.                       operating-system or BIOS interrupts.
  16591.  
  16592.    Keywords           Explanation
  16593.    ──────────────────────────────────────────────────────────────────────────
  16594. 
  16595.    WIDTH              A new argument on the WIDTH statement lets your
  16596.                       programs use the extended line modes on machines
  16597.                       equipped with EGA, VGA, and MCGA adapter cards.
  16598.    ──────────────────────────────────────────────────────────────────────────
  16599.  
  16600.  
  16601.    ──────────────────────────────────────────────────────────────────────────
  16602.    NOTE
  16603.      You can no longer conditionally execute NEXT and WEND statements using
  16604.      the single-line IF...THEN...ELSE statement.
  16605.    ──────────────────────────────────────────────────────────────────────────
  16606.  
  16607.  
  16608.  B.5  File Compatibility
  16609.  
  16610.    All versions of QuickBASIC are source-code compatible; source code created
  16611.    for a previous version compiles under Version 4.5, except as noted in
  16612.    Section B.3.4, "Restrictions on Include Files." QuickBASIC 4.5 translates
  16613.    QuickBASIC 4.0 binary files. If you encounter difficulty translating other
  16614.    binary files, save the program as an ASCII (text) format in QuickBASIC
  16615.    4.0, then load it with QuickBASIC 4.5. You must recompile object files and
  16616.    user libraries created with previous versions of QuickBASIC.
  16617.  
  16618.  
  16619.  
  16620.  ────────────────────────────────────────────────────────────────────────────
  16621.  Appendix C  Limits in QuickBASIC
  16622.  
  16623.    QuickBASIC and the BC compiler offer programming versatility, but both
  16624.    have limitations in order to keep file size and complexity manageable. As
  16625.    a result, you may reach these limits in some situations. This appendix
  16626.    lists the boundaries you may encounter.
  16627.  
  16628.    Table C.1  QuickBASIC Limits
  16629. ╓┌─┌────────────────────────┌───────────────────────┌────────────────────────╖
  16630.                             Maximum                 Minimum
  16631.    ──────────────────────────────────────────────────────────────────────────
  16632.    Names and Strings
  16633.    Variable names           40 characters           1 character
  16634.                             Maximum                 Minimum
  16635.    ──────────────────────────────────────────────────────────────────────────
  16636.   Variable names           40 characters           1 character
  16637.  
  16638.    String length            32,767 characters       0 characters
  16639.  
  16640.    Integers                 32,767                  -32,768
  16641.  
  16642.    Long integers            2,147,483,647           -2,147,483,648
  16643.  
  16644.    Single-precision numbers 3.402823 E+38           1.401298 E-45
  16645.    (positive)
  16646.  
  16647.    Single-precision numbers -1.401298 E-45          -3.402823 E+38
  16648.    (negative)
  16649.  
  16650.    Double-precision numbers 1.797693134862315 D+308 4.940656458412465 D-324
  16651.    (positive)
  16652.  
  16653.    Double-precision numbers -4.940656458412465      -1.797693134862315 D+308
  16654.    (negative)               D-324
  16655.                             Maximum                 Minimum
  16656.    ──────────────────────────────────────────────────────────────────────────
  16657.   (negative)               D-324
  16658.  
  16659.    Arrays
  16660.    Array size (all
  16661.    elements)
  16662.      Static                 65,535 bytes (64K)      1
  16663.      Dynamic                Available memory
  16664.  
  16665.    Array dimensions         8                       1
  16666.  
  16667.    Array subscripts         32,767                  -32,768
  16668.  
  16669.    Files and Procedures
  16670.    Number of arguments      60 interpreted          0 passed to a procedure
  16671.  
  16672.    Nesting of include files 5 levels                0
  16673.  
  16674.    Procedure size           65,535 bytes (64K)      0
  16675.    (interpreted)
  16676.                             Maximum                 Minimum
  16677.    ──────────────────────────────────────────────────────────────────────────
  16678.   (interpreted)
  16679.  
  16680.    Module size (compiled)   65,535 bytes (64K)      0
  16681.  
  16682.    Data files open          255                     0 simultaneously
  16683.  
  16684.    Data file record number  2,147,483,647           1
  16685.  
  16686.    Data file record size    32,767 bytes (32K)      1 byte
  16687.    (bytes)
  16688.  
  16689.    Data file size           Available disk space    0
  16690.  
  16691.    Path names               127 characters          1 character
  16692.  
  16693.    Error message numbers    255                     1
  16694.  
  16695.    Editing in the Quick-BASIC Environment
  16696.    Text box entry           128 characters          0 characters
  16697.                             Maximum                 Minimum
  16698.    ──────────────────────────────────────────────────────────────────────────
  16699.   Text box entry           128 characters          0 characters
  16700.  
  16701.    "Search for" string      128                     1
  16702.  
  16703.    "Change to" string       40                      0
  16704.  
  16705.    Placemarkers             4                       0
  16706.  
  16707.    Watchpoints and/or watch 8                       0 expressions
  16708.  
  16709.    Number of lines in       10                      0 Immediate window
  16710.  
  16711.    Characters in View       255                     0 window on one line
  16712.  
  16713.    Length of COMMAND$       124                     0 string
  16714.    ──────────────────────────────────────────────────────────────────────────
  16715.  
  16716.  
  16717.  
  16718.  ────────────────────────────────────────────────────────────────────────────
  16719.  Appendix D  Keyboard Scan Codes and ASCII Character Codes
  16720.  
  16721.  
  16722.  D.1  Keyboard Scan Codes
  16723.  
  16724.    The table on the next page shows the DOS keyboard scan codes. These codes
  16725.    are returned by the INKEY$ function.
  16726.  
  16727.    Key combinations with NUL in the Char column return two bytes──a null byte
  16728.    (&H00) followed by the value listed in the Dec and Hex columns. For
  16729.    example, pressing ALT+F1 returns a null byte followed by a byte containing
  16730.    104 (&H68).
  16731.  
  16732.    ┌────────┬───────┬────────────┬─────────────┬─────────────┬──────────────┐
  16733.    │        │       │            │ ASCII or    │  ASCII or   │   ASCII or   │
  16734.    │        │ Scan  │ ASCII or   │ Extended    │  Extended   │   Extended   │
  16735.    │  Key   │ Code  │ Extended   │ with SHIFT  │  with CTRL  │   with ALT   │
  16736.    ├────────┼───────┼────────────┼─────────────┼─────────────┼──────────────┤
  16737.    │        │Dec Hex│Dec Hex Char│Dec Hex Char │Dec Hex Char │ Dec Hex Char │
  16738.    ├────────┼───────┼────────────┼─────────────┼─────────────┼──────────────┤
  16739.    │ESC     │ 1  01 │ 27  1B     │ 27  1B      │ 27  1B      │              │
  16740.    │1!      │ 2  02 │ 49  31  1  │ 33  21   !  │             │ 120  78  NUL │
  16741.    │2@      │ 3  03 │ 50  32  2  │ 64  40   @  │  3  03 NUL  │ 121  79  NUL │
  16742.    │3#      │ 4  04 │ 51  33  3  │ 35  23   #  │             │ 122  7A  NUL │
  16743.    │4$      │ 5  05 │ 52  34  4  │ 36  24   $  │             │ 123  7B  NUL │
  16744.    │5%      │ 6  06 │ 53  35  5  │ 37  25   %  │             │ 124  7C  NUL │
  16745.    │6^      │ 7  07 │ 54  36  6  │ 94  5E   ^  │ 30  IE      │ 125  7D  NUL │
  16746.    │7&      │ 8  08 │ 55  37  7  │ 38  26   &  │             │ 126  7E  NUL │
  16747.    │8*      │ 9  09 │ 56  38  8  │ 42  2A   *  │             │ 127  7F  NUL │
  16748.    │9(      │10  0A │ 57  39  9  │ 40  28   (  │             │ 128  80  NUL │
  16749.    │0)      │11  0B │ 48  30  0  │ 41  29   )  │             │ 129  81  NUL │
  16750.    │-_      │12  0C │ 45  2D  -  │ 95  5F   -  │ 31  IF      │ 130  82  NUL │
  16751.    │=+      │13  0D │ 61  3D  =  │ 43  2B   +  │             │ 131  83  NUL │
  16752.    │BKSP    │14  0E │  8  08     │  8  08      │127  7F      │              │
  16753.    │TAB     │15  0F │  9  09     │ 15  OF   NUL│             │              │
  16754.    │Q       │16  10 │113  71  q  │ 81  51   Q  │ 17  11      │  16  10  NUL │
  16755.    │W       │17  11 │119  77  w  │ 87  57   W  │ 23  17      │  17  11  NUL │
  16756.    │E       │18  12 │101  65  e  │ 69  45   E  │  5  05      │  18  12  NUL │
  16757.    │R       │19   13│114  72   r │ 82  52   R  │ 18  12      │  19  13  NUL │
  16758.    │T       │20   14│116  74   t │ 84  54   T  │ 20  14      │  20  14  NUL │
  16759.    │Y       │21   15│121  79   y │ 89  59   Y  │ 25  19      │  21  15  NUL │
  16760.    │U       │22   16│117  75   u │ 85  55   U  │ 21  15      │  22  16  NUL │
  16761.    │I       │23   17│105  69   i │ 73  49   I  │  9  09      │  23  17  NUL │
  16762.    │O       │24   18│111  6F   o │ 79  4F   O  │ 15  0F      │  24  18  NUL │
  16763.    │P       │25   19│112  70   p │ 80  50   P  │ 16  10      │  25  19  NUL │
  16764.    │[{      │26   1A│ 91  5B   [ │123  7B   {  │ 27  1B      │              │
  16765.    │]}      │27   1B│ 93  5D   ] │125  7D   }  │ 29  1D      │              │
  16766.    │ENTER   │28   1C│ 13  OD   CR│ 13  OD   CR │ 10  OA   LF │              │
  16767.    │CTRL    │29   1D│            │             │             │              │
  16768.    │A       │30   1E│ 97  61   a │ 65  41   A  │  1  01      │  30  1E  NUL │
  16769.    │S       │31   1F│115  73   s │ 83  53   S  │ 19  13      │  31  1F  NUL │
  16770.    │D       │32   20│100  64   d │ 68  44   D  │  4  04      │  32  20  NUL │
  16771.    │F       │33   21│102  66   f │ 70  46   F  │  6  06      │  33  21  NUL │
  16772.    │G       │34   22│103  67   g │ 71  47   G  │  7  07      │  34  22  NUL │
  16773.    │H       │35   23│104  68   h │ 72  48   H  │  8  08      │  35  23  NUL │
  16774.    │J       │36   24│106  6A   j │ 74  4A   J  │ 10  0A      │  36  24  NUL │
  16775.    │K       │37   25│107  6B   k │ 75  4B   K  │ 11  0B      │  37  25  NUL │
  16776.    │L       │38   26│108  6C   l │ 76  4C   L  │ 12  0C      │  38  26  NUL │
  16777.    │;:      │39   27│ 59  3B   ; │ 58  3A   :  │             │              │
  16778.    │'"      │40   28│ 39  27   ' │ 34  22   "  │             │              │
  16779.    │`~      │41   29│ 96  60   ` │126  7E   ~  │             │              │
  16780.    │L SHIFT │42   2A│            │             │             │              │
  16781.    │\|      │43   2B│ 92  5C   \ │124  7C   |  │ 28  1C      │              │
  16782.    │Z       │44  2C │122  7A  z  │ 90  5A   Z  │ 26  1A      │  44  2C  NUL │
  16783.    │X       │45  2D │120  78  x  │ 88  58   X  │ 24  18      │  45  2D  NUL │
  16784.    │C       │46  2E │ 99  63  c  │ 67  43   C  │  3  03      │  46  2E  NUL │
  16785.    │V       │47  2F │118  76  v  │ 86  56   V  │ 22  16      │  47  2F  NUL │
  16786.    │B       │48  30 │ 98  62  b  │ 66  42   B  │  2  OE      │  48  30  NUL │
  16787.    │N       │49  31 │110  6E  n  │ 78  4E   N  │ 14  OD      │  49  31  NUL │
  16788.    │M       │50  32 │109  6D  m  │ 77  4D   M  │ 13          │  50  32  NUL │
  16789.    │,<      │51  33 │ 44  2C  '  │ 60  3C   <  │             │              │
  16790.    │.>      │52  34 │ 46  2E  .  │ 62  3E   >  │             │              │
  16791.    │/?      │53  35 │ 47  2F  /  │ 63  3F   ?  │             │              │
  16792.    │R SHIFT │54  36 │            │             │             │              │
  16793.    │* PRTSC │55  37 │ 42  2A  *  │     INT  5 │ 16  10      │              │
  16794.    │ALT     │56  38 │            │             │             │              │
  16795.    │SPACE   │57  39 │ 32  20  SPC│ 32  20   SPC│ 32  20  SPC │  32  20  SPC │
  16796.    │CAPS    │58  3A │            │             │             │              │
  16797.    │F1      │59  3B │ 59  3B  NUL│ 84  54   NUL│ 94  5E  NUL │ 104  68  NUL │
  16798.    │F2      │60  3C │ 60  3C  NUL│ 85  55   NUL│ 95  5F  NUL │ 105  69  NUL │
  16799.    │F3      │61  3D │ 61  3D  NUL│ 86  56   NUL│ 96  60  NUL │ 106  6A  NUL │
  16800.    │F4      │62  3E │ 62  3E  NUL│ 87  57   NUL│ 97  61  NUL │ 107  6B  NUL │
  16801.    │F5      │63  3F │ 63  3F  NUL│ 88  58   NUL│ 98  62  NUL │ 108  6C  NUL │
  16802.    │F6      │64  40 │ 64  40  NUL│ 89  59   NUL│ 99  63  NUL │ 109  6D  NUL │
  16803.    │F7      │65  41 │ 65  41  NUL│ 90  5A   NUL│100  64  NUL │ 110  6E  NUL │
  16804.    │F8      │66  42 │ 66  46  NUL│ 91  5B   NUL│101  65  NUL │ 111  6F  NUL │
  16805.    │F9      │67  43 │ 67  43  NUL│ 92  5C   NUL│102  66  NUL │ 112  70  NUL │
  16806.    │F10     │68  44 │ 68  44  NUL│ 93  5D   NUL│103  67  NUL │ 113  71  NUL │
  16807.    │NUM     │69  45 │            │             │             │              │
  16808.    │SCROLL  │70  46 │            │             │             │              │
  16809.    │HOME    │71  47 │ 71  47 NUL │ 55  37   7  │119  77  NUL │              │
  16810.    │UP      │72  48 │ 72  48 NUL │ 56  38   8  │             │              │
  16811.    │PGUP    │73  49 │ 73  49 NUL │ 57  39   9  │132  84  NUL │              │
  16812.    │GREY-   │74  4A │ 45  2D  -  │ 45  2D   -  │             │              │
  16813.    │LEFT    │75  4B │ 75  4B NUL │ 52  34   4  │115  73  NUL │              │
  16814.    │CENTER  │76  4C │            │ 53  35   5  │             │              │
  16815.    │RIGHT   │77  4D │ 77  4D NUL │ 54  36   6  │116  74  NUL │              │
  16816.    │GREY+   │78  4E │ 43  2B  +  │ 43  2b   +  │             │              │
  16817.    │END     │79  4F │ 79  4F NUL │ 49  31   1  │117  75  NUL │              │
  16818.    │DOWN    │80  50 │ 80  50 NUL │ 50  32   2  │             │              │
  16819.    │PGDN    │81  51 │ 81  51 NUL │ 51  33   3  │118  76  NUL │              │
  16820.    │INS     │82  52 │ 82  52 NUL │ 48  30   0  │             │              │
  16821.    │DEL     │83  53 │ 83  53 NUL │ 46  2E   .  │             │              │
  16822.    └────────┴───────┴────────────┴─────────────┴─────────────┴──────────────┘
  16823.  
  16824.  
  16825.  D.2  ASCII Character Codes
  16826.  
  16827.    ┌─────────────────────┐  ┌────────────┐  ┌────────────┐  ┌────────────┐
  16828.    │Ctrl D   H  Char Code│  │Dec Hex Char│  │Dec Hex Char│  │Dec Hex Char│
  16829.    ├───┬───┬───┬────┬────┤  ├───┬───┬────┤  ├───┬───┬────┤  ├───┬───┬────┤
  16830.    │^@ │  0│00 │    │ NUL│  │ 32│ 20│    │  │ 64│40 │ @  │  │ 96│60 │ `  │
  16831.    │^A │  1│01 │   │ SOH│  │ 33│ 21│ !  │  │ 65│41 │ A  │  │ 97│61 │ a  │
  16832.    │^B │  2│02 │   │ STX│  │ 34│ 22│ "  │  │ 66│42 │ B  │  │ 98│62 │ b  │
  16833.    │^C │  3│03 │   │ ETX│  │ 35│ 23│ #  │  │ 67│43 │ C  │  │ 99│63 │ c  │
  16834.    │^D │  4│04 │   │ EOT│  │ 36│ 24│ $  │  │ 68│44 │ D  │  │100│64 │ d  │
  16835.    │^E │  5│05 │   │ ENQ│  │ 37│ 25│ %  │  │ 69│45 │ E  │  │101│65 │ e  │
  16836.    │^F │  6│06 │   │ ACK│  │ 38│ 26│ &  │  │ 70│46 │ F  │  │102│66 │ f  │
  16837.    │^G │  7│07 │   │ BEL│  │ 39│ 27│ '  │  │ 71│47 │ G  │  │103│67 │ g  │
  16838.    │^H │  8│08 │   │ BS │  │ 40│ 28│ (  │  │ 72│48 │ H  │  │104│68 │ h  │
  16839.    │^I │  9│09 │    │ HT │  │ 41│ 29│ )  │  │ 73│49 │ I  │  │105│69 │ i  │
  16840.    │^J │ 10│0A │    │ LF │  │ 42│ 2A│ *  │  │ 74│4A │ J  │  │106│6A │ j  │
  16841.    │^K │ 11│0B │    │ VT │  │ 43│ 2B│ +  │  │ 75│4B │ K  │  │107│6B │ k  │
  16842.    │^L │ 12│0C │    │ FF │  │ 44│ 2C│ ,  │  │ 76│4C │ L  │  │108│6C │ l  │
  16843.    │^M │ 13│0D │    │ CR │  │ 45│ 2D│ -  │  │ 77│4D │ M  │  │109│6D │ m  │
  16844.    │^N │ 14│0E │   │ SO │  │ 46│ 2E│ .  │  │ 78│4E │ N  │  │110│6E │ n  │
  16845.    │^O │ 15│0F │    │ SI │  │ 47│ 2F│ /  │  │ 79│4F │ O  │  │111│6F │ o  │
  16846.    │^P │ 16│10 │   │ DLE│  │ 48│ 30│ 0  │  │ 80│50 │ P  │  │112│70 │ p  │
  16847.    │^Q │ 17│11 │   │ DC1│  │ 49│ 31│ 1  │  │ 81│51 │ Q  │  │113│71 │ q  │
  16848.    │^R │ 18│12 │   │ DC2│  │ 50│ 32│ 2  │  │ 82│52 │ R  │  │114│72 │ r  │
  16849.    │^S │ 19│13 │   │ DC3│  │ 51│ 33│ 3  │  │ 83│53 │ S  │  │115│73 │ s  │
  16850.    │^T │ 20│14 │   │ DC4│  │ 52│ 34│ 4  │  │ 84│54 │ T  │  │116│74 │ t  │
  16851.    │^U │ 21│15 │   │ NAK│  │ 53│ 35│ 5  │  │ 85│55 │ U  │  │117│75 │ u  │
  16852.    │^V │ 22│ 16│   │ SYN│  │ 54│ 36│ 6  │  │ 86│ 56│ V  │  │118│ 76│ v  │
  16853.    │^W │ 23│ 17│   │ ETB│  │ 55│ 37│ 7  │  │ 87│ 57│ W  │  │119│ 77│ w  │
  16854.    │^X │ 24│ 18│   │ CAN│  │ 56│ 38│ 8  │  │ 88│ 58│ X  │  │120│ 78│ x  │
  16855.    │^Y │ 25│ 19│   │ EM │  │ 57│ 39│ 9  │  │ 89│ 59│ Y  │  │121│ 79│ y  │
  16856.    │^Z │ 26│ 1A│   │ SUB│  │ 58│ 3A│ :  │  │ 90│ 5A│ Z  │  │122│ 7A│ z  │
  16857.    │^[ │ 27│ 1B│   │ ESC│  │ 59│ 3B│ ;  │  │ 91│ 5B│ [  │  │123│ 7B│ {  │
  16858.    │^\ │ 28│ 1C│   │ FS │  │ 60│ 3C│ <  │  │ 92│ 5C│ \  │  │124│ 7C│ |  │
  16859.    │^} │ 29│ 1D│   │ GS │  │ 61│ 3D│ =  │  │ 93│ 5D│ ]  │  │125│ 7D│ }  │
  16860.    │^^ │ 30│ 1E│   │ RS │  │ 62│ 3E│ >  │  │ 94│ 5E│ ^  │  │126│ 7E│ ~  │
  16861.    │^_ │ 31│ 1F│   │ US │  │ 63│ 3F│ ?  │  │ 95│ 5F│ _  │  │127│ 7F│    │
  16862.    └───┴───┴───┴────┴────┘  └───┴───┴────┘  └───┴───┴────┘  └───┴───┴────┘
  16863.  
  16864.  
  16865.             ┌────────────┐  ┌────────────┐  ┌────────────┐  ┌────────────┐
  16866.             │Dec Hex Char│  │Dec Hex Char│  │Dec Hex Char│  │Dec Hex Char│
  16867.             ├───┬───┬────┤  ├───┬───┬────┤  ├───┬───┬────┤  ├───┬───┬────┤
  16868.             │128│ 80│ Ç  │  │160│ A0│ á  │  │192│ C0│ └  │  │224│ E0│ α  │
  16869.             │129│ 81│ ü  │  │161│ A1│ í  │  │193│ C1│ ┴  │  │225│ E1│ ß  │
  16870.             │130│ 82│ é  │  │162│ A2│ ó  │  │194│ C2│ ┬  │  │226│ E2│ Γ  │
  16871.             │131│ 83│ â  │  │163│ A3│ ú  │  │195│ C3│ ├  │  │227│ E3│ π  │
  16872.             │132│ 84│ ä  │  │164│ A4│ ñ  │  │196│ C4│ ─  │  │228│ E4│ Σ  │
  16873.             │133│ 85│ à  │  │165│ A5│ Ñ  │  │197│ C5│ ┼  │  │229│ E5│ σ  │
  16874.             │134│ 86│ å  │  │166│ A6│ ª  │  │198│ C6│ ╞  │  │230│ E6│ µ  │
  16875.             │135│ 87│ ç  │  │167│ A7│ º  │  │199│ C7│ ╟  │  │231│ E7│ τ  │
  16876.             │136│ 88│ ê  │  │168│ A8│ ¿  │  │200│ C8│ ╚  │  │232│ E8│ Φ  │
  16877.             │137│ 89│ ë  │  │169│ A9│ ⌐  │  │201│ C9│ ╔  │  │233│ E9│ Θ  │
  16878.             │138│ 90│ è  │  │170│ AA│ ¬  │  │202│ CA│ ╩  │  │234│ EA│ Ω  │
  16879.             │139│ 91│ ï  │  │171│ AB│ ½  │  │203│ CB│ ╦  │  │235│ EB│ δ  │
  16880.             │140│ 92│ î  │  │172│ AC│ ¼  │  │204│ CC│ ╠  │  │236│ EC│ ∞  │
  16881.             │141│ 93│ ì  │  │173│ AD│ ¡  │  │205│ CD│ ═  │  │237│ ED│ φ  │
  16882.             │142│ 94│ Ä  │  │174│ AE│ «  │  │206│ CE│ ╬  │  │238│ EE│ ε  │
  16883.             │143│ 95│ Å  │  │175│ AF│ »  │  │207│ CF│ ╧  │  │239│ EF│ ∩  │
  16884.             │144│ 96│ É  │  │176│ B0│ ░  │  │208│ D0│ ╨  │  │240│ F0│ ≡  │
  16885.             │145│ 97│ æ  │  │177│ B1│ ▒  │  │209│ D1│ ╤  │  │241│ F1│ ±  │
  16886.             │146│ 98│ Æ  │  │178│ B2│ ▓  │  │210│ D2│ ╥  │  │242│ F2│ ≥  │
  16887.             │147│ 99│ ô  │  │179│ B3│ │  │  │211│ D3│ ╙  │  │243│ F3│ ≤  │
  16888.             │148│ 9A│ ö  │  │180│ B4│ ┤  │  │212│ D4│ ╘  │  │244│ F4│ ⌠  │
  16889.             │149│ 9B│ ò  │  │181│ B5│ ╡  │  │213│ D5│ ╒  │  │245│ F5│ ⌡  │
  16890.             │150│ 96│ û  │  │182│ B6│ ╢  │  │214│ D6│ ╓  │  │246│ F6│ ÷  │
  16891.             │151│ 97│ ù  │  │183│ B7│ ╖  │  │215│ D7│ ╫  │  │247│ F7│ ≈  │
  16892.             │152│ 98│ ÿ  │  │184│ B8│ ╕  │  │216│ D8│ ╪  │  │248│ F8│ °  │
  16893.             │153│ 99│ Ö  │  │185│ B9│ ╣  │  │217│ D9│ ≈  │  │249│ F9│ ∙  │
  16894.             │154│ 9A│ Ü  │  │186│ BA│ ║  │  │218│ DA│ ┌  │  │250│ FA│ ·  │
  16895.             │155│ 9B│ ¢  │  │187│ BB│ ╗  │  │219│ DB│ █  │  │251│ FB│ √  │
  16896.             │156│ 9C│ £  │  │188│ BC│ ╝  │  │220│ DC│ ▄  │  │252│ FC│ ⁿ  │
  16897.             │157│ 9D│ ¥  │  │189│ BD│ ╜  │  │221│ DD│ ▌  │  │253│ FD│ ²  │
  16898.             │158│ 9E│ ₧  │  │190│ BE│ ╛  │  │222│ DE│ ▐  │  │254│ FE│ ■  │
  16899.             │159│ 9F│ ƒ  │  │191│ BF│ ┐  │  │223│ DF│ ▀  │  │255│ FF│    │
  16900.             └───┴───┴────┘  └───┴───┴─┴──┘  └───┴───┴────┘  └───┴───┴────┘
  16901.  
  16902.  
  16903.  
  16904.  ────────────────────────────────────────────────────────────────────────────
  16905.  Appendix E  BASIC Reserved Words
  16906.  
  16907.    The following is a list of Microsoft BASIC reserved words:
  16908.  
  16909.    ──────────────────────────────────────────────────────────────────────────
  16910.    ABS               ELSE             LOOP              SEEK
  16911.    ACCESS             ELSEIF           LPOS              SEG
  16912.    ALIAS              END              LPRINT            SELECT
  16913.    AND                ENDIF            LSET              SETMEM
  16914.    ANY                ENVIRON          LTRIM$            SGN
  16915.    APPEND             ENVIRON$         MID$              SHARED
  16916.    AS                 EOF              MKD$              SHELL
  16917.    ASC               EQV               MKDIR             SIGNAL
  16918.    ATN               ERASE            MKDMBF$           SIN
  16919.    BASE               ERDEV            MKI$              SINGLE
  16920.    BEEP              ERDEV$           MKL$              SLEEP
  16921.    BINARY             ERL              MKS$              SOUND
  16922.    BLOAD             ERR              MKSMBF$           SPACE$
  16923.    BSAVE             ERROR            MOD                SPC
  16924.    BYVAL              EXIT             NAME              SQR
  16925.    CALL              EXP              NEXT              STATIC
  16926.    CALLS             FIELD            NOT                STEP
  16927.    CASE              FILEATTR         OCT$              STICK
  16928.    CDBL              FILES            OFF                STOP
  16929.    CDECL              FIX              ON                 STR$
  16930.    CHAIN             FOR              OPEN              STRIG
  16931.    CHDIR             FRE              OPTION            STRING
  16932.    CHR$              FREEFILE         OR                 STRING$
  16933.    CINT              FUNCTION         OUT               SUB
  16934.    CIRCLE            GET              OUTPUT             SWAP
  16935.    CLEAR             GOSUB            PAINT             SYSTEM
  16936.    CLNG              GOTO             PALETTE           TAB
  16937.    CLOSE             HEX$             PCOPY             TAN
  16938.    CLS               IF               PEEK              THEN
  16939.    COLOR             IMP               PEN               TIME$
  16940.    COM               INKEY$           PLAY              TIMER
  16941.    COMMAND$          INP              PMAP              TO
  16942.    COMMON            INPUT            POINT             TROFF
  16943.    CONST             INPUT$           POKE              TRON
  16944.    COS               INSTR            POS               TYPE
  16945.    CSNG              INT              PRESET            UBOUND
  16946.    CSRLIN            INTEGER           PRINT             UCASE$
  16947.    CVD               IOCTL            PSET              UEVENT
  16948.    CVDMBF            IOCTL$            PUT               UNLOCK
  16949.    CVI               IS                RANDOM             UNTIL
  16950.    CVL               KEY              RANDOMIZE         USING
  16951.    CVS               KILL             READ              VAL
  16952.    CVSMBF            LBOUND           REDIM             VARPTR
  16953.    DATA              LCASE$           REM               VARPTR$
  16954.    DATE$             LEFT$            RESET             VARSEG
  16955.    DECLARE           LEN              RESTORE           VIEW
  16956.    DEF               LET              RESUME            WAIT
  16957.    DEFDBL            LINE             RETURN            WEND
  16958.    DEFINT            LIST              RIGHT$            WHILE
  16959.    DEFLNG            LOC              RMDIR             WIDTH
  16960.    DEFSNG            LOCAL             RND               WINDOW
  16961.    DEFSTR            LOCATE           RSET              WRITE
  16962.    DIM               LOCK             RTRIM$            XOR
  16963.    DO                LOF              RUN
  16964.    DOUBLE             LOG              SADD
  16965.    DRAW              LONG              SCREEN
  16966.    ──────────────────────────────────────────────────────────────────────────
  16967.  
  16968.  
  16969.  
  16970.  ────────────────────────────────────────────────────────────────────────────
  16971.  Appendix F  Metacommands
  16972.  
  16973.    This appendix describes the QuickBASIC metacommands──commands that direct
  16974.    QuickBASIC to handle your program in a particular way. The first section
  16975.    describes the format used for metacommands. The next two sections describe
  16976.    specific metacommands.
  16977.  
  16978.    By using the metacommands, you can:
  16979.  
  16980.    ■ Read in and compile other BASIC source files at specific points during
  16981.      compilation ($INCLUDE)
  16982.  
  16983.    ■ Control the allocation of dimensioned arrays ($STATIC and $DYNAMIC)
  16984.  
  16985.  
  16986.  F.1  Metacommand Syntax
  16987.  
  16988.    Metacommands begin with a dollar sign ($) and are always enclosed in a
  16989.    program comment. More than one metacommand can be given in one comment.
  16990.    Multiple metacommands are separated by white-space characters (space or
  16991.    tab). Metacommands that take arguments have a colon between the
  16992.    metacommand and the argument:
  16993.  
  16994.    REM $METACOMMAND [[ : argument ]]
  16995.  
  16996.    String arguments must be enclosed in single quotation marks. White-space
  16997.    characters between elements of a metacommand are ignored. The following
  16998.    are all valid forms for metacommands:
  16999.  
  17000.    REM $STATIC $INCLUDE:  'datadefs.bi'
  17001.    REM     $STATIC    $INCLUDE :  'datadefs.bi'
  17002.    ' $STATIC $INCLUDE: 'datadefs.bi'
  17003.    '     $STATIC    $INCLUDE :  'datadefs.bi'
  17004.  
  17005.    Note that no spaces appear between the dollar sign and the rest of the
  17006.    metacommand.
  17007.  
  17008.    If you want to refer to a metacommand in a description but do not want it
  17009.    to execute, place a character that is not a tab or space before the first
  17010.    dollar sign on the line. For example, on the following line both
  17011.    metacommands are ignored:
  17012.  
  17013.    REM x$STATIC $INCLUDE:  'datadefs.bi'
  17014.  
  17015.  
  17016.  F.2  Processing Additional Source Files: $INCLUDE
  17017.  
  17018.    The $INCLUDE metacommand instructs the compiler to temporarily switch from
  17019.    processing one file and instead to read program statements from the BASIC
  17020.    file named in the argument. When the end of the included file is reached,
  17021.    the compiler returns to processing the original file. Because compilation
  17022.    begins with the line immediately following the line in which $INCLUDE
  17023.    occurred, $INCLUDE should be the last statement on a line. The following
  17024.    statement is correct:
  17025.  
  17026.    DEFINT I-N   ' $INCLUDE: 'COMMON.BAS'
  17027.  
  17028.    There are two restrictions on using include files:
  17029.  
  17030.    1. Included files must not contain SUB or FUNCTION statements.
  17031.  
  17032.    2. Included files created with BASICA must be saved with the ,A option.
  17033.  
  17034.  
  17035.  F.3  Dimensioned Array Allocation: $STATIC and $DYNAMIC
  17036.  
  17037.    The $STATIC and $DYNAMIC metacommands tell the compiler how to allocate
  17038.    memory for arrays. Neither of these metacommands takes an argument:
  17039.  
  17040.    'Make all arrays dynamic.
  17041.  
  17042.    '$DYNAMIC
  17043.  
  17044.    $STATIC sets aside storage for arrays during compilation. When the $STATIC
  17045.    metacommand is used, the ERASE statement reinitializes all array values to
  17046.    zero (numeric arrays) or the null string (string arrays) but does not
  17047.    remove the array. The REDIM statement has no effect on $STATIC arrays.
  17048.  
  17049.    $DYNAMIC allocates storage for arrays while the program is running. This
  17050.    means that the ERASE statement removes the array and frees the memory it
  17051.    took for other uses. You can also use the REDIM statement to change the
  17052.    size of a $DYNAMIC array.
  17053.  
  17054.    The $STATIC and $DYNAMIC metacommands affect all arrays except implicitly
  17055.    dimensioned arrays (arrays not declared in a DIM statement). Implicitly
  17056.    dimensioned arrays are always allocated as if $STATIC had been used.
  17057.  
  17058.  
  17059.  
  17060.  ────────────────────────────────────────────────────────────────────────────
  17061.  Appendix G  Compiling and Linking from DOS
  17062.  
  17063.    This appendix explains how to compile and link outside the QuickBASIC
  17064.    environment. You might want to do this for some of the following reasons:
  17065.  
  17066.    ■ To use a different text editor
  17067.  
  17068.    ■ To create executable programs that can be debugged with the Microsoft
  17069.      CodeView debugger
  17070.  
  17071.    ■ To create listing files for use in debugging a stand-alone executable
  17072.      program
  17073.  
  17074.    ■ To use options not available within the QuickBASIC environment, such as
  17075.      storing arrays in row order
  17076.  
  17077.    ■ To link with NOCOM.OBJ or NOEM.OBJ (files supplied with QuickBASIC),
  17078.      which reduce the size of executable files in programs that do not use
  17079.      the COM statement or are always used with a math coprocessor
  17080.  
  17081.    When you finish this appendix you will understand how to
  17082.  
  17083.    ■ Compile from the DOS command line with the BC command
  17084.  
  17085.    ■ Create executable files and link program object files with the LINK
  17086.      command
  17087.  
  17088.    ■ Create and maintain stand-alone (.LIB) libraries with the LIB command
  17089.  
  17090.  
  17091.  G.1  BC, LINK, and LIB
  17092.  
  17093.    The Microsoft QuickBASIC package includes BC, LINK, and LIB. The following
  17094.    list describes how these special tools are used when compiling and linking
  17095.    outside of the QuickBASIC environment:
  17096.  
  17097. ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
  17098.    Program            Function
  17099.    ──────────────────────────────────────────────────────────────────────────
  17100.    BC.EXE             When you choose the Make EXE File or Make Library
  17101.                       command from the Run menu, QuickBASIC invokes the BASIC
  17102.                       command-line compiler (BC) to produce intermediate
  17103.                       program files called object files. These object files
  17104.                       will be linked together to form your program or Quick
  17105.                       library. BC is also available any time you want to
  17106.                       compile programs outside of the QuickBASIC environment.
  17107.                       You may prefer to use BC if you want to compile
  17108.                       programs you have written with another text editor.
  17109.                       However, you only need to use BC from the command line
  17110.                       if your program is too large to compile in memory
  17111.                       within the QuickBASIC environment or if you want your
  17112.                       executable files to be compatible with the Microsoft
  17113.                       CodeView debugger.
  17114.  
  17115.    LINK.EXE           QuickBASIC uses the Microsoft Overlay Linker (LINK) to
  17116.                       link object files produced by BC with the appropriate
  17117.    Program            Function
  17118.    ──────────────────────────────────────────────────────────────────────────
  17119.                      link object files produced by BC with the appropriate
  17120.                       libraries to produce an executable file. You can use
  17121.                       LINK directly whenever you want to link object files or
  17122.                       make Quick libraries.
  17123.  
  17124.    LIB.EXE            The Microsoft Library Manager (LIB) creates stand-alone
  17125.                       libraries from the object files produced by BC.
  17126.                       QuickBASIC itself uses LIB to create such libraries and
  17127.                       then uses them when you choose the Make EXE File
  17128.                       command from the Run menu.
  17129.  
  17130.    ──────────────────────────────────────────────────────────────────────────
  17131.  
  17132.  
  17133.  
  17134.  G.2  The Compiling and Linking Process
  17135.  
  17136.    To create a stand-alone program from a BASIC source file when you are
  17137.    outside of the QuickBASIC environment, follow these steps:
  17138.  
  17139.    1. Compile each source file, creating an object file.
  17140.  
  17141.    2. Link the object files using LINK. LINK includes one or more stand-alone
  17142.       libraries and creates an executable file. LINK makes sure that all the
  17143.       procedure calls in the source files match up with the procedures in the
  17144.       libraries or with procedures in other object files before it creates an
  17145.       executable file.
  17146.  
  17147.    You can use either of the following methods of compiling and linking:
  17148.  
  17149.    ■ Compile and link in separate steps by using the BC and LINK commands.
  17150.  
  17151.    ■ Create a batch file containing all the compiling and linking commands.
  17152.      This method is most useful if you use the same options whenever you
  17153.      compile and link your programs.
  17154.  
  17155.    ──────────────────────────────────────────────────────────────────────────
  17156.    NOTE
  17157.      When QuickBASIC compiles and links your program from within the
  17158.      environment, the /E linker option is set automatically. However, when
  17159.      you use the LINK command outside the QuickBASIC environment, you must
  17160.      explicitly specify the /E option to minimize the size of the executable
  17161.      file and maximize program-loading speed.
  17162.    ──────────────────────────────────────────────────────────────────────────
  17163.  
  17164.    When compiling and linking from DOS, the paths you defined in the Options
  17165.    menu are not used. To search for include and library files the way you
  17166.    specified on the Options menu, you must set the DOS environment variables
  17167.    LIB and INCLUDE to point to the appropriate directories. Otherwise the
  17168.    compiler and/or linker might generate File not found errors.
  17169.  
  17170.    Sections G.3 and G.4 explain how to compile and link in separate steps.
  17171.  
  17172.  
  17173.  G.3  Compiling with the BC Command
  17174.  
  17175.    You can compile with the BC command in either of the following ways:
  17176.  
  17177.    ■ Type all information on a single command line, using the following
  17178.      syntax:
  17179.  
  17180.      BC sourcefile [[,[[objectfile]] [[,[[listingfile]]]]]]
  17181.      [[optionslist]][[;]]
  17182.  
  17183.    ■ Type
  17184.  
  17185.      BC
  17186.  
  17187.      and respond to the following prompts:
  17188.  
  17189.      Source Filename [.BAS]:
  17190.      Object Filename [basename.OBJ]:
  17191.      Source Listing: [NUL.LST]:
  17192.  
  17193.    Table G.1 shows the input you must give on the BC command line or in
  17194.    response to each prompt:
  17195.  
  17196.    Table G.1  Input to the BC Command
  17197.    Field              Prompt            Input
  17198.    ──────────────────────────────────────────────────────────────────────────
  17199.    sourcefile         "Source Filename" The name of your source file
  17200.  
  17201.    objectfile         "Object Filename" The name of the object file you are
  17202.                                         creating
  17203.  
  17204.    listingfile        "Source Listing"  The name of the file containing a
  17205.                                         source listing. The source-listing
  17206.                                         file contains the address of each
  17207.                                         line in your source file, the text of
  17208.                                         the source file, its size, and any
  17209.                                         error messages produced during
  17210.                                         compilation.
  17211.  
  17212.    optionslist        Gives options     Any of the compiler options described
  17213.                       after any         in Section G.3.2, "Using BC Command
  17214.                       response          Options"
  17215.    ──────────────────────────────────────────────────────────────────────────
  17216.  
  17217.  G.3.1  Specifying File Names
  17218.  
  17219.    The BC command makes certain assumptions about the files you specify,
  17220.    based on the path names and extensions you use for the files. The
  17221.    following sections describe these assumptions and other rules for
  17222.    specifying file names to the BC command.
  17223.  
  17224.    G.3.1.1  Uppercase and Lowercase Letters
  17225.  
  17226.    You can use any combination of uppercase and lowercase letters for file
  17227.    names; the compiler accepts uppercase and lowercase letters
  17228.    interchangeably.
  17229.  
  17230.    Example
  17231.  
  17232.    The BC command considers the following three file names to be equivalent:
  17233.  
  17234.    abcde.BAS
  17235.    ABCDE.BAS
  17236.    aBcDe.Bas
  17237.  
  17238.    G.3.1.2  File-Name Extensions
  17239.  
  17240.    A DOS file name has two parts: the "base name," which includes everything
  17241.    up to (but not including) the period (.), and the "extension," which
  17242.    includes the period and up to three characters following the period. In
  17243.    general, the extension identifies the type of file (for example, whether
  17244.    the file is a BASIC source file, an object file, an executable file, or a
  17245.    stand-alone library).
  17246.  
  17247.    BC and LINK use the file-name extensions described in the following list:
  17248.  
  17249.    Extension                File Description
  17250.    ──────────────────────────────────────────────────────────────────────────
  17251.    .BAS                     BASIC source file
  17252.  
  17253.    .OBJ                     Object file
  17254.  
  17255.    .LIB                     Stand-alone library file
  17256.  
  17257.    .LST                     Listing file produced by BC
  17258.  
  17259.    .MAP                     File of symbols from the linked program
  17260.  
  17261.    .EXE                     Executable file
  17262.  
  17263.    ──────────────────────────────────────────────────────────────────────────
  17264.  
  17265.    G.3.1.3  Path Names
  17266.  
  17267.    Any file name can include a full or partial path name. A full path name
  17268.    starts with the drive name; a partial path name has one or more directory
  17269.    names preceding the file name, but does not include a drive name.
  17270.  
  17271.    Giving a full path name allows you to specify files in different paths as
  17272.    input to the BC command and lets you create files on different drives or
  17273.    in different directories on the current drive.
  17274.  
  17275.    ──────────────────────────────────────────────────────────────────────────
  17276.    NOTE
  17277.      For files that you are creating with BC, you can give a path name ending
  17278.      in a backslash (\) to create the file in that path. When it creates the
  17279.      file, BC uses the default name for the file.
  17280.    ──────────────────────────────────────────────────────────────────────────
  17281.  
  17282.  G.3.2  Using BC Command Options
  17283.  
  17284.    Options to the BC command consist of either a forward-slash character (/)
  17285.    or a dash (-) followed by one or more letters. (The forward slash and the
  17286.    dash can be used interchangeably. In this manual, forward slashes are used
  17287.    for options.)
  17288.  
  17289.    The BC command-line options are explained in the following list:
  17290.  
  17291. ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
  17292.    Option             Description
  17293.    ──────────────────────────────────────────────────────────────────────────
  17294.    /A                 Creates a listing of the disassembled object code for
  17295.                       each source line and shows the assembly-language code
  17296.                       generated by the compiler.
  17297.  
  17298.    /AH                Allows dynamic arrays of records, fixed-length strings,
  17299.                       and numeric data to occupy all of available memory. If
  17300.                       this option is not specified, the maximum size is 64K
  17301.                       per array. Note that this option has no effect on the
  17302.                       way data items are passed to procedures.
  17303.  
  17304.    /C:buffersize      Sets the size of the buffer receiving remote data for
  17305.                       each communications port when using an asynchronous
  17306.    Option             Description
  17307.    ──────────────────────────────────────────────────────────────────────────
  17308.                      each communications port when using an asynchronous
  17309.                       communications adapter. (The transmission buffer is
  17310.                       allocated 128 bytes for each communications port and
  17311.                       cannot be changed on the BC command line.) This option
  17312.                       has no effect if the asynchronous communications card
  17313.                       is not present. The default buffer size is 512 bytes
  17314.                       total for both ports; the maximum size is 32,767 bytes.
  17315.  
  17316.    /D                 Generates debugging code for run-time error checking
  17317.                       and enables CTRL+BREAK. This option is the same as the
  17318.                       Produce Debug Code option from the Run menu's Make EXE
  17319.                       File command within the QuickBASIC environment.
  17320.  
  17321.    /E                 Indicates presence of ON ERROR with RESUME linenumber
  17322.                       statements. (See also the discussion of the /X option
  17323.                       in this list.)
  17324.  
  17325.    /MBF               The intrinsic functions MKS$, MKD$, CVS, and CVD are
  17326.                       converted to MKSMBF$, MKDMBF$, CVSMBF, and CVDMBF,
  17327.    Option             Description
  17328.    ──────────────────────────────────────────────────────────────────────────
  17329.                      converted to MKSMBF$, MKDMBF$, CVSMBF, and CVDMBF,
  17330.                       respectively. This allows your QuickBASIC program to
  17331.                       read and write floating-point values stored in
  17332.                       Microsoft Binary format.
  17333.  
  17334.    /O                 Substitutes the BCOM45.LIB run-time library for
  17335.                       BRUN45.LIB. See Chapter 16, "The Run Menu," in Learning
  17336.                       to Use Microsoft QuickBASIC for more information about
  17337.                       using these libraries.
  17338.  
  17339.    /R                 Stores arrays in row-major order. BASIC normally stores
  17340.                       arrays in column-major order. This option is useful if
  17341.                       you are using other-language routines that store arrays
  17342.                       in row order.
  17343.  
  17344.    /S                 Writes quoted strings to the object file instead of the
  17345.                       symbol table. Use this option when an Out of memory
  17346.                       error message occurs in a program that has many string
  17347.                       constants.
  17348.    Option             Description
  17349.    ──────────────────────────────────────────────────────────────────────────
  17350.                      constants.
  17351.  
  17352.    /V                 Enables event trapping for communications (COM),
  17353.                       lightpen (PEN), joystick (STRIG), timer (TIMER), music
  17354.                       buffer (PLAY) and function keys (KEY). Use this option
  17355.                       to check between statements for an occurrence of an
  17356.                       event.
  17357.  
  17358.    /W                 Enables event trapping for the same statements as /V,
  17359.                       but checks at each line number or label for occurrence
  17360.                       of an event.
  17361.  
  17362.    /X                 Indicates presence of ON ERROR with RESUME, RESUME
  17363.                       NEXT, or RESUME 0.
  17364.  
  17365.    /ZD                Produces an object file containing line-number records
  17366.                       corresponding to the line numbers of the source file.
  17367.                       This option is useful when you want to perform
  17368.                       source-level debugging using the Microsoft Symbolic
  17369.    Option             Description
  17370.    ──────────────────────────────────────────────────────────────────────────
  17371.                      source-level debugging using the Microsoft Symbolic
  17372.                       Debug Utility (SYMDEB), available with the Microsoft
  17373.                       Macro Assembler, Version 4.0.
  17374.  
  17375.    /ZI                Produces an object file of debugging information used
  17376.                       by the Microsoft CodeView debugger, available with
  17377.                       Microsoft C, Version 5.0 and later and Microsoft Macro
  17378.                       Assembler, Version 5.0 and later.
  17379.    ──────────────────────────────────────────────────────────────────────────
  17380.  
  17381.  
  17382.  G.4  Linking
  17383.  
  17384.    After compiling your program, you must link the object file with the
  17385.    appropriate libraries to create an executable program. You can use the
  17386.    LINK command in any of the following ways:
  17387.  
  17388.    ■ Give the input on a command line of the following form:
  17389.  
  17390.      LINK objfile [[,[[exefile]][[,[[mapfile]][[,[[lib]]]]]]
  17391.      [[linkopts]][[;]]]]
  17392.  
  17393.      The command line cannot be longer than 128 characters.
  17394.  
  17395.    ■ Type
  17396.  
  17397.      LINK
  17398.  
  17399.      and respond to the following prompts:
  17400.  
  17401.      Object Modules [.OBJ]:
  17402.      Run File [basename.EXE]:
  17403.      List File [NUL.MAP]:
  17404.      Libraries [.LIB]:
  17405.  
  17406.      To give more files for any prompt, type a plus sign (+) at the end of
  17407.      the line. The prompt reappears on the next line, and you can continue
  17408.      typing input for the prompt.
  17409.  
  17410.    ■ Set up a "response file" (a file containing responses to the LINK
  17411.      command prompts), and then type a LINK command of the following form:
  17412.  
  17413.      LINK @filename
  17414.  
  17415.      Here, filename is the name of the response file. You can append linker
  17416.      options to any response or give options on one or more separate lines.
  17417.      The responses must be in the same order as the LINK command prompts
  17418.      discussed above. You can also enter the name of a response file after
  17419.      any linker prompt, or at any position in the LINK command line.
  17420.  
  17421.    Table G.2 shows the input you must give on the LINK command line, or in
  17422.    response to each prompt.
  17423.  
  17424.    Table G.2  Input to the LINK Command
  17425. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  17426.    Field                    Prompt
  17427.                             Input
  17428.    ──────────────────────────────────────────────────────────────────────────
  17429.    objfile                  "Object Modules"
  17430.                             One or more object files that you are linking.
  17431.                             The object files should be separated by either
  17432.    Field                    Prompt
  17433.                             Input
  17434.    ──────────────────────────────────────────────────────────────────────────
  17435.                            The object files should be separated by either
  17436.                             plus signs or spaces.
  17437.  
  17438.    exefile                  "Run File"
  17439.                             Name of the executable file you are creating, if
  17440.                             you want to give it a name or extension other
  17441.                             than the default. You should always use the .EXE
  17442.                             extension, since DOS expects executable files to
  17443.                             have this extension.
  17444.  
  17445.    mapfile                  "List File"
  17446.                             Name of the file containing a symbol map listing,
  17447.                             if you are creating one. You can also specify
  17448.                             one of the following DOS device names to direct
  17449.                             the map file to that device: AUX for an auxiliary
  17450.                             device, CON for the console (terminal), PRN for a
  17451.                             printer device, or NUL for no device (so that no
  17452.                             map file is created). See Section G.4.6.11 for a
  17453.    Field                    Prompt
  17454.                             Input
  17455.    ──────────────────────────────────────────────────────────────────────────
  17456.                            map file is created). See Section G.4.6.11 for a
  17457.                             sample map file and information about its
  17458.                             contents.
  17459.  
  17460.    lib                      "Libraries"
  17461.                             One or more stand-alone libraries (or directories
  17462.                             to be searched for stand-alone libraries)
  17463.                             separated by plus signs or spaces. The
  17464.                             "Libraries" prompt allows you to specify up to 16
  17465.                             libraries; any additional libraries are ignored.
  17466.                             See Section G.4.3 for rules for specifying
  17467.                             library names to the linker.
  17468.  
  17469.    linkopts                 Gives options after any response
  17470.                             Any of the LINK options described in Sections
  17471.                             G.4.6.2-G.4.6.15. You can specify LINK options
  17472.                             anywhere on the command line.
  17473.  
  17474.    Field                    Prompt
  17475.                             Input
  17476.    ──────────────────────────────────────────────────────────────────────────
  17477. 
  17478.    ──────────────────────────────────────────────────────────────────────────
  17479.  
  17480.  
  17481.    If you are using a response file, each response must follow the rules
  17482.    outlined in Table G.2.
  17483.  
  17484.  G.4.1  Defaults for LINK
  17485.  
  17486.    You can choose defaults for any of the information that LINK needs in any
  17487.    of the following ways:
  17488.  
  17489.    ■ To choose the default for any command-line entry, omit the file name or
  17490.      names before the entry and type only the required comma. The only
  17491.      exception to this is the default for the mapfile entry: if you use a
  17492.      comma as a placeholder for this entry, LINK creates a map file.
  17493.  
  17494.    ■ To choose the default for any prompt, press ENTER.
  17495.  
  17496.    ■ To choose the defaults for all remaining command-line entries or
  17497.      prompts, type a semicolon after any entry or prompt. The only required
  17498.      input is one or more object-file names.
  17499.  
  17500.    The following list shows the defaults that LINK uses for executable files,
  17501.    map files, and libraries:
  17502.  
  17503. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  17504.    File Type                Default
  17505.    ──────────────────────────────────────────────────────────────────────────
  17506.    Executable               Base name of the first object file given, plus
  17507.                             the .EXE extension. To rename the executable
  17508.                             file, you are required to specify only the new
  17509.                             base name; if you give a file name with no
  17510.                             extension, LINK automatically appends the .EXE
  17511.                             extension.
  17512.  
  17513.    Map                      The special file name NUL.MAP, which tells LINK
  17514.                             not to create a map file. To create a map file,
  17515.                             you are required to specify only the base name;
  17516.    File Type                Default
  17517.    ──────────────────────────────────────────────────────────────────────────
  17518.                            you are required to specify only the base name;
  17519.                             if you give a file name with no extension, LINK
  17520.                             automatically appends the .MAP extension.
  17521.  
  17522.    Libraries                Libraries named in the given object files. If you
  17523.                             choose the Stand-Alone EXE File option,
  17524.                             BCOM45.LIB is the default library; otherwise, the
  17525.                             default is BRUN45.LIB. If you specify a library
  17526.                             other than a default library, you must give only
  17527.                             the base name; if you give a library name with no
  17528.                             extension, LINK automatically appends the .LIB
  17529.                             extension. See Section G.4.3 for information
  17530.                             about specifying libraries other than the default
  17531.                             libraries.
  17532.    ──────────────────────────────────────────────────────────────────────────
  17533.  
  17534.  
  17535.    ──────────────────────────────────────────────────────────────────────────
  17536.    NOTE
  17537.      When linking a stand-alone executable file, if your program does not use
  17538.      the COM statement, your program will be about 4K smaller if you link
  17539.      with NOCOM.OBJ, a file supplied with QuickBASIC.
  17540.    ──────────────────────────────────────────────────────────────────────────
  17541.  
  17542.    Examples
  17543.  
  17544.    The following example shows a response file. It tells LINK to link
  17545.    together the four object modules FRAME, TEXT, TABLE, and LINEOUT. The
  17546.    executable file FRAME.EXE and the map file named FRAMESYM.MAP are
  17547.    produced. The /PAUSE option causes LINK to pause before producing the
  17548.    executable file to permit disk swapping, if necessary. The /MAP option
  17549.    tells LINK to include public symbols and addresses in the map file. LINK
  17550.    also links any needed routines from the library file GRAF.LIB. See
  17551.    Sections G.4.6.2 and G.4.6.11 for more information on /PAUSE and /MAP
  17552.    options.
  17553.  
  17554.    FRAME TEXT TABLE LINEOUT
  17555.    /PAUSE /MAP
  17556.    FRAMESYM
  17557.    GRAF.LIB
  17558.  
  17559.    In the following example, LINK loads and links the object files FRAME.OBJ,
  17560.    TEXT.OBJ, TABLE.OBJ, and LINEOUT.OBJ, searching for unresolved references
  17561.    in the library file COBLIB.LIB. By default, the executable file is named
  17562.    FRAME.EXE. A map file called FRAMESYM.MAP is also produced.
  17563.  
  17564.    LINK FRAME+TEXT+TABLE+LINEOUT, ,FRAMESYM, COBLIB.LIB
  17565.  
  17566.    The example that follows illustrates how to continue any prompt by typing
  17567.    a plus sign (+) at the end of your response. The example links all of the
  17568.    given object files, then creates an executable file. Since a semicolon is
  17569.    typed as a response to the "Run File" prompt, the executable file is given
  17570.    the default name, which is the base name of the first object file given
  17571.    (FRAME), plus the .EXE extension. The defaults are also used for the
  17572.    remaining prompts. As a result, no map file is created, and the default
  17573.    libraries named in the object files are used for linking.
  17574.  
  17575.    LINK
  17576.  
  17577.    Object Modules [.OBJ]: FRAME TEXT TABLE LINEOUT+
  17578.    Object Modules [.OBJ]: BASELINE REVERSE COLNUM+
  17579.    Object Modules [.OBJ]: ROWNUM
  17580.    Run File [FRAME.EXE]: ;
  17581.  
  17582.  G.4.2  Specifying Files to LINK
  17583.  
  17584.    The rules for specifying file names to the linker are the same as for
  17585.    specifying file names to the BC command: uppercase and lowercase letters
  17586.    can be used interchangeably, and file names can include path names to tell
  17587.    LINK to look for files or create files in the given path. See Section
  17588.    G.3.1 for more information.
  17589.  
  17590.  G.4.3  Specifying Libraries to LINK
  17591.  
  17592.    Ordinarily, you do not need to give LINK a stand-alone-library name. When
  17593.    the BC command creates object files, it places in each object file the
  17594.    name of the correct stand-alone library for that object file. When the
  17595.    object file is passed to the linker, LINK looks for a library with the
  17596.    same name as the name in the object file and links the object file with
  17597.    that library automatically.
  17598.  
  17599.    To link object files with a stand-alone library other than the default,
  17600.    give the name of the nondefault library to LINK. You can give the library
  17601.    name in either of the following ways:
  17602.  
  17603.    ■ After the third comma on the LINK command line. Commas follow the list
  17604.      of object-file names, the executable-file name, and the listing-file
  17605.      name. The final name is the library name.
  17606.  
  17607.    ■ In response to the "Libraries" prompt of the LINK command.
  17608.  
  17609.    LINK searches libraries you specify to resolve external references before
  17610.    it searches default libraries.
  17611.  
  17612.    You might want to link with a stand-alone library other than the default
  17613.    to
  17614.  
  17615.    ■ Link with additional stand-alone libraries.
  17616.  
  17617.    ■ Link with libraries in different paths. If you specify a complete path
  17618.      name for the library, LINK only looks in that path for the library.
  17619.      Otherwise, it looks in the following three locations:
  17620.  
  17621.      1. The current working directory
  17622.  
  17623.      2. Any paths or drives you specify after the third comma on the LINK
  17624.         command line
  17625.  
  17626.      3. The locations given by the LIB environment variable
  17627.  
  17628.    ■ Ignore the library named in the object file. In this case, you must give
  17629.      the LINK option /NOD in addition to specifying the library you want to
  17630.      use for linking. See Section G.4.6.8 for more information about the
  17631.      /NOD option.
  17632.  
  17633.  G.4.4  Memory Requirements for LINK
  17634.  
  17635.    LINK uses available memory for the linking session. If the files to be
  17636.    linked create an output file that exceeds available memory, LINK creates a
  17637.    temporary disk file to serve as memory. This temporary file is handled in
  17638.    one of the following ways, depending on the DOS version:
  17639.  
  17640.    ■ LINK uses the directory specified by the TMP environment variable from
  17641.      DOS for the purpose of creating a temporary file. For example, if the
  17642.      TMP variable was set to C:\TEMPDIR, then LINK would put the temporary
  17643.      file in C:\TEMPDIR.
  17644.  
  17645.      If there is no TMP environment variable, or if the directory specified
  17646.      by TMP does not exist, then LINK puts the temporary file in the current
  17647.      working directory.
  17648.  
  17649.    ■ If LINK is running on DOS Version 3.0 or later, it uses a DOS system
  17650.      call to create a temporary file with a unique name in the temporary-file
  17651.      directory.
  17652.  
  17653.    ■ If LINK is running on a version of DOS prior to 3.0, it creates a
  17654.      temporary file named VM.TMP.
  17655.  
  17656.    When the linker creates a temporary disk file, you see the message
  17657.  
  17658.    Temporary file tempfile has been created.
  17659.    Do not change diskette in drive, letter
  17660.  
  17661.    where tempfile is ".\" followed by either the file name VM.TMP or a name
  17662.    generated by DOS, and letter is the drive containing the temporary file.
  17663.  
  17664.    The message
  17665.  
  17666.    Do not change diskette in drive
  17667.  
  17668.    does not appear unless the drive named letter is a floppy-disk drive. If
  17669.    this message appears, do not remove the disk from the drive until the
  17670.    linking session ends. If you remove the disk, linker operations will be
  17671.    unpredictable, and you may see the following message:
  17672.  
  17673.    unexpected end-of-file on scratch file
  17674.  
  17675.    If you see this message, rerun the linking session.
  17676.  
  17677.    The temporary file that LINK creates is a working file only. LINK deletes
  17678.    it at the end of the session.
  17679.  
  17680.    ──────────────────────────────────────────────────────────────────────────
  17681.    NOTE
  17682.      Do not give any of your own files the name VM.TMP. LINK displays an
  17683.      error message if it finds an existing file with this name.
  17684.    ──────────────────────────────────────────────────────────────────────────
  17685.  
  17686.  G.4.5  Linking with Mixed-Language Programs
  17687.  
  17688.    You can link mixed-language programs with LINK. However, problems can
  17689.    result from linking .OBJ files from within the other language. Different
  17690.    assumptions by different linkers can corrupt QuickBASIC files.
  17691.  
  17692.    The following sections discuss linking with modules written in Pascal,
  17693.    FORTRAN, and assembly language.
  17694.  
  17695.    G.4.5.1  Pascal and FORTRAN Modules in QuickBASIC Programs
  17696.  
  17697.    Modules compiled with Microsoft Pascal or FORTRAN can be linked with BASIC
  17698.    programs, as described in the Microsoft Mixed-Language Programming Guide.
  17699.    They can also be incorporated in Quick libraries. However, QuickBASIC
  17700.    programs containing code compiled with Microsoft Pascal must allocate at
  17701.    least 2K near-heap space for Pascal. The following example does this by
  17702.    using the DIM statement to allocate a static array of 2K or greater in a
  17703.    named common block called NMALLOC:
  17704.  
  17705.    DIM name%(2048) : COMMON SHARED /NMALLOC/ name%()
  17706.  
  17707.    The Pascal run-time module assumes it always has at least 2K of near-heap
  17708.    space available. If the Pascal code cannot allocate the required space,
  17709.    QuickBASIC may crash. This applies to Pascal code in Quick libraries and
  17710.    to Pascal code linked into executable files. The situation is similar for
  17711.    FORTRAN I/O, which also requires near buffer space, and which can be
  17712.    provided by using an NMALLOC common block.
  17713.  
  17714.    G.4.5.2  STATIC Array Allocation in Assembly-Language Routines
  17715.  
  17716.    Use the SEG or CALLS keywords or far pointers to pass static array data to
  17717.    assembly-language routines. You cannot assume data is in a particular
  17718.    segment. Alternatively, you can declare all arrays dynamic (still using
  17719.    far pointers) since BC and the QuickBASIC environment handle dynamic
  17720.    arrays identically.
  17721.  
  17722.    G.4.5.3  References to DGROUP in Extended Run-Time Modules
  17723.  
  17724.    For mixed-language programs that use the CHAIN command, you should make
  17725.    sure that any code built into an extended run-time module does not contain
  17726.    any references to DGROUP. (The CHAIN command causes DGROUP to move, but
  17727.    does not update references to DGROUP.) This rule applies only to
  17728.    mixed-language programs; because BASIC routines never refer to DGROUP, you
  17729.    can ignore this caution for programs written entirely in BASIC.
  17730.  
  17731.    To avoid this problem, you can use the value of SS, since BASIC always
  17732.    assumes that SS coincides with DGROUP.
  17733.  
  17734.  G.4.6  Using LINK Options
  17735.  
  17736.    LINK options begin with the linker's option character, which is the
  17737.    forward slash (/).
  17738.  
  17739.    Case is not significant in LINK options; for example, /NOI and /noi are
  17740.    equivalent.
  17741.  
  17742.    You can abbreviate LINK options to save space and effort. The minimum
  17743.    valid abbreviation for each option is indicated in the syntax of the
  17744.    option. For example, several options begin with the letters "NO";
  17745.    therefore, abbreviations for those options must be longer than "NO" to be
  17746.    unique. You cannot use "NO" as an abbreviation for the /NOIGNORECASE
  17747.    option, since LINK cannot tell which of the options beginning with "NO"
  17748.    you intend. The shortest valid abbreviation for this option is /NOI.
  17749.  
  17750.    Abbreviations must begin with the first letter of the option and must be
  17751.    continuous through the last letter typed. No gaps or transpositions are
  17752.    allowed.
  17753.  
  17754.    Some LINK options take numeric arguments. A numeric argument can be any of
  17755.    the following:
  17756.  
  17757.    ■ A decimal number from 0 to 65,535.
  17758.  
  17759.    ■ An octal number from 0 to 0177777. A number is interpreted as octal if
  17760.      it starts with a zero (0). For example, the number 10 is a decimal
  17761.      number, but the number 010 is an octal number, equivalent to 8 in
  17762.      decimal.
  17763.  
  17764.    ■ A hexadecimal number from 0 to 0xFFFF. A number is interpreted as
  17765.      hexadecimal if it starts with a zero followed by an x or an X. For
  17766.      example, 0x10 is a hexadecimal number, equivalent to 16 in decimal.
  17767.  
  17768.    LINK options affect all files in the linking process, regardless of where
  17769.    the options are specified.
  17770.  
  17771.    If you usually use the same set of LINK options, you can use the LINK
  17772.    environment variable in DOS to specify certain options each time you link.
  17773.    If you set this variable, LINK checks it for options and expects to find
  17774.    options listed exactly as you would type them on the command line. You
  17775.    cannot specify file-name arguments in the LINK environment variable.
  17776.  
  17777.    ──────────────────────────────────────────────────────────────────────────
  17778.    NOTE
  17779.      A command-line option overrides the effect of any environment-variable
  17780.      option with which it conflicts. For example, the command-line option
  17781.      /SE:256 cancels the effect of the environment-variable option /SE:512.
  17782.      To prevent an option in the environment variable from being used, you
  17783.      must reset the environment variable itself.
  17784.    ──────────────────────────────────────────────────────────────────────────
  17785.  
  17786.    Example
  17787.  
  17788.    In the following example, the file TEST.OBJ is linked with the options
  17789.    /SE:256 and /CO. After that, the file PROG.OBJ is linked with the option
  17790.    /NOD, as well as with the options /SE:256 and /CO.
  17791.  
  17792.    SET LINK=/SE:256 /CO
  17793.    LINK TEST;
  17794.    LINK /NOD PROG;
  17795.  
  17796.    G.4.6.1  Viewing the Options List (/HE)
  17797.  
  17798.    /HE[[LP]]
  17799.  
  17800.    The /HE option tells LINK to display a list of the available LINK options
  17801.    on the screen.
  17802.  
  17803.    G.4.6.2  Pausing during Linking (/PAU)
  17804.  
  17805.    /PAU[[SE]]
  17806.  
  17807.    The /PAU option tells LINK to pause in the link session and display a
  17808.    message before it writes the executable file to disk. This allows you to
  17809.    insert a new disk to hold the executable file.
  17810.  
  17811.    If you specify the /PAUSE option, LINK displays the following message
  17812.    before it creates the executable file:
  17813.  
  17814.    About to generate .EXE file
  17815.    Change diskette in drive letterand press <ENTER>
  17816.  
  17817.    The letter corresponds to the current drive. LINK resumes processing when
  17818.    you press the ENTER key.
  17819.  
  17820.    ──────────────────────────────────────────────────────────────────────────
  17821.    NOTE
  17822.      Do not remove the disk on which the list file is created or the disk
  17823.      used for the temporary file. If a temporary file is created on the disk
  17824.      you plan to swap, press CTRL+C to terminate the linking session.
  17825.      Rearrange your files so that the temporary file and the executable file
  17826.      can be written to the same disk. Then try linking again.
  17827.    ──────────────────────────────────────────────────────────────────────────
  17828.  
  17829.    G.4.6.3  Displaying Linker Process Information (/I)
  17830.  
  17831.    /I[[NFORMATION]]
  17832.  
  17833.    The /I option displays information about the linking process, including
  17834.    the phase of linking and the names of the object files being linked.
  17835.  
  17836.    This option helps you determine the locations of the object files being
  17837.    linked and the order in which they are linked.
  17838.  
  17839.    G.4.6.4  Preventing Linker Prompting (/B)
  17840.  
  17841.    /B[[ATCH]]
  17842.  
  17843.    The /B option tells LINK not to prompt you for a new path name whenever it
  17844.    cannot find a library or object file that it needs. When this option is
  17845.    used, the linker simply continues to execute without using the file in
  17846.    question.
  17847.  
  17848.    This option can cause unresolved external references. It is intended
  17849.    primarily to let you use batch or MAKE files to link many executable files
  17850.    with a single command if you do not want LINK to stop processing if it
  17851.    cannot find a required file. It is also useful when you are redirecting
  17852.    the LINK command line to create a file of linker output for future
  17853.    reference. However, this option does not prevent LINK from prompting for
  17854.    arguments missing from the LINK command line.
  17855.  
  17856.    G.4.6.5  Creating Quick Libraries (/Q)
  17857.  
  17858.    /Q[[UICKLIB]]
  17859.  
  17860.    The /Q option tells LINK to combine the object files you specify into a
  17861.    Quick library. When you start the QuickBASIC environment, you can give the
  17862.    /L option on the QB command line to load the Quick library. If you use the
  17863.    /Q option, be sure to specify BQLB45.LIB in the library list in order to
  17864.    include QuickBASIC Quick-library support routines.
  17865.  
  17866.    See Appendix H, "Creating and Using Quick Libraries," for more
  17867.    information about creating and loading Quick libraries.
  17868.  
  17869.    ──────────────────────────────────────────────────────────────────────────
  17870.    NOTE
  17871.      You cannot use the /EXEPACK option with the /Q option.
  17872.    ──────────────────────────────────────────────────────────────────────────
  17873.  
  17874.    G.4.6.6  Packing Executable Files (/E)
  17875.  
  17876.    /E[[XEPACK]]
  17877.  
  17878.    The /E option removes sequences of repeated bytes (typically null
  17879.    characters) and optimizes the "load-time relocation table" before creating
  17880.    the executable file. The load-time relocation table is a table of
  17881.    references relative to the start of the program. Each reference changes
  17882.    when the executable image is loaded into memory and an actual address for
  17883.    the entry point is assigned.
  17884.  
  17885.    ──────────────────────────────────────────────────────────────────────────
  17886.    NOTE
  17887.      Executable files linked with this option may be smaller and load faster
  17888.      than files linked without this option.
  17889.    ──────────────────────────────────────────────────────────────────────────
  17890.  
  17891.    G.4.6.7  Disabling Segment Packing (/NOP)
  17892.  
  17893.    /NOP[[ACKCODE]]
  17894.  
  17895.    The /NOP option is normally not necessary because code-segment packing is
  17896.    normally turned off. However, if a DOS environment variable such as LINK
  17897.    turns on code-segment packing automatically, you can use the /NOP option
  17898.    to turn segment packing back off again.
  17899.  
  17900.    G.4.6.8  Ignoring the Usual BASIC Libraries (/NOD)
  17901.  
  17902.    /NOD[[EFAULTLIBRARYSEARCH]]
  17903.  
  17904.    When it creates an object file, BC includes the names of the "standard"
  17905.    libraries──libraries that LINK searches to resolve external references.
  17906.    The /NOD option tells LINK not to search any library specified in an
  17907.    object file to resolve external references.
  17908.  
  17909.    In general, QuickBASIC programs do not work correctly without the standard
  17910.    QuickBASIC libraries (BRUN45.LIB and BCOM45.LIB). Thus, if you use the
  17911.    /NOD option, you should explicitly give the path name of the required
  17912.    standard library.
  17913.  
  17914.    G.4.6.9  Ignoring Dictionaries (/NOE)
  17915.  
  17916.    /NOE[[XTDICTIONARY]]
  17917.  
  17918.    If LINK suspects that a public symbol has been redefined, it prompts you
  17919.    to link again with the /NOE option. When you do so, it searches the
  17920.    individual object files, rather than "dictionaries" it has created, to
  17921.    resolve conflicts. For example, when linking a program with 87.LIB or
  17922.    NOCOM.OBJ, you must use the /NOE option.
  17923.  
  17924.    G.4.6.10  Setting Maximum Number of Segments (/SE)
  17925.  
  17926.    /SE[[GMENTS]]:number
  17927.  
  17928.    The /SE option controls the number of segments that LINK allows a program
  17929.    to have. The default is 128, but you can set number to any value
  17930.    (specified as decimal, octal, or hexadecimal) in the range 1-1024
  17931.    (decimal).
  17932.  
  17933.    For each segment, LINK must allocate space to keep track of segment
  17934.    information. When you set the segment limit higher than 128, LINK
  17935.    allocates more space for segment information. For programs with fewer than
  17936.    128 segments, you can minimize the amount of storage LINK needs by setting
  17937.    number to reflect the actual number of segments in the program. LINK
  17938.    displays an error message if this number is too high for the amount of
  17939.    memory it has available.
  17940.  
  17941.    G.4.6.11  Creating a Map File (/M)
  17942.  
  17943.    /M[[AP]]
  17944.  
  17945.    The /M option creates a map file. A map file lists the segments of a
  17946.    program and the program's public symbols. LINK always tries to allocate
  17947.    all of the available memory for sorting public symbols. If the number of
  17948.    symbols exceeds the memory limit, then LINK generates an unsorted list.
  17949.    The map file mapfile contains a list of symbols sorted by address;
  17950.    however, it does not contain a list sorted by name. A sample map file is
  17951.    shown below:
  17952.  
  17953.    Start  Stop   Length Name                   Class
  17954.     00000H 01E9FH 01EA0H _TEXT                  CODE
  17955.     01EA0H 01EA0H 00000H C_ETEXT                ENDCODE
  17956.    .
  17957.    .
  17958.    .
  17959.  
  17960.    The information in the columns Start and Stop shows the 20-bit address (in
  17961.    hexadecimal) of each segment, relative to the beginning of the load
  17962.    module. The load module begins at location zero. The column Length gives
  17963.    the length of the segment in bytes. The column Name gives the name of the
  17964.    segment; the column Class gives information about the segment type. See
  17965.    the Microsoft MS-DOS Programmer's Reference for information about groups,
  17966.    segments, and classes.
  17967.  
  17968.    The starting address and name of each group appear after the list of
  17969.    segments. A sample group listing is shown below:
  17970.  
  17971.    Origin   Group
  17972.    01EA:0   DGROUP
  17973.  
  17974.    In this example, DGROUP is the name of the data group.
  17975.  
  17976.    The map file shown below contains two lists of global symbols: the first
  17977.    list is sorted in ASCII-character order by symbol name; the second, by
  17978.    symbol address. The notation Abs appears next to the names of absolute
  17979.    symbols (symbols containing 16-bit constant values that are not associated
  17980.    with program addresses).
  17981.  
  17982.    Many of the global symbols that appear in the map file are symbols used
  17983.    internally by the compiler and linker. These symbols usually begin with
  17984.    the characters B$ or end with QQ.
  17985.  
  17986.    Address         Publics by Name
  17987.  
  17988.     01EA:0096       STKHQQ
  17989.     0000:1D86       B$Shell
  17990.     01EA:04B0       _edata
  17991.     01EA:0910       _end
  17992.    .
  17993.    .
  17994.    .
  17995.     01EA:00EC       __abrkp
  17996.     01EA:009C       __abrktb
  17997.     01EA:00EC       __abrktbe
  17998.     0000:9876  Abs  __acrtmsg
  17999.     0000:9876  Abs  __acrtused
  18000.    .
  18001.    .
  18002.    .
  18003.     01EA:0240       ___argc
  18004.     01EA:0242       ___argv
  18005.  
  18006.     Address         Publics by Value
  18007.  
  18008.     0000:0010       _main
  18009.     0000:0047       _htoi
  18010.    .
  18011.    .
  18012.    .
  18013.  
  18014.    The addresses of the external symbols are in the frame:offset format,
  18015.    showing the location of the symbol relative to zero (the beginning of the
  18016.    load module).
  18017.  
  18018.    Following the lists of symbols, the map file gives the program entry
  18019.    point, as shown in the following example:
  18020.  
  18021.    Program entry point at 0000:0129
  18022.  
  18023.    A map file can also be specified by giving a map-file name on the LINK
  18024.    command line or by giving a map-file name in response to the "List File"
  18025.    prompt.
  18026.  
  18027.    G.4.6.12  Including Line Numbers in a Map File (/LI)
  18028.  
  18029.    /LI[[NENUMBERS]]
  18030.  
  18031.    The /LI option creates a map file and includes the line numbers and
  18032.    associated addresses of the source program. If you are compiling and
  18033.    linking in separate steps, this option has an effect only if you are
  18034.    linking object files compiled with the /M option.
  18035.  
  18036.    G.4.6.13  Packing Contiguous Segments (/PAC)
  18037.  
  18038.    /[[NO]]PAC[[KCODE]][[:number]]
  18039.  
  18040.    The /PAC option tells LINK to group neighboring code segments. Code
  18041.    segments in the same group share the same segment address; all offset
  18042.    addresses are then adjusted upward as needed. As a result, many
  18043.    instructions that would otherwise have different segment addresses share
  18044.    the same segment address.
  18045.  
  18046.    If specified, number is the size limit of groups formed by /PAC. LINK
  18047.    stops adding segments to a particular group as soon as it cannot add a
  18048.    segment to the group without exceeding number. At that point, LINK starts
  18049.    forming a new group with the remaining code segments. If number is not
  18050.    given, the default is 65,530.
  18051.  
  18052.    Although LINK does not pack neighboring segments unless you explicitly ask
  18053.    for it, you can use the /NOPACKCODE option to turn off segment packing if,
  18054.    for example, you have given the /PAC option in the LINK environment
  18055.    variable in DOS.
  18056.  
  18057.    G.4.6.14  Using the CodeView Debugger (/CO)
  18058.  
  18059.    /CO[[DEVIEW]]
  18060.  
  18061.    The /CO option prepares an executable file for debugging using the
  18062.    CodeView debugger. If you are compiling and linking in separate steps,
  18063.    this option has an effect only if you are linking object files compiled
  18064.    with the /ZI option of the BC command. Similarly, it should not be used in
  18065.    conjunction with the LINK command's /Q option, because a Quick library
  18066.    cannot be debugged with the CodeView debugger.
  18067.  
  18068.    G.4.6.15  Distinguishing Case (/NOI)
  18069.  
  18070.    /NOI[[GNORECASE]]
  18071.  
  18072.    The /NOI option tells LINK to distinguish between uppercase and lowercase
  18073.    letters; for example, LINK would consider the names ABC, abc, and Abc to
  18074.    be three separate names. When you link, do not specify the /NOI option on
  18075.    the LINK command line.
  18076.  
  18077.  G.4.7  Other LINK Command-Line Options
  18078.  
  18079.    Not all options of the LINK command are suitable for use with QuickBASIC
  18080.    programs. The following LINK options can be used with Microsoft QuickBASIC
  18081.    programs; however, they are never required, since they request actions
  18082.    that the BC command or QuickBASIC performs automatically:
  18083.  
  18084. ╓┌─┌─────────────────────────────┌───────────────────────────────────────────╖
  18085.    Option                        Action
  18086.    ──────────────────────────────────────────────────────────────────────────
  18087.    /CP[[ARMAXALLOC]]:number      Sets the maximum number of 16-byte
  18088.                                  paragraphs needed by the program when it is
  18089.                                  loaded into memory to number, an integer
  18090.                                  between 1 and 65,535, inclusive. The
  18091.                                  operating system uses this value when
  18092.                                  allocating space for the program before
  18093.                                  loading it. Although you can use this option
  18094.                                  on the LINK command line, it has no effect
  18095.                                  because, while it is running, your BASIC
  18096.                                  program controls memory.
  18097.  
  18098.    /DO[[SSEG]]                   Forces segments to be ordered using the
  18099.                                  defaults for Microsoft high-level language
  18100.                                  products. QuickBASIC programs always use
  18101.                                  this segment order by default.
  18102.  
  18103.    /ST[[ACK]]:number             Specifies the size of the stack for your
  18104.    Option                        Action
  18105.    ──────────────────────────────────────────────────────────────────────────
  18106.   /ST[[ACK]]:number             Specifies the size of the stack for your
  18107.                                  program, where number is any positive value
  18108.                                  (decimal, octal, or hexadecimal) up to
  18109.                                  65,535 (decimal) representing the size, in
  18110.                                  bytes, of the stack. The standard BASIC
  18111.                                  library sets the default stack size to 2K.
  18112.  
  18113.    /DS[[ALLOCATE]]               Loads all data starting at the high end of
  18114.                                  the default data segment.
  18115.  
  18116.    /HI[[GH]]                     Places the executable file as high in memory
  18117.                                  as possible.
  18118.  
  18119.    /NOG[[ROUPASSOCIATION]]       Tells LINK to ignore group associations when
  18120.                                  assigning addresses to data and code items.
  18121.  
  18122.    /O[[VERLAYINTERRUPT]]:number  Specifies an interrupt number other than
  18123.                                  0x3F for passing control to overlays.
  18124.    ──────────────────────────────────────────────────────────────────────────
  18125.    Option                        Action
  18126.    ──────────────────────────────────────────────────────────────────────────
  18127.   ──────────────────────────────────────────────────────────────────────────
  18128.  
  18129.  
  18130.    ──────────────────────────────────────────────────────────────────────────
  18131.    NOTE
  18132.      Do not use the /DS, /HI, /NOG, or /O options when linking object files
  18133.      compiled with BC. They are suitable only for object files created by the
  18134.      Microsoft Macro Assembler (MASM).
  18135.    ──────────────────────────────────────────────────────────────────────────
  18136.  
  18137.  
  18138.  G.5  Managing Stand-Alone Libraries: LIB
  18139.  
  18140.    The Microsoft Library Manager (LIB) manages the contents of stand-alone
  18141.    libraries. A stand-alone library is made up of "object modules"──that is,
  18142.    object files combined to form a library. Unlike an object file, an object
  18143.    module does not exist independently of its library, and does not have a
  18144.    path name or extension associated with its file name. Using LIB, you can:
  18145.  
  18146.    ■ Combine object files to create a new library
  18147.  
  18148.    ■ Add object files to an existing library
  18149.  
  18150.    ■ Delete or replace the object modules of an existing library
  18151.  
  18152.    ■ Extract object modules from an existing library and place them in
  18153.      separate object files
  18154.  
  18155.    ■ Combine the contents of two existing libraries into a new library
  18156.  
  18157.    When updating an existing library, LIB performs all of its operations on a
  18158.    copy of the library. This mechanism ensures that you have a backup copy of
  18159.    any library you update in case of problems with the updated version of the
  18160.    library.
  18161.  
  18162.  G.5.1  Running LIB
  18163.  
  18164.    You can give the LIB command input in any of the following ways:
  18165.  
  18166.    ■ Specify the input on a command line of the following form:
  18167.  
  18168.      LIB oldlib [[/P[[AGESIZE]]:number]]
  18169.      [[commands]][[,[[listfile]][[,[[newlib]]]]]][[;]]
  18170.  
  18171.      The command line has a maximum length of 128 characters.
  18172.  
  18173.    ■ Type
  18174.  
  18175.      lib
  18176.  
  18177.      and respond to the following prompts:
  18178.  
  18179.      Library name:
  18180.      Operations:
  18181.      List file:
  18182.      Output library:
  18183.  
  18184.      To give more files for any prompt, type an ampersand (&) at the end of
  18185.      the line. The prompt reappears on the next line, and you can continue
  18186.      typing input for the prompt.
  18187.  
  18188.    ■ Set up a response file, a file with responses to LIB command prompts,
  18189.      then type a LIB command of the following form:
  18190.  
  18191.      LIB @filename
  18192.  
  18193.    Here, filename is the name of the response file. The responses must be in
  18194.    the same order as the LIB prompts discussed above. You can also enter the
  18195.    name of a response file after any LINK prompt, or at any position in the
  18196.    LIB command line.
  18197.  
  18198.    Table G.3 shows the input you must give on the LIB command line, or in
  18199.    response to each prompt. If you are using a response file, each response
  18200.    must follow the rules outlined in this table.
  18201.  
  18202.    Table G.3  Input to the LIB Command
  18203. ╓┌─┌───────────┌────────────────────────┌────────────────────────────────────╖
  18204.    Field       Prompt                   Input
  18205.    ──────────────────────────────────────────────────────────────────────────
  18206.    oldlib      "Library name"           Name of the library you are changing
  18207.                                         or creating. If this library does not
  18208.                                         exist, LIB asks if you want to create
  18209.    Field       Prompt                   Input
  18210.    ──────────────────────────────────────────────────────────────────────────
  18211.                                        exist, LIB asks if you want to create
  18212.                                         it. Type the letter y to create a new
  18213.                                         library or the letter n to terminate
  18214.                                         LIB. This message is suppressed if
  18215.                                         you type command characters, a comma,
  18216.                                         or a semicolon after the library
  18217.                                         name. A semicolon tells LIB to
  18218.                                         perform a consistency check on the
  18219.                                         library; in this case, it displays a
  18220.                                         message if it finds errors in any
  18221.                                         library module.
  18222.  
  18223.    /P:number   /P:number after "Library The library page size. This sets the
  18224.                name" prompt             page size for the library to number,
  18225.                                         where number is an integer power of 2
  18226.                                         between 16 and 32,768, inclusive. The
  18227.                                         default page size for a new library
  18228.                                         is 16 bytes. Modules in the library
  18229.                                         are always aligned to start at a
  18230.    Field       Prompt                   Input
  18231.    ──────────────────────────────────────────────────────────────────────────
  18232.                                        are always aligned to start at a
  18233.                                         position that is a multiple of the
  18234.                                         page size (in bytes) from the
  18235.                                         beginning of the file.
  18236.  
  18237.    /I          None                     Tells LIB to ignore case when
  18238.                                         comparing symbols (default). Use when
  18239.                                         combining with libraries that are
  18240.                                         case sensitive.
  18241.  
  18242.    /NOE        None                     Tells LIB not to generate an extended
  18243.                                         dictionary.
  18244.  
  18245.    /NOI        None                     Tells LIB to compare case when
  18246.                                         comparing symbols (LIB remains case
  18247.                                         sensitive).
  18248.  
  18249.    commands    "Operations"             Command symbols and object files that
  18250.                                         tell LIB what changes to make in the
  18251.    Field       Prompt                   Input
  18252.    ──────────────────────────────────────────────────────────────────────────
  18253.                                        tell LIB what changes to make in the
  18254.                                         library.
  18255.  
  18256.    listfile    "List file"              Name of a cross-reference-listing
  18257.                                         file. No listing file is created if
  18258.                                         you do not give a file name.
  18259.  
  18260.    newlib      "Output library"         Name of the changed library that LIB
  18261.                                         creates as output. If you do not give
  18262.                                         a new library name, the original,
  18263.                                         unchanged library is saved in a
  18264.                                         library file with the same name but
  18265.                                         with a .BAK extension replacing the
  18266.                                         .LIB extension.
  18267.    ──────────────────────────────────────────────────────────────────────────
  18268.  
  18269.  
  18270.  G.5.2  Usual Responses for LIB
  18271.  
  18272.    LIB has its own built-in (default) responses. You can choose these usual
  18273.    responses for any of the information that LIB needs, in any the following
  18274.    ways:
  18275.  
  18276.    ■ To choose the default for any command-line entry, omit the file name or
  18277.      names before the entry and type only the required comma. The only
  18278.      exception to this is the default for the listfile entry: if you omit
  18279.      this entry, LIB creates a cross-reference-listing file.
  18280.  
  18281.    ■ To choose the default for any prompt, press ENTER.
  18282.  
  18283.    ■ To choose the defaults for all command-line entries or prompts that
  18284.      follow an entry or prompt, type a semicolon (;) after that entry or
  18285.      prompt. The semicolon should be the last character on the command line.
  18286.  
  18287.    The following list shows the defaults that LIB uses for
  18288.    cross-reference-listing files and output libraries:
  18289.  
  18290.    File               Default
  18291.    ──────────────────────────────────────────────────────────────────────────
  18292.    Cross-reference    The special file name NUL, which tells the linker not
  18293.    listing            to create a cross-reference-listing file
  18294.  
  18295.    Output library     The oldlib entry or the response to the "Library name"
  18296.                       prompt
  18297.    ──────────────────────────────────────────────────────────────────────────
  18298.  
  18299.  G.5.3  Cross-Reference-Listing Files
  18300.  
  18301.    A cross-reference-listing file tracks which routines are contained in a
  18302.    stand-alone library and the original object files they came from. A
  18303.    cross-reference-listing file contains the following lists:
  18304.  
  18305.    ■ An alphabetical list of all public symbols in the library. Each symbol
  18306.      name is followed by the name of the module in which it is defined.
  18307.  
  18308.    ■ A list of the modules in the library. Under each module name is an
  18309.      alphabetical listing of the public symbols defined in that module.
  18310.  
  18311.  G.5.4  Command Symbols
  18312.  
  18313.    To tell LIB what changes you want to make to a library, type a command
  18314.    symbol such as +, -, -+, *, or -*, followed immediately by a module name,
  18315.    object-file name, or library name. You can specify more than one
  18316.    operation, in any order.
  18317.  
  18318.    The following list shows each LIB command symbol, the type of file name to
  18319.    specify with the symbol, and what the symbol does:
  18320.  
  18321. ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
  18322.    Command                  Meaning
  18323.    ──────────────────────────────────────────────────────────────────────────
  18324.    +{objfile | lib}         Adds the given object file to the input library
  18325.                             and makes that object file the last module in the
  18326.                             library, if given with an object-file name. You
  18327.                             can use a path name for the object file name.
  18328.                             Since LIB automatically supplies the .OBJ
  18329.                             extension, you can omit the extension from the
  18330.                             object-file name.
  18331.  
  18332.                             If given with a library name, the plus sign (+)
  18333.                             adds the contents of that library to the input
  18334.                             library. The library name must have the .LIB
  18335.    Command                  Meaning
  18336.    ──────────────────────────────────────────────────────────────────────────
  18337.                            library. The library name must have the .LIB
  18338.                             extension.
  18339.  
  18340.    -module                  Deletes the given module from the input library.
  18341.                             A module name does not have a path name or an
  18342.                             extension.
  18343.  
  18344.    -+module                 Replaces the given module in the input library.
  18345.                             Module names have no path names and no
  18346.                             extensions. LIB deletes the given module, then
  18347.                             appends the object file that has the same name as
  18348.                             the module. The object file is assumed to have an
  18349.                             .OBJ extension and to reside in the current
  18350.                             working directory.
  18351.  
  18352.    *module                  Copies the given module from the library to an
  18353.                             object file in the current working directory. The
  18354.                             module remains in the library file. When LIB
  18355.                             copies the module to an object file, it adds the
  18356.    Command                  Meaning
  18357.    ──────────────────────────────────────────────────────────────────────────
  18358.                            copies the module to an object file, it adds the
  18359.                             .OBJ extension. You cannot override the .OBJ
  18360.                             extension, drive designation, or path name given
  18361.                             to the object file. However, you can later rename
  18362.                             the file or copy it to whatever location you
  18363.                             like.
  18364.  
  18365.    -*module                 Moves the given object module from the library to
  18366.                             an object file. This operation is equivalent to
  18367.                             copying the module to an object file, as
  18368.                             described above, then deleting the module from
  18369.                             the library.
  18370.    ──────────────────────────────────────────────────────────────────────────
  18371.  
  18372.  
  18373.    Examples
  18374.  
  18375.    The example below uses the replace command symbol (-+) to instruct LIB to
  18376.    replace the HEAP module in the library LANG.LIB. LIB deletes HEAP from the
  18377.    library, then appends the object file HEAP.OBJ as a new module in the
  18378.    library. The semicolon at the end of the command line tells LIB to use the
  18379.    default responses for the remaining prompts. This means that no listing
  18380.    file is created and that the changes are written to the original library
  18381.    file instead of creating a new library file.
  18382.  
  18383.    LIB LANG-+HEAP;
  18384.  
  18385.    The examples below perform the same function as the first example in this
  18386.    section, but in two separate operations, using the add (+) and delete (-)
  18387.    command symbols. The effect is the same for these examples because delete
  18388.    operations are always carried out before add operations, regardless of the
  18389.    order of the operations in the command line. This order of execution
  18390.    prevents confusion when a new version of a module replaces an old version
  18391.    in the library file.
  18392.  
  18393.    LIB LANG-HEAP+HEAP;
  18394.  
  18395.    LIB LANG+HEAP-HEAP;
  18396.  
  18397.    The example below causes LIB to perform a consistency check of the library
  18398.    file FOR.LIB. No other action is performed. LIB displays any consistency
  18399.    errors it finds and returns to the operating-system level.
  18400.  
  18401.    LIB FOR;
  18402.  
  18403.    The following example tells LIB to perform a consistency check on the
  18404.    library file LANG.LIB and then create the cross-reference-listing file
  18405.    LCROSS.PUB.
  18406.  
  18407.    LIB LANG,LCROSS.PUB
  18408.  
  18409.    The next example instructs LIB to move the module STUFF from the library
  18410.    FIRST.LIB to an object file called STUFF.OBJ. The module STUFF is removed
  18411.    from the library in the process. The module MORE is copied from the
  18412.    library to an object file called MORE.OBJ; the module remains in the
  18413.    library. The revised library is called SECOND.LIB. It contains all the
  18414.    modules in the library FIRST.LIB except STUFF, which was removed by using
  18415.    the move command symbol (-*). The original library, FIRST.LIB, remains
  18416.    unchanged.
  18417.  
  18418.    LIB FIRST -*STUFF *MORE, ,SECOND
  18419.  
  18420.    The contents of the response file below cause LIB to delete the module
  18421.    HEAP from the LIBFOR.LIB library file, extract (without deleting) FOIBLES
  18422.    and place it in an object file named FOIBLES.OBJ, and append the object
  18423.    files CURSOR.OBJ and HEAP.OBJ as the last two modules in the library.
  18424.    Finally, LIB creates the cross-reference-listing file CROSSLST.
  18425.  
  18426.    LIBFOR
  18427.    +CURSOR+HEAP-HEAP*FOIBLES
  18428.    CROSSLST
  18429.  
  18430.  G.5.5  LIB Options
  18431.  
  18432.    LIB has four options. Specify options on the command line following the
  18433.    required library-file name and preceding any commands.
  18434.  
  18435.    G.5.5.1  Ignoring Case for Symbols
  18436.  
  18437.    /I[[GNORECASE]]
  18438.  
  18439.    The /I option tells LIB to ignore case when comparing symbols, as LIB does
  18440.    by default. Use this option when you are combining a library that is
  18441.    marked /NOI (described below) with others that are unmarked and you want
  18442.    the new library to be unmarked.
  18443.  
  18444.    G.5.5.2  Ignoring Extended Dictionaries
  18445.  
  18446.    /NOE[[XTDICTIONARY]]
  18447.  
  18448.    The /NOE option tells LIB not to generate an extended dictionary. The
  18449.    extended dictionary is an extra part of the library that helps the linker
  18450.    process libraries faster.
  18451.  
  18452.    Use the /NOE option if you get errors U1171 or U1172, or if the extended
  18453.    dictionary causes problems with LINK. See Section G.4.6.9 for more
  18454.    information on how LINK uses the extended dictionary.
  18455.  
  18456.    G.5.5.3  Distinguishing Case for Symbols
  18457.  
  18458.    /NOI[[GNORECASE]]
  18459.  
  18460.    The /NOI option tells LIB not to ignore case when comparing symbols; that
  18461.    is, /NOI makes LIB case sensitive. By default, LIB ignores case. Using
  18462.    this option allows symbols that are the same except for case, such as
  18463.    SPLINE and Spline, to be put in the same library.
  18464.  
  18465.    Note that when you create a library with the /NOI option, LIB marks the
  18466.    library internally to indicate that /NOI is in effect. Earlier version of
  18467.    LIB did not mark libraries in this way. If you combine multiple libraries,
  18468.    and any one of them is marked /NOI, then /NOI is assumed to be in effect
  18469.    for the output library.
  18470.  
  18471.    G.5.5.4  Setting Page Size
  18472.  
  18473.    /P[[AGESIZE]]:number
  18474.  
  18475.    The page size of a library affects the alignment of modules stored in the
  18476.    library. Modules in the library are always aligned to start at a position
  18477.    that is a multiple of the page size (in bytes) from the beginning of the
  18478.    file. The default page size for a newly created library is 16 bytes.
  18479.  
  18480.    You can set a different library page size while you are creating a library
  18481.    or change the page size of an existing library by adding the following
  18482.    option after the oldlib entry on the LIB command line or after the name
  18483.    you type in response to the "Library name" prompt:
  18484.  
  18485.    The number specifies the new library page size. It must be an integer
  18486.    value representing a power of 2 between the values 16 and 32,768.
  18487.  
  18488.    The library page size determines the number of modules the library can
  18489.    hold. Thus, increasing the page size allows you to include more modules in
  18490.    the library. However, the larger the page size, the larger the amount of
  18491.    wasted storage space in the library (on the average, pagesize/2 bytes). In
  18492.    most cases you should use a small page size unless you need to put a very
  18493.    large number of modules in a library.
  18494.  
  18495.    The page size also determines the maximum possible size of the library.
  18496.    This limit is number * 65,536. For example, if you invoke LIB with the
  18497.    option /P:16, the library must be smaller than one megabyte (16 * 65,536
  18498.    bytes).
  18499.  
  18500.  
  18501.  
  18502.  ────────────────────────────────────────────────────────────────────────────
  18503.  Appendix H  Creating and Using Quick Libraries
  18504.  
  18505.    This appendix describes how to create and maintain libraries from within
  18506.    the QuickBASIC programming environment. A library is a file containing the
  18507.    contents of several modules under a single file name. When you finish this
  18508.    appendix you will know how to:
  18509.  
  18510.    ■ Make libraries from within the QuickBASIC environment
  18511.  
  18512.    ■ Load a Quick library when running a QuickBASIC program
  18513.  
  18514.    ■ View the contents of a Quick library
  18515.  
  18516.    ■ Add routines written in other languages to a Quick library
  18517.  
  18518.  
  18519.  H.1  Types of Libraries
  18520.  
  18521.    QuickBASIC provides tools for creating two different types of libraries,
  18522.    which are identified by different file-name extensions:
  18523.  
  18524.    Extension                Function
  18525.    ──────────────────────────────────────────────────────────────────────────
  18526.    .QLB                     The .QLB extension characterizes a Quick library,
  18527.                             a special kind of library that permits easy
  18528.                             addition of frequently used procedures to your
  18529.                             programs. A Quick library can contain procedures
  18530.                             written in QuickBASIC or other Microsoft
  18531.                             languages such as Microsoft C.
  18532.  
  18533.    .LIB                     The .LIB extension characterizes a stand-alone
  18534.                             (.LIB) library, one that is created with the
  18535.                             Microsoft Library Manager, LIB. When QuickBASIC
  18536.                             makes a Quick library, it simultaneously creates
  18537.                             a .LIB library containing the same procedures in
  18538.                             a somewhat different form.
  18539.    ──────────────────────────────────────────────────────────────────────────
  18540.  
  18541.    You can generate both types of libraries from within the programming
  18542.    environment or from the command line. You can think of a Quick library as
  18543.    a group of procedures appended to QuickBASIC when the library is loaded
  18544.    with QuickBASIC. Libraries with the .LIB extension are essentially
  18545.    independent, compiled procedures. They can either be added to a Quick
  18546.    library or linked with a main module to create a file that is executable
  18547.    from the DOS command line.
  18548.  
  18549.    This appendix discusses the use of command-line utilities for some common
  18550.    cases, but you should refer to Appendix G, "Compiling and Linking from
  18551.    DOS," for a full explanation of using those utilities.
  18552.  
  18553.  
  18554.  H.2  Advantages of Quick Libraries
  18555.  
  18556.    Quick libraries facilitate program development and maintenance. As
  18557.    development progresses on a project and modules become stable components
  18558.    of your program, you can add them to a Quick library, then set aside the
  18559.    source files for the original modules until you want to improve or
  18560.    maintain those source files. Thereafter you can load the library along
  18561.    with QuickBASIC, and your program has instant access to all procedures in
  18562.    the library.
  18563.  
  18564.    Procedures in a Quick library behave like QuickBASIC's own statements. If
  18565.    properly declared, a SUB procedure in a Quick library can even be invoked
  18566.    without a CALL statement. See Chapter 2, "SUB and FUNCTION Procedures,"
  18567.    for more information on calling a SUB procedure with or without the CALL
  18568.    keyword.
  18569.  
  18570.    Procedures in a Quick library can be executed directly from the Immediate
  18571.    window, just like BASIC statements. This means that you can test their
  18572.    effects before using them in other programs.
  18573.  
  18574.    If you codevelop programs with others, Quick libraries make it easy to
  18575.    update a pool of common procedures. If you wish to offer a library of
  18576.    original procedures for commercial distribution, all QuickBASIC
  18577.    programmers will be able to use them immediately to enhance their own
  18578.    work. You could leave your custom Quick library on a bulletin board for
  18579.    others to try before purchasing. Because Quick libraries contain no source
  18580.    code and can only be used within the QuickBASIC programming environment,
  18581.    your proprietary interests are protected while your marketing goals are
  18582.    advanced.
  18583.  
  18584.    ──────────────────────────────────────────────────────────────────────────
  18585.    NOTE
  18586.      Quick libraries have the same function as user libraries in QuickBASIC
  18587.      Versions 2.0 and 3.0. However, you cannot load a user library as a Quick
  18588.      library. You must recreate the library from the original source code, as
  18589.      described below.
  18590.    ──────────────────────────────────────────────────────────────────────────
  18591.  
  18592.  
  18593.  H.3  Creating a Quick Library
  18594.  
  18595.    A Quick library automatically contains all modules, both main and nonmain,
  18596.    present in the QuickBASIC environment when you create the new library. It
  18597.    also contains the contents of any other Quick library that you loaded when
  18598.    starting QuickBASIC. If you load a whole program but only want certain
  18599.    modules to be put in the library, you must explicitly unload those you
  18600.    don't want. You can unload modules with the File menu's Unload File
  18601.    command.
  18602.  
  18603.    You can quickly determine which modules are loaded by checking the list
  18604.    box of the SUBs command on the View menu. However, this method does not
  18605.    show which procedures a loaded library contains. The QLBDUMP.BAS utility
  18606.    program, described in Section H.4.3, "Viewing the Contents of a Quick
  18607.    Library," allows you to list all the procedures in a library.
  18608.  
  18609.    Only whole modules can be put into a library. That is, you cannot select
  18610.    one procedure from among many in a module. If you want to enter only
  18611.    certain procedures from a module, put the procedures you want in a
  18612.    separate module, then put that module into a library.
  18613.  
  18614.    A Quick library must be self-contained. A procedure in a Quick library can
  18615.    only call other procedures within the same Quick library. Procedure names
  18616.    must be unique within the library.
  18617.  
  18618.    With large programs, you can reduce loading time by putting as many
  18619.    routines as possible in Quick libraries. Putting many routines in Quick
  18620.    libraries is also an advantage if you plan to make the program into a
  18621.    stand-alone executable file later, since the contents of libraries are
  18622.    simply linked without recompiling.
  18623.  
  18624.    ──────────────────────────────────────────────────────────────────────────
  18625.    NOTE
  18626.      Your main module may or may not contain procedures. If it does and you
  18627.      incorporate those procedures in the library, the entire main module goes
  18628.      in the library, too. This does not cause an error message, but the
  18629.      module-level code in the library can never be executed unless one of its
  18630.      procedures contains a routine (such as ON ERROR) that explicitly passes
  18631.      control to the module level. Even if that is the case, much of the
  18632.      module-level code may be extraneous. If you organize your procedures in
  18633.      modules that are frequently used together, your Quick libraries are
  18634.      likely to be less cluttered with useless code.
  18635.    ──────────────────────────────────────────────────────────────────────────
  18636.  
  18637.  H.3.1  Files Needed to Create a Quick Library
  18638.  
  18639.    To create a Quick library, make sure that the proper files are available
  18640.    before you begin. If you don't have a hard disk, you should keep your
  18641.    files and the other programs on several floppy disks. QuickBASIC prompts
  18642.    you for a path name when it cannot find a file; when this happens, insert
  18643.    the correct disk and respond to the prompt.
  18644.  
  18645.    Make sure that the following files are in the current working directory or
  18646.    accessible to QuickBASIC through the appropriate DOS environment
  18647.    variables:
  18648.  
  18649.    File                     Purpose
  18650.    ──────────────────────────────────────────────────────────────────────────
  18651.    QB.EXE                   Directs the process of creating a Quick library.
  18652.                             If you are working only with QuickBASIC modules,
  18653.                             you can do everything in one step from within the
  18654.                             QuickBASIC environment.
  18655.  
  18656.    BC.EXE                   Creates object files from source code.
  18657.  
  18658.    LINK.EXE                 Links object files.
  18659.  
  18660.    LIB.EXE                  Manages stand-alone libraries of object modules.
  18661.  
  18662.    BQLB45.LIB               Supplies routines needed by your Quick library.
  18663.                             This library is a stand-alone library that is
  18664.                             linked with objects in your library to form a
  18665.                             Quick library.
  18666.    ──────────────────────────────────────────────────────────────────────────
  18667.  
  18668.  H.3.2  Making a Quick Library
  18669.  
  18670.    Most of the time you create Quick libraries from within the QuickBASIC
  18671.    environment. Occasionally, you may want to update a library or include
  18672.    routines from other Microsoft languages in your Quick library. In these
  18673.    cases, begin by constructing a base library of the non-BASIC routines from
  18674.    outside the environment by invoking LINK and LIB directly. Then you can
  18675.    add the most current QuickBASIC modules from within QuickBASIC.
  18676.  
  18677.  H.3.3  Making a Quick Library from within the Environment
  18678.  
  18679.    When making a library from within the QuickBASIC environment, the first
  18680.    consideration is whether the library to be made is totally new or an
  18681.    update of an existing library. If it is to be an update, you should start
  18682.    QuickBASIC with the /L command-line option, supplying the name of the
  18683.    library to be updated as a command-line argument. At the same time, you
  18684.    can also include the name of a program whose modules you want to put in
  18685.    the library. In this case QuickBASIC loads all the modules specified in
  18686.    that program's .MAK file.
  18687.  
  18688.    H.3.3.1  Unloading Unwanted Files
  18689.  
  18690.    If you load your program when starting QuickBASIC, be sure to unload any
  18691.    modules you don't want in the Quick library, including the main module
  18692.    (unless it contains procedures you want in the library).
  18693.  
  18694.    Follow these steps to unload modules:
  18695.  
  18696.    1. Choose the Unload File command from the File menu.
  18697.  
  18698.    2. Select the module you want to unload from the list box, then press
  18699.       ENTER.
  18700.  
  18701.    3. Repeat steps 1 and 2 until you have unloaded all unwanted modules.
  18702.  
  18703.    H.3.3.2  Loading Desired Files
  18704.  
  18705.    Alternatively, you can simply start QuickBASIC, with or without a library
  18706.    specification, and load the modules you want one at a time from within the
  18707.    environment. In this case, you load each module using the Load File
  18708.    command from the File menu.
  18709.  
  18710.    To load one module at a time with QuickBASIC:
  18711.  
  18712.    1. Choose the File menu's Load File command.
  18713.  
  18714.    2. Select the name of a module you want to load from the list box.
  18715.  
  18716.    3. Repeat steps 1 and 2 until all you have loaded all the modules you
  18717.       want.
  18718.  
  18719.    H.3.3.3  Creating a Quick Library
  18720.  
  18721.    Once you have loaded the previous library (if any) and all the new modules
  18722.    you want to include in the Quick library, choose the Make Library command
  18723.    from the Run menu. The dialog box shown in Figure H.1 appears.
  18724.  
  18725.  
  18726.                               Type Quick-library file name here.
  18727.                                 │
  18728.    ┌────────────────────────────┼─Make Library───────────────────────────┐
  18729.    │                          ┌─┼─────────────────────────────────────┐  │
  18730.    │ Quick-Library File Name: │                                       │  │
  18731.    │                          └───────────────────────────────────────┘  │
  18732.    │ [X] Produce Debug Code                                              │
  18733.    ├─────────────────────────────────────────────────────────────────────┤
  18734.    │ < Make Library >   <Make Library and Exit >   < Cancel >   < Help > │
  18735.    └───────────────────────────────┼─────────────────────────────────────┘
  18736.                                    │
  18737.                                    │Makes a library
  18738.                                     and exits to DOS
  18739.  
  18740.    Figure H.1 Make Library Dialog Box
  18741.  
  18742.    To create a Quick library, perform the following steps:
  18743.  
  18744.    1. Enter the name of the library you wish to create in the Quick-Library
  18745.       File Name text box.
  18746.  
  18747.       If you enter only a base name (that is, a file name with no extension),
  18748.       QuickBASIC automatically appends the extension .QLB when it creates the
  18749.       library. If you want your library to have no extension, add a
  18750.       terminating period (.) to the base name. Otherwise, you may enter any
  18751.       base name and extension you like (except the name of a loaded Quick
  18752.       library), consistent with DOS file-name rules.
  18753.  
  18754.    2. Select the Produce Debug Code check box only if you are specifically
  18755.       trying to track a bug you believe to be in a library that you are
  18756.       updating. It makes your library larger, slows program execution and
  18757.       gives only a small amount of error control, mostly in regard to
  18758.       checking of array bounds.
  18759.  
  18760.    3. Create the Quick library:
  18761.  
  18762.       ■ Choose the Make Library command button if you want to remain in the
  18763.         environment after the Quick library is created.
  18764.  
  18765.       ■ Choose the Make Library and Exit command button if you want to return
  18766.         to the DOS command level after the Quick library is created.
  18767.  
  18768.    ──────────────────────────────────────────────────────────────────────────
  18769.    NOTE
  18770.      When you make a Quick library, be aware that if it is ever to be used
  18771.      with a nonlibrary module that needs to trap events such as keystrokes,
  18772.      then one of the modules in the library must contain at least one
  18773.      event-trapping statement. This statement can be as simple as TIMER OFF,
  18774.      but without it events are not trapped correctly in the Quick library.
  18775.    ──────────────────────────────────────────────────────────────────────────
  18776.  
  18777.  
  18778.  H.4  Using Quick Libraries
  18779.  
  18780.    This section explains how to load a Quick library when you start
  18781.    QuickBASIC and how to view the contents of a Quick library. It also gives
  18782.    facts that you should remember when procedures within a Quick library
  18783.    perform floating-point arithmetic.
  18784.  
  18785.  H.4.1  Loading a Quick Library
  18786.  
  18787.    To load a Quick library, you must specify the name of the desired library
  18788.    on the command line when you start QuickBASIC using the following syntax:
  18789.  
  18790.    QB[[programname]] /L [[libraryname]]
  18791.  
  18792.    If you start QuickBASIC with the /L option and supply the name of a
  18793.    library (libraryname), QuickBASIC loads the specified library and places
  18794.    you in the programming environment. The contents of the library are now
  18795.    available for use. If you start QuickBASIC with the /L option but don't
  18796.    specify a library, QuickBASIC loads the library QB.QLB (see Section H.5).
  18797.  
  18798.    You can also start QuickBASIC with the /RUN option followed by both a
  18799.    program name (programname) and the /L option. In this case, QuickBASIC
  18800.    loads both the program and the specified Quick library, then runs the
  18801.    program without stopping at the programming environment.
  18802.  
  18803.    ──────────────────────────────────────────────────────────────────────────
  18804.    NOTE
  18805.      When using Quick libraries to represent program modules, remember to
  18806.      update the .MAK file to keep it consistent with the modules in the
  18807.      evolving program. (This is done with the Unload File command from the
  18808.      File menu.) If the .MAK file is not up to date, it may cause QuickBASIC
  18809.      to load a module containing a procedure definition with the same name as
  18810.      one defined in the Quick library, which in turn causes the error message
  18811.      Duplicate definition.
  18812.    ──────────────────────────────────────────────────────────────────────────
  18813.  
  18814.    You can load only one Quick library at a time. If you specify a path,
  18815.    QuickBASIC looks where you indicate; otherwise, QuickBASIC searches for
  18816.    the Quick library in the following three locations:
  18817.  
  18818.    1. The current directory.
  18819.  
  18820.    2. The path specified for libraries by the Set Paths command.
  18821.  
  18822.    3. The path specified by the LIB environment variable. (See your DOS
  18823.       documentation for information about environment variables.)
  18824.  
  18825.    Example
  18826.  
  18827.    The following command starts QuickBASIC and runs the program REPORT.BAS
  18828.    using the routines in the library FIGS.QLB:
  18829.  
  18830.    QB /RUN REPORT.BAS /L FIGS.QLB
  18831.  
  18832.  H.4.2  Floating-Point Arithmetic in Quick Libraries
  18833.  
  18834.    BASIC procedures within Quick libraries represent code compiled with the
  18835.    BC command-line compiler. These procedures share significant
  18836.    characteristics with executable files. For example, both executable files
  18837.    and Quick libraries perform floating-point arithmetic faster and with a
  18838.    higher degree of accuracy than the same calculations performed within the
  18839.    QuickBASIC environment. For more information, see Chapter 16, "The Run
  18840.    Menu," in Learning to Use Microsoft QuickBASIC.
  18841.  
  18842.  H.4.3  Viewing the Contents of a Quick Library
  18843.  
  18844.    Because a Quick library is essentially a binary file, you cannot view its
  18845.    contents with a text editor to find out what it contains. Your
  18846.    distribution disk includes the QLBDUMP.BAS utility, which allows you to
  18847.    list all the procedures and data symbols in a given library. Follow these
  18848.    steps to view the contents of a Quick library:
  18849.  
  18850.    1. Start QuickBASIC.
  18851.  
  18852.    2. Load and run QLBDUMP.BAS.
  18853.  
  18854.    3. Enter the name of the Quick library you wish to examine in response to
  18855.       the prompt. You do not need to include the .QLB extension when you type
  18856.       the file name; however, supplying the extension does no harm.
  18857.  
  18858.       If the specified file exists and it is a Quick library, the program
  18859.       displays a list of all the symbol names in the library. In this
  18860.       context, symbol names correspond to the names of procedures in the
  18861.       library.
  18862.  
  18863.    See Chapter 3, "File and Device I/O," for a commented listing of
  18864.    QLBDUMP.BAS.
  18865.  
  18866.  
  18867.  H.5  The Supplied Library (QB.QLB)
  18868.  
  18869.    If you invoke QuickBASIC with the /L option, but do not supply a Quick
  18870.    library name, QuickBASIC automatically loads a library named QB.QLB,
  18871.    included with the QuickBASIC package. This file contains three routines,
  18872.    INTERRUPT, INT86OLD, and ABSOLUTE, that provide software-interrupt support
  18873.    for system-service calls and support for CALL ABSOLUTE. To use the
  18874.    routines in QB.QLB, you must specify it (or another library into which
  18875.    those routines have been incorporated) on the command line when you invoke
  18876.    QuickBASIC. If you wish to use these routines along with other routines
  18877.    that you have placed in libraries, make a copy of the QB.QLB library and
  18878.    use it as a basis for building a library containing all the routines you
  18879.    need.
  18880.  
  18881.  
  18882.  H.6  The .QLB File-Name Extension
  18883.  
  18884.    The extension .QLB is just a convenient convention. You can use any
  18885.    extension for your Quick library files, or no extension at all. However,
  18886.    in processing the /L libraryname option, QuickBASIC assumes that the
  18887.    listed libraryname has the .QLB extension if no other extension is
  18888.    specified. If your Quick library has no extension, you must put a period
  18889.    after the Quick-library name (libraryname.) or QuickBASIC searches for a
  18890.    file with your base name and the .QLB extension.
  18891.  
  18892.  
  18893.  H.7  Making a Library from the Command Line
  18894.  
  18895.    After making a library from within the QuickBASIC environment, you will
  18896.    notice the appearance of extra files with the extensions .OBJ and .LIB. In
  18897.    creating Quick libraries, QuickBASIC actually directs the work of three
  18898.    other programs, BC, LINK, and LIB, and then combines what they produce
  18899.    into both a Quick library and a stand-alone (.LIB) library. Once the
  18900.    process is complete, there is one object (.OBJ) file for each module in
  18901.    your Quick library and a single library (.LIB) file containing an object
  18902.    module for each object file. The files with the extension .OBJ are now
  18903.    extraneous and can be deleted. However, files with the extension .LIB are
  18904.    very important and should be preserved. These parallel libraries are the
  18905.    files QuickBASIC uses to create executable files of your programs.
  18906.  
  18907.    You can use the programs LINK and LIB to create both Quick libraries and
  18908.    stand-alone (.LIB) libraries from the command line in batch mode. If you
  18909.    want to use routines originally written and compiled in other languages in
  18910.    QuickBASIC, you must first put the other-language routines in a Quick
  18911.    library via the command line. Once the other-language routines are in the
  18912.    library, you can incorporate your BASIC modules from the command line or
  18913.    from within the QuickBASIC environment.
  18914.  
  18915.    Professional software developers should be sure to deliver both the Quick
  18916.    (.QLB) and stand-alone (.LIB) versions of libraries to customers. Without
  18917.    the .LIB libraries, end users would not be able to use your library
  18918.    routines in executable files produced with QuickBASIC.
  18919.  
  18920.    When you create a Quick library using LINK, the library BQLB45.LIB must
  18921.    always be specified after the third comma on the LINK command line or in
  18922.    response to the "Libraries" prompt.
  18923.  
  18924.  
  18925.  H.8  Using Routines from Other Languages in a Quick Library
  18926.  
  18927.    To place routines from other languages in a Quick library, you must start
  18928.    with precompiled or preassembled object files that contain the
  18929.    other-language routines you wish to use. Several other languages are
  18930.    suitable for this purpose, including Microsoft C, Microsoft Macro
  18931.    Assembler, Microsoft Pascal, Microsoft FORTRAN, and any other language
  18932.    that creates object files compatible with the Microsoft language family.
  18933.  
  18934.  H.8.1  Building a Quick Library
  18935.  
  18936.    The following is a typical scenario for building a Quick library
  18937.    containing routines from other languages:
  18938.  
  18939.    1. Suppose you begin with three modules, created in FORTRAN, C, and Macro
  18940.       Assembler. First you compile or assemble each module with the proper
  18941.       language translator to produce object files called here FOR.OBJ, C.OBJ,
  18942.       and ASM.OBJ.
  18943.  
  18944.    2. You then link the object files with the LINK option /Q, which instructs
  18945.       the linker to produce a Quick library file, as shown in the following
  18946.       command line:
  18947.  
  18948.       LINK /Q FOR.OBJ C.OBJ ASM.OBJ, MIXED.QLB,,BQLB45.LIB;
  18949.  
  18950.       The linker interprets the entry that follows the names of the object
  18951.       files (in this case MIXED.QLB) as the file name by which the linked
  18952.       modules will be known. Thus, in this case, the Quick library file is
  18953.       named MIXED.QLB.
  18954.  
  18955.    3. Now create a parallel .LIB library, using the same object files you
  18956.       just used to make the Quick library. In this case the first name
  18957.       following the LIB command is the name of the .LIB library:
  18958.  
  18959.       LIB MIXED.LIB+FOR.OBJ+C.OBJ+ASM.OBJ;
  18960.  
  18961.       It is easy to overlook this step when making a library that contains
  18962.       other-language routines, but this step is crucial if you hope to use
  18963.       the library to create a stand-alone executable file. Without these
  18964.       parallel stand-alone (.LIB) libraries, QuickBASIC cannot create an
  18965.       executable file containing their routines.
  18966.  
  18967.    4. With the other-language routines now in a Quick library and the
  18968.       original object files in a stand-alone library having the same base
  18969.       name, you can return to the QuickBASIC environment and build as many
  18970.       BASIC modules into the library as available memory permits.
  18971.  
  18972.    See Appendix G, "Compiling and Linking from DOS," for a complete
  18973.    description of the features of LINK and LIB.
  18974.  
  18975.  H.8.2  Quick Libraries with Leading Zeros in the First Code Segment
  18976.  
  18977.    A Quick library containing leading zeros in the first code segment is
  18978.    invalid, causing the message Error in loading file filename - Invalid
  18979.    format when you try to load it in QuickBASIC. For example, this can occur
  18980.    if an assembly-language routine puts data that is initialized to zero in
  18981.    the first code segment and it is subsequently listed first on the LINK
  18982.    command line when you make a Quick library. If you have this problem, do
  18983.    one of the following two things:
  18984.  
  18985.    1. Link with a BASIC module first on the LINK command line.
  18986.  
  18987.    2. Make sure that, in whatever module comes first on the LINK command
  18988.       line, the first code segment starts with a nonzero byte.
  18989.  
  18990.  H.8.3  The B_OnExit Routine
  18991.  
  18992.    QuickBASIC provides a BASIC system-level function, B_OnExit. You can use
  18993.    B_OnExit when your other-language routines take special actions that need
  18994.    to be undone before leaving the program (intentionally or otherwise) or
  18995.    rerunning the program. For example, within the QuickBASIC environment, an
  18996.    executing program that calls other-language routines in a Quick library
  18997.    may not always run to normal termination. If such routines need to take
  18998.    special actions at termination (for example, deinstallation of previously
  18999.    installed interrupt vectors), you can guarantee that your termination
  19000.    routines will always be called if you include an invocation of B_OnExit in
  19001.    the routine. The following example illustrates such a call (for
  19002.    simplicity, the example omits error-handling code). Note that such a
  19003.    function would be compiled in C in large model.
  19004.  
  19005.    #include <malloc.h>
  19006.  
  19007.    extern pascal far B_OnExit();  /* Declare the routine   */
  19008.  
  19009.    int *p_IntArray;
  19010.  
  19011.    void InitProc()
  19012.    {
  19013.       void TermProc();     /* Declare TermProc function    */
  19014.  
  19015.       /* Allocate far space for 20-integer array:          */
  19016.  
  19017.       p_IntArray = (int *)malloc(20*sizeof(int));
  19018.  
  19019.       /* Log termination routine (TermProc) with BASIC:    */
  19020.  
  19021.       B_OnExit(TermProc);
  19022.    }
  19023.  
  19024.                           /* The TermProc function is      */
  19025.    void TermProc()        /* called before any restarting  */
  19026.    {                      /* or termination of program.    */
  19027.  
  19028.       free(p_IntArray);   /* Release far space allocated   */
  19029.    }                      /* previously by InitProc.       */
  19030.  
  19031.    If the InitProc function were in a Quick library, the call to B_OnExit
  19032.    would insure proper release of the space reserved in the call to malloc,
  19033.    should the program crash. The routine could be called several times, since
  19034.    the program can be executed several times from the QuickBASIC environment.
  19035.    However, the TermProc function itself would be called only once each time
  19036.    the program runs.
  19037.  
  19038.    The following BASIC program is an example of a call to the InitProc
  19039.    function:
  19040.  
  19041.    DECLARE SUB InitProc CDECL
  19042.  
  19043.    X = SETMEM(-2048)       ' Make room for the malloc memory
  19044.                            ' allocation in C function.
  19045.    CALL InitProc
  19046.    END
  19047.  
  19048.    If more than 32 routines are registered, B_OnExit returns NULL, indicating
  19049.    there is not enough space to register the current routine. (Note that
  19050.    B_OnExit has the same return values as the Microsoft C run-time-library
  19051.    routine onexit.)
  19052.  
  19053.    B_OnExit can be used with any other-language (including assembly-language)
  19054.    routines you place in a Quick library. With programs compiled and linked
  19055.    completely from the command line, B_OnExit is optional.
  19056.  
  19057.  
  19058.  H.9  Memory Considerations with Quick Libraries
  19059.  
  19060.    Because a Quick library is essentially an executable file (although it
  19061.    cannot be invoked by itself from the DOS command line), it is quite large
  19062.    in comparison to the sum of the sizes of its source files. This puts an
  19063.    upper limit on the number of routines you can put in a Quick library. To
  19064.    determine how large your Quick library can be, add up the memory required
  19065.    for DOS, QB.EXE, and your program's main module. An easy way to estimate
  19066.    these factors is to boot your machine, start QuickBASIC with your program,
  19067.    and enter this command in the Immediate window:
  19068.  
  19069.    PRINT FRE (-1)
  19070.  
  19071.    This command shows you the number of bytes of free memory. This indicates
  19072.    the maximum size for any Quick library associated with this program. In
  19073.    most cases the amount of memory required for a Quick library is about the
  19074.    same as the size of its disk file. One exception to this rule of thumb is
  19075.    a library with procedures that use a lot of strings; such a program may
  19076.    require somewhat more memory.
  19077.  
  19078.  
  19079.  H.10  Making Compact Executable Files
  19080.  
  19081.    As discussed above, when QuickBASIC creates a Quick library, it also
  19082.    creates a stand-alone (.LIB) library of object modules in which each
  19083.    object module corresponds to one of the modules in the Quick library. When
  19084.    you make an executable file, QuickBASIC searches the stand-alone (.LIB)
  19085.    library for object modules containing the procedures referenced in the
  19086.    program.
  19087.  
  19088.    If an object module in the library does not contain procedures referenced
  19089.    in the program, it is not included in the executable file. However, a
  19090.    single module may contain many procedures, and if even one of them is
  19091.    referenced in the program all are included in the executable file.
  19092.    Therefore, even if a program uses only one of four procedures in a certain
  19093.    module, that entire module becomes part of the final executable file.
  19094.  
  19095.    To make your executable files as compact as possible, you should maintain
  19096.    a library in which each module contains only closely related procedures.
  19097.    If you have any doubts about what a library contains, list its contents
  19098.    with the utility QLBDUMP.BAS, described in Section H.4.3, "Viewing the
  19099.    Contents of a Quick Library."
  19100.  
  19101.  
  19102.  
  19103.  ────────────────────────────────────────────────────────────────────────────
  19104.  Appendix I  Error Messages
  19105.  
  19106.    During development of a BASIC program with QuickBASIC, the following types
  19107.    of errors can occur:
  19108.  
  19109.    ■ Invocation errors
  19110.  
  19111.    ■ Compile-time errors
  19112.  
  19113.    ■ Link-time errors
  19114.  
  19115.    ■ Run-time errors
  19116.  
  19117.    Each type of error is associated with a particular step in the program
  19118.    development process. Invocation errors occur when you invoke QuickBASIC
  19119.    with the QB or BC commands. Compile-time errors (and warnings) occur
  19120.    during compilation, and run-time errors occur when the program is
  19121.    executing. Link-time errors occur only when you use the LINK command to
  19122.    link object files created with BC or other language compilers.
  19123.  
  19124.    Section I.2 lists alphabetically the invocation, compile-time, and
  19125.    run-time error messages, along with any error codes that are assigned.
  19126.    Table I.1 lists the run-time error messages and error codes in numerical
  19127.    order. Section I.3 lists the Microsoft Overlay Linker error messages, and
  19128.    Section I.4, the Microsoft Library Manager error messages.
  19129.  
  19130.  
  19131.  I.1  Error-Message Display
  19132.  
  19133.    When a run-time error occurs within the QuickBASIC environment (with
  19134.    default screen options), the error message appears in a dialog box and the
  19135.    cursor is placed on the line where the error occurred.
  19136.  
  19137.    In stand-alone executable programs (that is, programs that are executed by
  19138.    entering the base name of the executable file at the system prompt), the
  19139.    run-time system prints the error messages followed by an address, unless
  19140.    the /D, /E, or /W option is specified on the BC command line. In those
  19141.    cases, the error message is followed by the number of the line in which
  19142.    the error occurred. The standard forms of this type of error message are
  19143.    as follows:
  19144.  
  19145.    Error n in module module-name at address segment:offset
  19146.  
  19147.    and
  19148.  
  19149.    Error n in line linenumber of module module-name at
  19150.    address segment:offset
  19151.  
  19152.    An ERR code is listed for some errors. If an error occurs, the value
  19153.    returned by ERR is set to the appropriate code when an error-trapping
  19154.    subroutine is entered. (Error-trapping routines are entered via the ON
  19155.    ERROR statement.) The ERR value remains unchanged until a RESUME statement
  19156.    returns control to the main program. See Chapter 6, "Error and Event
  19157.    Trapping," for more information.
  19158.  
  19159.    Table I.1 lists the error codes in numerical order. See the alphabetical
  19160.    listing for explanations of the errors.
  19161.  
  19162.    Table I.1  Run-Time Error Codes
  19163. ╓┌─┌────────┌───────────────────────────┌────────┌───────────────────────────╖
  19164.    Code     Description                 Code     Description
  19165.    ──────────────────────────────────────────────────────────────────────────
  19166.    2        Syntax error                53       File not found
  19167.  
  19168.    3        RETURN without GOSUB        54       Bad file mode
  19169.  
  19170.    4        Out of DATA                 55       File already open
  19171.  
  19172.    5        Illegal function call       56       FIELD statement active
  19173.  
  19174.    6        Overflow                    57       Device I/O error
  19175.    Code     Description                 Code     Description
  19176.    ──────────────────────────────────────────────────────────────────────────
  19177.   6        Overflow                    57       Device I/O error
  19178.  
  19179.    7        Out of memory               58       File already exists
  19180.  
  19181.    9        Subscript out of range      59       Bad record length
  19182.  
  19183.    10       Duplicate definition        61       Disk full
  19184.  
  19185.    11       Division by zero            62       Input past end of file
  19186.  
  19187.    13       Type mismatch               63       Bad record number
  19188.  
  19189.    14       Out of string space         64       Bad file name
  19190.  
  19191.    16       String formula too complex  67       Too many files
  19192.  
  19193.    19       No RESUME                   68       Device unavailable
  19194.  
  19195.    20       RESUME without error        69       Communication-buffer
  19196.    Code     Description                 Code     Description
  19197.    ──────────────────────────────────────────────────────────────────────────
  19198.   20       RESUME without error        69       Communication-buffer
  19199.                                                  overflow
  19200.  
  19201.    24       Device timeout              70       Permission denied
  19202.  
  19203.    25       Device fault                71       Disk not ready
  19204.  
  19205.    27       Out of paper                72       Disk-media error
  19206.  
  19207.    39       CASE ELSE expected          73       Advanced feature unavailable
  19208.  
  19209.    40       Variable required           74       Rename across disks
  19210.  
  19211.    50       FIELD overflow              75       Path/File access error
  19212.  
  19213.    51       Internal error              76       Path not found
  19214.  
  19215.    52       Bad file name or number
  19216.    ──────────────────────────────────────────────────────────────────────────
  19217.    Code     Description                 Code     Description
  19218.    ──────────────────────────────────────────────────────────────────────────
  19219.   ──────────────────────────────────────────────────────────────────────────
  19220.  
  19221.  
  19222.  
  19223.  I.2  Invocation, Compile-Time, and Run-Time Error Messages
  19224.  
  19225.  Advanced feature unavailable
  19226.  
  19227.    You are attempting to use a feature of QuickBASIC that is available with
  19228.    another version of BASIC, or supported only under a later version of DOS.
  19229.    (Compile-time or run-time error)
  19230.  
  19231.    ERR code: 73
  19232.  
  19233.  Argument-count mismatch
  19234.  
  19235.    You are using an incorrect number of arguments with a BASIC subprogram or
  19236.    function. (Compile-time error)
  19237.  
  19238.  Array already dimensioned
  19239.  
  19240.    This error can be caused by any of the following:
  19241.  
  19242.    ■ More than one DIM statement for the same static array.
  19243.  
  19244.    ■ A DIM statement after the initial use of an array. Dynamic arrays must
  19245.      be deallocated with the ERASE statement before they can be redimensioned
  19246.      with DIM; dynamic arrays may also be redimensioned with the REDIM
  19247.      statement.
  19248.  
  19249.    ■ An OPTION BASE statement that occurs after an array is dimensioned.
  19250.  
  19251.    (Compile-time or run-time error)
  19252.  
  19253.  Array not defined
  19254.  
  19255.    An array is referenced but never defined. (Compile-time error)
  19256.  
  19257.  Array not dimensioned
  19258.  
  19259.    An array is referenced but not dimensioned. If you are compiling the
  19260.    program with BC, this error is not "fatal"; the program will execute,
  19261.    although program results may be incorrect. (Compile-time warning)
  19262.  
  19263.  Array too big
  19264.  
  19265.    There is not enough user data space to accommodate the array declaration.
  19266.    Reduce the size of the array or use the $DYNAMIC metacommand. You may also
  19267.    get this error if the array size exceeds 64K, the array is not dynamic,
  19268.    and the /AH option is not used. Reduce the size of the array, or make the
  19269.    array dynamic and use the /AH command-line option. (Compile-time error)
  19270.  
  19271.  AS clause required
  19272.  
  19273.    A variable declared with an AS clause is referenced without one. If the
  19274.    first declaration of a variable has an AS clause, every subsequent DIM,
  19275.    REDIM, SHARED, and COMMON statement that references that variable must
  19276.    have an AS clause. (Compile-time error)
  19277.  
  19278.  AS clause required on first declaration
  19279.  
  19280.    A variable that has not been declared using an AS clause is being
  19281.    referenced with an AS clause. (Compile-time error)
  19282.  
  19283.  AS missing
  19284.  
  19285.    The compiler expects an AS keyword, as in OPEN "FILENAME" FOR INPUT AS #1.
  19286.    (Compile-time error)
  19287.  
  19288.  Asterisk missing
  19289.  
  19290.    The asterisk is missing from a string definition in a user type.
  19291.    (Compile-time error)
  19292.  
  19293.  Bad file mode
  19294.  
  19295.    This error occurs in the following situations:
  19296.  
  19297.    ■ The program tries to use PUT or GET with a sequential file or execute an
  19298.      OPEN statement with a file mode other than I, O, or R.
  19299.  
  19300.    ■ The program tries to use a FIELD statement with a file not opened for
  19301.      random access.
  19302.  
  19303.    ■ The program tries to print to a file opened for input.
  19304.  
  19305.    ■ The program tries to read from a file opened for output or appending.
  19306.  
  19307.    ■ QuickBASIC tries to use an include file previously saved in compressed
  19308.      format. Include files must be saved in text format. Reload the include
  19309.      file, save it in text format, then try to run the program again.
  19310.  
  19311.    ■ You try to load a corrupt binary program.
  19312.  
  19313.    (Run-time error)
  19314.  
  19315.    ERR code: 54
  19316.  
  19317.  Bad file name
  19318.  
  19319.    An illegal form is used for the file name with LOAD, SAVE, KILL, or OPEN
  19320.    (for example, the file name has too many characters). (Run-time error)
  19321.  
  19322.    ERR code: 64
  19323.  
  19324.  Bad file name or number
  19325.  
  19326.    A statement or command references a file with a file name or number that
  19327.    is not specified in the OPEN statement or is out of the range of file
  19328.    numbers specified earlier in the program. (Run-time error)
  19329.  
  19330.    ERR code: 52
  19331.  
  19332.  Bad record length
  19333.  
  19334.    A GET or PUT statement that specified a record variable whose length did
  19335.    not match the record length specified in the corresponding OPEN statement
  19336.    was executed. (Run-time error)
  19337.  
  19338.    ERR code: 59
  19339.  
  19340.  Bad record number
  19341.  
  19342.    In a PUT or GET statement, the record number is less than or equal to
  19343.    zero. (Run-time error)
  19344.  
  19345.    ERR code: 63
  19346.  
  19347.  BASE missing
  19348.  
  19349.    QuickBASIC expected the keyword BASE here, as in OPTION BASE.
  19350.    (Compile-time error)
  19351.  
  19352.  Binary source file
  19353.  
  19354.    The file you have attempted to compile is not an ASCII file. All source
  19355.    files saved by BASICA should be saved with the ,A option. QuickBASIC also
  19356.    uses this message to warn you when you try to use the /ZI or /ZD CodeView
  19357.    options with binary source files. (Compile-time error)
  19358.  
  19359.  Block IF without END IF
  19360.  
  19361.    There is no corresponding END IF in a block IF construct. (Compile-time
  19362.    error)
  19363.  
  19364.  Buffer size expected after /C:
  19365.  
  19366.    You must specify a buffer size after the /C option. (BC invocation error)
  19367.  
  19368.  BYVAL allowed only with numeric arguments
  19369.  
  19370.    BYVAL does not accept string or record arguments. (Compile-time error)
  19371.  
  19372.  /C: buffer size too large
  19373.  
  19374.    The maximum size of the communications buffer is 32,767 bytes. (BC
  19375.    invocation error)
  19376.  
  19377.  Cannot continue
  19378.  
  19379.    While debugging, you have made a change that prevents execution from
  19380.    continuing. (Run-time error)
  19381.  
  19382.  Cannot find file (filename). Input path:
  19383.  
  19384.    This error occurs when QuickBASIC cannot find a Quick library or utility
  19385.    (BC.EXE, LINK.EXE, LIB.EXE, or QB.EXE) required by the program. Enter the
  19386.    correct path name, or press CTRL+C to return to the DOS prompt. (QB
  19387.    invocation error)
  19388.  
  19389.  Cannot generate listing for BASIC binary source files
  19390.  
  19391.    You are attempting to compile a binary source file with the BC command and
  19392.    the /A option. Recompile without the /A option. (BC invocation error)
  19393.  
  19394.  Cannot start with `FN'
  19395.  
  19396.    You used "FN" as the first two letters of a subprogram or variable name.
  19397.    "FN" can only be used as the first two letters when calling a DEF FN
  19398.    function. (Compile-time error)
  19399.  
  19400.  CASE ELSE expected
  19401.  
  19402.    No matching case was found for an expression in a SELECT CASE statement.
  19403.    (Run-time error)
  19404.  
  19405.    ERR code: 39
  19406.  
  19407.  CASE without SELECT
  19408.  
  19409.    The first part of a SELECT CASE statement is missing or misspelled.
  19410.    (Compile-time error)
  19411.  
  19412.  Colon expected after /C
  19413.  
  19414.    A colon is required between the option and the buffer size argument. (BC
  19415.    invocation error)
  19416.  
  19417.  Comma missing
  19418.  
  19419.    QuickBASIC expects a comma. (Compile-time error)
  19420.  
  19421.  COMMON and DECLARE must precede executable statements
  19422.  
  19423.    A COMMON statement or a DECLARE statement is misplaced. COMMON and DECLARE
  19424.    statements must appear before any executable statements. All BASIC
  19425.    statements are executable except the following:
  19426.  
  19427.    ■ COMMON
  19428.  
  19429.    ■ DEFtype
  19430.  
  19431.    ■ DIM (for static arrays)
  19432.  
  19433.    ■ OPTION BASE
  19434.  
  19435.    ■ REM
  19436.  
  19437.    ■ TYPE
  19438.  
  19439.    ■ All metacommands
  19440.  
  19441.    (Compile-time error)
  19442.  
  19443.  COMMON in Quick library too small
  19444.  
  19445.    More common variables are specified in the module than in the currently
  19446.    loaded Quick library. (Compile-time error)
  19447.  
  19448.  COMMON name illegal
  19449.  
  19450.    QuickBASIC encountered an illegal /blockname/ specification (for example,
  19451.    a blockname that is a BASIC reserved word) in a named COMMON block.
  19452.    (Compile-time error).
  19453.  
  19454.  Communication-buffer overflow
  19455.  
  19456.    During remote communications, the receive buffer overflowed. The size of
  19457.    the receive buffer is set by the /C command line option or the RB option
  19458.    in the OPEN COM statement. Try checking the buffer more frequently (with
  19459.    the LOC function) or emptying it more often (with the INPUT$ function).
  19460.    (Run-time error)
  19461.  
  19462.    ERR code: 69
  19463.  
  19464.  CONST/DIM SHARED follows SUB/FUNCTION
  19465.  
  19466.    CONST and DIM SHARED statements should appear before any subprogram or
  19467.    FUNCTION procedure definitions. If you are compiling your program with BC,
  19468.    this error is not "fatal"; the program will execute, although the results
  19469.    may be incorrect. (Compile-time warning)
  19470.  
  19471.  Control structure in IF...THEN...ELSE incomplete
  19472.  
  19473.    An unmatched NEXT, WEND, END IF, END SELECT, or LOOP statement appears in
  19474.    a single-line IF...THEN...ELSE statement. (Compile-time error)
  19475.  
  19476.  Data-memory overflow
  19477.  
  19478.    There is too much program data to fit in memory. This error is often
  19479.    caused by too many constants, or too much static array data. If you are
  19480.    using the BC command, or the Make EXE File or Make Library commands, try
  19481.    turning off any debugging options. If memory is still exhausted, break
  19482.    your program into parts and use the CHAIN statement or use the $DYNAMIC
  19483.    metacommand. (Compile-time error)
  19484.  
  19485.  DECLARE required
  19486.  
  19487.    An implicit SUB or FUNCTION procedure call appears before the procedure
  19488.    definition. (An implicit call does not use the CALL statement.) All
  19489.    procedures must be defined or declared before they are implicitly called.
  19490.    (Compile-time error)
  19491.  
  19492.  DEF FN not allowed in control statements
  19493.  
  19494.    DEF FN function definitions are not permitted inside control constructs
  19495.    such as IF...THEN...ELSE and SELECT CASE. (Compile-time error)
  19496.  
  19497.  DEF without END DEF
  19498.  
  19499.    There is no corresponding END DEF in a multiline function definition.
  19500.    (Compile-time error)
  19501.  
  19502.  DEFtype character specification illegal
  19503.  
  19504.    A DEFtype statement is entered incorrectly. DEF can only be followed by
  19505.    LNG, DBL, INT, SNG, STR, or (for user-defined functions) a blank space.
  19506.    (Compile-time error)
  19507.  
  19508.  Device fault
  19509.  
  19510.    A device has returned a hardware error. If this message occurs while data
  19511.    are being transmitted to a communications file, it indicates that the
  19512.    signals being tested with the OPEN COM statement were not found in the
  19513.    specified period of time. (Run-time error)
  19514.  
  19515.    ERR code: 25
  19516.  
  19517.  Device I/O error
  19518.  
  19519.    An I/O error occurred on a device I/O operation. The operating system
  19520.    cannot recover from the error. (Run-time error)
  19521.  
  19522.    ERR code: 57
  19523.  
  19524.  Device timeout
  19525.  
  19526.    The program did not receive information from an I/O device within a
  19527.    predetermined amount of time. (Run-time error)
  19528.  
  19529.    ERR code: 24
  19530.  
  19531.  Device unavailable
  19532.  
  19533.    The device you are attempting to access is not on line or does not exist.
  19534.  
  19535.    (Run-time error)
  19536.  
  19537.    ERR code: 68
  19538.  
  19539.  Disk full
  19540.  
  19541.    There is not enough room on the disk for the completion of a PRINT, WRITE,
  19542.    or CLOSE operation. This error can also occur if there is not enough room
  19543.    for QuickBASIC to write out an object or executable file. (Run-time error)
  19544.  
  19545.    ERR code: 61
  19546.  
  19547.  Disk-media error
  19548.  
  19549.    Disk-drive hardware has detected a physical flaw on the disk. (Run-time
  19550.    error)
  19551.  
  19552.    ERR code: 72
  19553.  
  19554.  Disk not ready
  19555.  
  19556.    The disk-drive door is open, or no disk is in the drive. (Run-time error)
  19557.  
  19558.    ERR code: 71
  19559.  
  19560.  Division by zero
  19561.  
  19562.    A division by zero is encountered in an expression, or an exponentiation
  19563.    operation results in zero being raised to a negative power. (Compile-time
  19564.    or run-time error)
  19565.  
  19566.    ERR code: 11
  19567.  
  19568.  DO without LOOP
  19569.  
  19570.    The terminating LOOP clause is missing from a DO...LOOP statement.
  19571.    (Compile-time error)
  19572.  
  19573.  Document too large
  19574.  
  19575.    Your document exceeds QuickBASIC's internal limit. Divide the document
  19576.    into separate files.
  19577.  
  19578.  Duplicate definition
  19579.  
  19580.    You are using an identifier that has already been defined. For example,
  19581.    you are attempting to use the same name in a CONST statement and as a
  19582.    variable definition, or the same name for a procedure and a variable.
  19583.  
  19584.    This error also occurs if you attempt to redimension an array. You must
  19585.    use DIM or REDIM when redimensioning dynamic arrays. (Compile-time or
  19586.    run-time error)
  19587.  
  19588.    ERR code: 10
  19589.  
  19590.  Duplicate label
  19591.  
  19592.    Two program lines are assigned the same number or label. Each line number
  19593.    or label in a module must be unique. (Compile-time error)
  19594.  
  19595.  Dynamic array element illegal
  19596.  
  19597.    Dynamic array elements are not allowed with VARPTR$. (Compile-time error)
  19598.  
  19599.  Element not defined
  19600.  
  19601.    A user-defined type element is referenced but not defined. For example, if
  19602.    the user-defined type MYTYPE contained elements A, B, and C, then an
  19603.    attempt to use the variable D as an element of MYTYPE would cause this
  19604.    message to appear. (Compile-time error)
  19605.  
  19606.  ELSE without IF
  19607.  
  19608.    An ELSE clause appears without a corresponding IF. Sometimes this error is
  19609.    caused by incorrectly nested IF statements. (Compile-time error)
  19610.  
  19611.  ELSEIF without IF
  19612.  
  19613.    An ELSEIF statement appears without a corresponding IF. Sometimes this
  19614.    error is caused by incorrectly nested IF statements. (Compile-time error)
  19615.  
  19616.  END DEF without DEF
  19617.  
  19618.    An END DEF statement has no corresponding DEF statement. (Compile-time
  19619.    error)
  19620.  
  19621.  END IF without block IF
  19622.  
  19623.    The beginning of an IF block is missing. (Compile-time error)
  19624.  
  19625.  END SELECT without SELECT
  19626.  
  19627.    The end of a SELECT CASE statement appears without a beginning SELECT
  19628.    CASE. The beginning of the SELECT CASE statement may be missing or
  19629.    misspelled. (Compile-time error)
  19630.  
  19631.  END SUB or END FUNCTION must be last line in window
  19632.  
  19633.    You are attempting to add code after a procedure. You must either return
  19634.    to the main module or open another module. (Compile-time error)
  19635.  
  19636.  END SUB/FUNCTION without SUB/FUNCTION
  19637.  
  19638.    You deleted the SUB or FUNCTION statement. (Compile-time error)
  19639.  
  19640.  END TYPE without TYPE
  19641.  
  19642.    An END TYPE statement is used outside a TYPE declaration. (Compile-time
  19643.    error)
  19644.  
  19645.  Equal sign missing
  19646.  
  19647.    QuickBASIC expects an equal sign. (Compile-time error)
  19648.  
  19649.  Error during QuickBASIC initialization
  19650.  
  19651.    Several conditions can cause this error. It is most commonly caused when
  19652.    there is not enough memory in the machine to load QuickBASIC. If you are
  19653.    loading a Quick library, try reducing the size of the library.
  19654.  
  19655.    This error may occur when you attempt to use QuickBASIC on unsupported
  19656.    hardware. (QB invocation error)
  19657.  
  19658.  Error in loading file (filename)──Cannot find file
  19659.  
  19660.    This error occurs when redirecting input to QuickBASIC from a file. The
  19661.    input file is not at the location specified on the command line. (QB
  19662.    invocation error)
  19663.  
  19664.  Error in loading file (filename)──Disk I/O error
  19665.  
  19666.    This error is caused by physical problems accessing the disk, for example,
  19667.    if the drive door is left open. (QB invocation error)
  19668.  
  19669.  Error in loading file (filename)──DOS memory-area error
  19670.  
  19671.    The area of memory used by DOS has been written to, either by an assembly
  19672.    language routine or with the POKE statement. (QB invocation error)
  19673.  
  19674.  Error in loading file (filename)──Invalid format
  19675.  
  19676.    You are attempting to load a Quick library that is not in the correct
  19677.    format. This error can occur if you are attempting to use a Quick library
  19678.    created with a previous version of QuickBASIC, if you are trying to use a
  19679.    file that has not been processed with QuickBASIC's Make Library command or
  19680.    the /QU option from LINK, or if you are trying to load a stand-alone
  19681.    (.LIB) library with QuickBASIC. (QB invocation error)
  19682.  
  19683.  Error in loading file (filename)──Out of memory
  19684.  
  19685.    More memory is required than is available. For example, there may not be
  19686.    enough memory to allocate a file buffer. Try reducing the size of your DOS
  19687.    buffers, getting rid of any terminate-and-stay resident programs, or
  19688.    eliminating some device drivers. If you have large arrays, try placing a
  19689.    $DYNAMIC metacommand at the top of your program. If you have documents
  19690.    loaded, then unloading them will free some memory. (Run-time error)
  19691.  
  19692.  EXIT DO not within DO...LOOP
  19693.  
  19694.    An EXIT DO statement is used outside of a DO...LOOP statement.
  19695.    (Compile-time error)
  19696.  
  19697.  EXIT not within FOR...NEXT
  19698.  
  19699.    An EXIT FOR statement is used outside of a FOR...NEXT statement.
  19700.    (Compile-time error)
  19701.  
  19702.  Expected: item
  19703.  
  19704.    This is a syntax error. The cursor is positioned at the unexpected item.
  19705.    (Compile-time error)
  19706.  
  19707.  Expression too complex
  19708.  
  19709.    This error is caused when certain internal limitations are exceeded. For
  19710.    example, during expression evaluation, strings that are not associated
  19711.    with variables are assigned temporary locations. A large number of such
  19712.    strings can cause this error to occur. Try simplifying expressions, and
  19713.    assigning strings to variables. (Compile-time error)
  19714.  
  19715.  Extra file name ignored
  19716.  
  19717.    You specified too many files on the command line; the last file name on
  19718.    the line is ignored. (BC invocation error)
  19719.  
  19720.  Far heap corrupt
  19721.  
  19722.    The far-heap memory has been corrupted by one of the following:
  19723.  
  19724.    ■ The QB compiler does not support a terminate-and-stay-resident program
  19725.      resident in DOS.
  19726.  
  19727.    ■ The POKE statement modified areas of memory used by QuickBASIC. (This
  19728.      may modify the descriptor for a dynamic array of numbers or fixed-length
  19729.      strings.)
  19730.  
  19731.    ■ The program called an other-language routine that modified areas of
  19732.      memory used by QuickBASIC. (This may modify the descriptor for a dynamic
  19733.      array of numbers or fixed-length strings.
  19734.  
  19735.    (Compile-time error)
  19736.  
  19737.  FIELD overflow
  19738.  
  19739.    A FIELD statement is attempting to allocate more bytes than were specified
  19740.    for the record length of a random file. (Run-time error)
  19741.  
  19742.    ERR code: 50
  19743.  
  19744.  FIELD statement active
  19745.  
  19746.    A GET or PUT statement referred to a record variable used in a a file with
  19747.    space previously allocated by the FIELD statement. GET or PUT with a
  19748.    record variable argument may only be used on files where no FIELD
  19749.    statements have been executed. (Run-time error)
  19750.  
  19751.    ERR code: 56
  19752.  
  19753.  File already exists
  19754.  
  19755.    The file name specified in a NAME statement is identical to a file name
  19756.    already in use on the disk. (Run-time error)
  19757.  
  19758.    ERR code: 58
  19759.  
  19760.  File already open
  19761.  
  19762.    A sequential-output-mode OPEN statement is issued for a file that is
  19763.    already open, or a KILL statement is given for a file that is open.
  19764.    (Run-time error)
  19765.  
  19766.    ERR code: 55
  19767.  
  19768.  File not found
  19769.  
  19770.    A FILES, KILL, NAME, OPEN or RUN statement references a file that does not
  19771.    exist. (Run-time error)
  19772.  
  19773.    ERR code: 53
  19774.  
  19775.  File not found in module module-name at address segment:offset
  19776.  
  19777.    A FILES, KILL, NAME, OPEN or RUN statement references a file that does not
  19778.    exist. This error message is equivalent to the File not found message, but
  19779.    it occurs during execution of compiled programs. The module-name is the
  19780.    name of the calling module. The address is the location of the error in
  19781.    the code. (Run-time error)
  19782.  
  19783.    ERR code: 53
  19784.  
  19785.  File previously loaded
  19786.  
  19787.    You are attempting to load a file that is already in memory. (Compile-time
  19788.    error)
  19789.  
  19790.  Fixed-length string illegal
  19791.  
  19792.    You are attempting to use a fixed-length string as a formal parameter.
  19793.    (Compile-time error)
  19794.  
  19795.  FOR index variable already in use
  19796.  
  19797.    This error occurs when an index variable is used more than once in nested
  19798.    FOR loops. (Compile-time error)
  19799.  
  19800.  FOR index variable illegal
  19801.  
  19802.    This error is usually caused when an incorrect variable type is used in a
  19803.    FOR-loop index. A FOR-loop index variable must be a simple numeric
  19804.    variable. (Compile-time error)
  19805.  
  19806.  FOR without NEXT
  19807.  
  19808.    Each FOR statement must have a matching NEXT statement. (Compile-time
  19809.    error)
  19810.  
  19811.  Formal parameter specification illegal
  19812.  
  19813.    There is an error in a function or subprogram parameter list.
  19814.    (Compile-time error)
  19815.  
  19816.  Formal parameters not unique
  19817.  
  19818.    A FUNCTION or SUB declaration contains duplicate parameters, as in this
  19819.    example: SUB GetName(A,B,C,A) STATIC. (Compile-time error)
  19820.  
  19821.  Function already defined
  19822.  
  19823.    This error occurs when a previously defined FUNCTION is redefined.
  19824.    (Compile-time error)
  19825.  
  19826.  Function name illegal
  19827.  
  19828.    A BASIC reserved word is used as a user-defined FUNCTION name.
  19829.    (Compile-time error)
  19830.  
  19831.  Function not defined
  19832.  
  19833.    You must declare or define a FUNCTION before using it. (Compile-time
  19834.    error)
  19835.  
  19836.  GOSUB missing
  19837.  
  19838.    The GOSUB is missing from an ON event statement. (Compile-time error)
  19839.  
  19840.  GOTO missing
  19841.  
  19842.    The GOTO is missing from an ON ERROR statement. (Compile-time error)
  19843.  
  19844.  GOTO or GOSUB expected
  19845.  
  19846.    QuickBASIC expects a GOTO or GOSUB statement. (Compile-time error)
  19847.  
  19848.  Help not found
  19849.  
  19850.    Help was requested but not found, and the program contains errors
  19851.    prohibiting QuickBASIC from building a variable table. Press F5 to view
  19852.    the line that caused the error.
  19853.  
  19854.  Identifier cannot end with %, &, !, #, or $
  19855.  
  19856.    The above suffixes are not allowed in type identifiers, subprogram names,
  19857.    or names appearing in COMMON statements. (Compile-time error)
  19858.  
  19859.  Identifier cannot include period
  19860.  
  19861.    User-defined type identifier and record element names cannot contain
  19862.    periods. The period should only be used as a record variable separator. In
  19863.    addition, a variable name cannot contain a period if the part of the name
  19864.    before the period has been used in an identifier AS usertype clause
  19865.    anywhere in the program. If you have programs that use the period in
  19866.    variable names, it is recommended that you change them to use mixed case
  19867.    instead. For example, variable ALPHA.BETA would become AlphaBeta.
  19868.    (Compile-time error)
  19869.  
  19870.  Identifier expected
  19871.  
  19872.    You are attempting to use a number or a BASIC reserved word where an
  19873.    identifier is expected. (Compile-time error)
  19874.  
  19875.  Identifier too long
  19876.  
  19877.    Identifiers must not be longer than 40 characters. (Compile-time error)
  19878.  
  19879.  Illegal function call
  19880.  
  19881.    A parameter that is out of range is passed to a math or string function. A
  19882.    function-call error can also occur for the following reasons:
  19883.  
  19884.    ■ A negative or unreasonably large subscript is used.
  19885.  
  19886.    ■ A negative number is raised to a power that is not an integer.
  19887.  
  19888.    ■ A negative record number is given when using GET file or PUT file.
  19889.  
  19890.    ■ An improper or out-of-range argument is given to a function.
  19891.  
  19892.    ■ A BLOAD or BSAVE operation is directed to a nondisk device.
  19893.  
  19894.    ■ An I/O function or statement (LOC or LOF, for example) is performed on a
  19895.      device that does not support it.
  19896.  
  19897.    ■ Strings are concatenated to create a string greater than 32,767
  19898.      characters in length.
  19899.  
  19900.    (Run-time error)
  19901.  
  19902.    ERR code: 5
  19903.  
  19904.  Illegal in direct mode
  19905.  
  19906.    The statement is valid only within a program and cannot be used in the
  19907.    Immediate window. (Compile-time error)
  19908.  
  19909.  Illegal in procedure or DEF FN
  19910.  
  19911.    The statement is not allowed inside a procedure. (Compile-time error)
  19912.  
  19913.  Illegal number
  19914.  
  19915.    The format of the number does not correspond to a valid number format. You
  19916.    have probably made a typographical error. For example, the number 2p3 will
  19917.    produce this error. (Compile-time error)
  19918.  
  19919.  Illegal outside of SUB, FUNCTION, or DEF FN
  19920.  
  19921.    This statement is not allowed in module-level code. (Compile-time error)
  19922.  
  19923.  Illegal outside of SUB/FUNCTION
  19924.  
  19925.    The statement is not allowed in module-level code or DEF FN functions.
  19926.    (Compile-time error)
  19927.  
  19928.  Illegal outside of TYPE block
  19929.  
  19930.    The element AS type clause is permitted only within a TYPE...END TYPE
  19931.    block. (Compile-time error)
  19932.  
  19933.  Illegal type character in numeric constant
  19934.  
  19935.    A numeric constant contains an inappropriate type-declaration character.
  19936.    (Compile-time error)
  19937.  
  19938.  $INCLUDE-file access error
  19939.  
  19940.    The include file named in the $INCLUDE metacommand cannot be located.
  19941.    (Compile-time error)
  19942.  
  19943.  Include file too large
  19944.  
  19945.    Your include file exceeds QuickBASIC's internal limit. Break the file into
  19946.    separate files. (Compile-time error)
  19947.  
  19948.  Input file not found
  19949.  
  19950.    The source file you gave on the command line is not in the specified
  19951.    location. (BC invocation error)
  19952.  
  19953.  INPUT missing
  19954.  
  19955.    The compiler expects the keyword INPUT. (Compile-time error)
  19956.  
  19957.  Input past end of file
  19958.  
  19959.    An INPUT statement reads from a null (empty) file or from a file in which
  19960.    all data have already been read. To avoid this error, use the EOF function
  19961.    to detect the end of file. (Run-time error)
  19962.  
  19963.    ERR code: 62
  19964.  
  19965.  Input runtime module path:
  19966.  
  19967.    This prompt appears if the run-time module BRUN45.EXE is not found. Enter
  19968.    the correct path specification. This error is severe and cannot be
  19969.    trapped. (Run-time error)
  19970.  
  19971.  Integer between 1 and 32767 required
  19972.  
  19973.    The statement requires an integer argument. (Compile-time error)
  19974.  
  19975.  Internal error
  19976.  
  19977.    An internal malfunction occurred in QuickBASIC. Use the Product Assistance
  19978.    Request form included with your documentation to report to Microsoft the
  19979.    conditions under which the message appeared. (Run-time error)
  19980.  
  19981.    ERR code: 51
  19982.  
  19983.  Internal error near xxxx
  19984.  
  19985.    An internal malfunction occurred in QuickBASIC at location xxxx. Use the
  19986.    Product Assistance Request form included with your documentation to report
  19987.    the conditions under which the message appeared. (Compile-time error)
  19988.  
  19989.  Invalid character
  19990.  
  19991.    QuickBASIC found an invalid character, such as a control character, in the
  19992.    source file. (Compile-time error)
  19993.  
  19994.  Invalid constant
  19995.  
  19996.    An invalid expression is used to assign a value to a constant. Remember
  19997.    that expressions assigned to constants may contain numeric constants,
  19998.    symbolic constants, and any of the arithmetic or logical operators except
  19999.    exponentiation. A string expression assigned to a constant may consist
  20000.    only of a single literal string. (Compile-time error)
  20001.  
  20002.  Invalid DECLARE for BASIC procedure
  20003.  
  20004.    You are attempting to use the DECLARE statement keywords ALIAS, CDECL, or
  20005.    BYVAL with a BASIC procedure. ALIAS, CDECL, and BYVAL can only be used
  20006.    with non-BASIC procedures. (Compile-time error)
  20007.  
  20008.  Label not defined
  20009.  
  20010.    A line label is referenced (in a GOTO statement, for example), but does
  20011.    not occur in the program. (Compile-time error)
  20012.  
  20013.  Label not defined: label
  20014.  
  20015.    A GOTO linelabel statement refers to a nonexistent line label.
  20016.    (Compile-time error)
  20017.  
  20018.  Left parenthesis missing
  20019.  
  20020.    QuickBASIC expected a left parenthesis, or a REDIM statement tried to
  20021.    reallocate space for a scalar. (Compile-time error)
  20022.  
  20023.  Line invalid. Start again
  20024.  
  20025.    An invalid file-name character was used following the path characters "\"
  20026.    (backslash) or ":" (colon). (BC invocation error)
  20027.  
  20028.  Line number or label missing
  20029.  
  20030.    A line number or label is missing from a statement that requires one, for
  20031.    example, GOTO. (Compile-time error)
  20032.  
  20033.  Line too long
  20034.  
  20035.    Lines are limited to 255 characters. (Compile-time error)
  20036.  
  20037.  LOOP without DO
  20038.  
  20039.    The DO starting a DO...LOOP statement is missing or misspelled.
  20040.    (Compile-time error)
  20041.  
  20042.  Lower bound exceeds upper bound
  20043.  
  20044.    The lower bound exceeds the upper bound defined in a DIM statement.
  20045.    (Compile-time error)
  20046.  
  20047.  Math overflow
  20048.  
  20049.    The result of a calculation is too large to be represented in BASIC number
  20050.    format. (Compile-time error)
  20051.  
  20052.  $Metacommand error
  20053.  
  20054.    A metacommand is incorrect. If you are compiling the program with BC this
  20055.    error is not "fatal"; the program will execute, although the results may
  20056.    be incorrect. (Compile-time warning)
  20057.  
  20058.  Minus sign missing
  20059.  
  20060.    QuickBASIC expects a minus sign. (Compile-time error)
  20061.  
  20062.  Missing Event Trapping (/W) or Checking Between Statements (/V) option
  20063.  
  20064.    The program contains an ON event statement requiring one of these options.
  20065.    (Compile-time error)
  20066.  
  20067.  Missing On Error (/E) option
  20068.  
  20069.    When using the BC command, programs containing ON ERROR statements must be
  20070.    compiled with the On Error (/E) option. (Compile-time error)
  20071.  
  20072.  Missing Resume Next (/X) option
  20073.  
  20074.    When using the BC command, programs containing RESUME, RESUME NEXT, and
  20075.    RESUME 0 statements must be compiled with the Resume Next (/X) option.
  20076.    (Compile-time error)
  20077.  
  20078.  Module level code too large
  20079.  
  20080.    Your module-level code exceeds QuickBASIC's internal limit. Try moving
  20081.    some of the code into SUB or FUNCTION procedures. (Compile-time error)
  20082.  
  20083.  Module not found. Unload module from program?
  20084.  
  20085.    When loading the program, QuickBASIC did not find the file containing the
  20086.    indicated module. QuickBASIC created an empty module instead. You must
  20087.    delete the empty module before you can run the program.
  20088.  
  20089.  Must be first statement on the line
  20090.  
  20091.    In block IF...THEN...ELSE constructs, IF, ELSE, ELSEIF, and END IF can be
  20092.    preceded only by a line number or label. (Compile-time error)
  20093.  
  20094.  Name of subprogram illegal
  20095.  
  20096.    The error is caused when a subprogram name is a BASIC reserved word, or a
  20097.    subprogram name is used twice. (Compile-time error)
  20098.  
  20099.  Nested function definition
  20100.  
  20101.    A FUNCTION definition appears inside another FUNCTION definition, or
  20102.    inside an IF...THEN...ELSE clause. (Compile-time error)
  20103.  
  20104.  NEXT missing for variable
  20105.  
  20106.    A FOR statement is missing a corresponding NEXT statement. The variable is
  20107.    the FOR-loop index variable. (Compile-time error)
  20108.  
  20109.  NEXT without FOR
  20110.  
  20111.    Each NEXT statement must have a matching FOR statement. (Compile-time
  20112.    error)
  20113.  
  20114.  No line number in module-name at address segment:offset
  20115.  
  20116.    This error occurs when the error address cannot be found in the
  20117.    line-number table during error trapping. This happens if there are no
  20118.    integer line numbers between 0 and 65,527. It may also occur if the
  20119.    line-number table has been accidentally overwritten by the user program.
  20120.    This error is severe and cannot be trapped. (Run-time error)
  20121.  
  20122.  No main module. Choose Set Main Module from the Run menu to select one
  20123.  
  20124.    You are attempting to run the program after you have unloaded the main
  20125.    module. Every program must have a main module. (Compile-time error)
  20126.  
  20127.  No RESUME
  20128.  
  20129.    The end of the program was encountered while the program was in an
  20130.    error-handling routine. A RESUME statement is needed to remedy this
  20131.    situation. (Run-time error)
  20132.  
  20133.    ERR code: 19
  20134.  
  20135.  Not watchable
  20136.  
  20137.    This error occurs when you are specifying a variable in a watch
  20138.    expression. Make sure the module or procedure in the active View window
  20139.    has access to the variable you want to watch. For example, module-level
  20140.    code cannot access variables that are local to a SUB or FUNCTION.
  20141.    (Run-time error)
  20142.  
  20143.  Numeric array illegal
  20144.  
  20145.    Numeric arrays are not allowed as arguments to VARPTR$. Only simple
  20146.    variables and string array elements are permitted. (Compile-time error)
  20147.  
  20148.  Only simple variables allowed
  20149.  
  20150.    User-defined types and arrays are not permitted in READ and INPUT
  20151.    statements. Array elements that are not of a user-defined type are
  20152.    permitted. (Compile-time error)
  20153.  
  20154.  Operation requires disk
  20155.  
  20156.    You are attempting to load from, or save to, a nondisk device such as the
  20157.    printer or keyboard. (Compile-time error)
  20158.  
  20159.  Option unknown: option
  20160.  
  20161.    You have given an illegal option. (BC invocation error)
  20162.  
  20163.  Out of DATA
  20164.  
  20165.    A READ statement is executed when there are no DATA statements with unread
  20166.    data remaining in the program. (Run-time error)
  20167.  
  20168.    ERR code: 4
  20169.  
  20170.  Out of data space
  20171.  
  20172.    Try modifying your data space requirements as follows:
  20173.  
  20174.    ■ Use a smaller file buffer in the OPEN statement's LEN clause.
  20175.  
  20176.    ■ Use the $DYNAMIC metacommand to create dynamic arrays. Dynamic array
  20177.      data can usually be much larger than static array data.
  20178.  
  20179.    ■ Use fixed-length string arrays instead of variable-length string arrays.
  20180.  
  20181.    ■ Use the smallest data type that will accomplish your task. Use integers
  20182.      whenever possible.
  20183.  
  20184.    ■ Try not to use many small procedures. QuickBASIC must create several
  20185.      bytes of control information for each procedure.
  20186.  
  20187.    ■ Use CLEAR to modify the size of the stack. Use only enough stack space
  20188.      to accomplish your task.
  20189.  
  20190.    ■ Do not use source lines longer than 255 characters. Such lines require
  20191.      allocation of additional text buffer space.
  20192.  
  20193.    (Compile-time or run-time error)
  20194.  
  20195.  Out of memory
  20196.  
  20197.    More memory is required than is available. For example, there may not be
  20198.    enough memory to allocate a file buffer. Try reducing the size of your DOS
  20199.    buffers, or getting rid of any terminate-and-stay-resident programs, or
  20200.    eliminating some device drivers. If you have large arrays, try placing a
  20201.    $DYNAMIC metacommand at the top of your program. If you have documents
  20202.    loaded, unloading them will free some memory. (BC invocation,
  20203.    compile-time, or run-time error)
  20204.  
  20205.    ERR code: 7
  20206.  
  20207.  Out of paper
  20208.  
  20209.    The printer is out of paper or is not turned on. (Run-time error)
  20210.  
  20211.    ERR code: 27
  20212.  
  20213.  Out of stack space
  20214.  
  20215.    This error can occur when a recursive FUNCTION procedure nests too deeply,
  20216.    or there are too many active subroutine, FUNCTION, and SUB calls. You can
  20217.    use the CLEAR statement to increase the program's allotted stack space.
  20218.    This error cannot be trapped. (Run-time error)
  20219.  
  20220.  Out of string space
  20221.  
  20222.    String variables exceed the allocated amount of string space. (Run-time
  20223.    error)
  20224.  
  20225.    ERR code: 14
  20226.  
  20227.  Overflow
  20228.  
  20229.    The result of a calculation is too large to be represented within the
  20230.    range allowed for either floating-point or integer numbers. (Run-time
  20231.    error)
  20232.  
  20233.    ERR code: 6
  20234.  
  20235.  Overflow in numeric constant
  20236.  
  20237.    The numeric constant is too large. (Compile-time error)
  20238.  
  20239.  Parameter type mismatch
  20240.  
  20241.    A subprogram or FUNCTION parameter type does not match the DECLARE
  20242.    statement argument or the calling argument. (Compile-time error)
  20243.  
  20244.  Path not found
  20245.  
  20246.    During an OPEN, MKDIR, CHDIR, or RMDIR operation, DOS was unable to find
  20247.    the path specified. The operation is not completed. (Run-time error)
  20248.  
  20249.    ERR code: 76
  20250.  
  20251.  Path/File access error
  20252.  
  20253.    During an OPEN, MKDIR, CHDIR, or RMDIR operation, DOS was unable to make a
  20254.    correct connection between the path and file name. The operation is not
  20255.    completed. (Compile-time or run-time error)
  20256.  
  20257.    ERR code: 75
  20258.  
  20259.  Permission denied
  20260.  
  20261.    An attempt was made to write to a write-protected disk, or to access a
  20262.    locked file. (Run-time error)
  20263.  
  20264.    ERR code: 70
  20265.  
  20266.  Procedure already defined in Quick library
  20267.  
  20268.    A procedure in the Quick library has the same name as a procedure in your
  20269.    program. (Compile-time error)
  20270.  
  20271.  Procedure too large
  20272.  
  20273.    The procedure has exceeded QuickBASIC's internal limit. Make the procedure
  20274.    smaller by dividing it into several procedures. (Compile-time error)
  20275.  
  20276.  Program-memory overflow
  20277.  
  20278.    You are attempting to compile a program whose code segment is larger than
  20279.    64K. Try splitting the program into separate modules, or use the CHAIN
  20280.    statement. (Compile-time error)
  20281.  
  20282.  Read error on standard input
  20283.  
  20284.    A system error occurred while reading from the console or a redirected
  20285.    input file. (BC invocation error)
  20286.  
  20287.  Record/string assignment required
  20288.  
  20289.    The string or record variable assignment is missing from the LSET
  20290.    statement. (Compile-time error)
  20291.  
  20292.  Redo from start
  20293.  
  20294.    You have responded to an INPUT prompt with the wrong number or type of
  20295.    items. Retype your response in the correct form. (Run-time error)
  20296.  
  20297.  Rename across disks
  20298.  
  20299.    An attempt was made to rename a file with a new drive designation. This is
  20300.    not allowed. (Run-time prompt)
  20301.  
  20302.    ERR code: 74
  20303.  
  20304.  Requires DOS 2.10 or later
  20305.  
  20306.    You are attempting to use QuickBASIC with an incorrect version of DOS. (QB
  20307.    invocation or run-time error)
  20308.  
  20309.  RESUME without error
  20310.  
  20311.    A RESUME statement is encountered before an error-trapping routine is
  20312.    entered. (Run-time error)
  20313.  
  20314.    ERR code: 20
  20315.  
  20316.  RETURN without GOSUB
  20317.  
  20318.    A RETURN statement is encountered for which there is no previous,
  20319.    unmatched GOSUB statement. (Run-time error)
  20320.  
  20321.    ERR code: 3
  20322.  
  20323.  Right parenthesis missing
  20324.  
  20325.    QuickBASIC expects a right (closing) parenthesis. (Compile-time error)
  20326.  
  20327.  SEG or BYVAL not allowed in CALLS
  20328.  
  20329.    BYVAL and SEG are permitted only in a CALL statement. (Compile-time error)
  20330.  
  20331.  SELECT without END SELECT
  20332.  
  20333.    The end of a SELECT CASE statement is missing or misspelled. (Compile-time
  20334.    error)
  20335.  
  20336.  Semicolon missing
  20337.  
  20338.    QuickBASIC expects a semicolon. (Compile-time error)
  20339.  
  20340.  Separator illegal
  20341.  
  20342.    There is an illegal delimiting character in a PRINT USING or WRITE
  20343.    statement. Use a semicolon or a comma as a delimiter. (Compile-time error)
  20344.  
  20345.  Simple or array variable expected
  20346.  
  20347.    The compiler expects a variable argument. (Compile-time error)
  20348.  
  20349.  Skipping forward to END TYPE statement
  20350.  
  20351.    An error in the TYPE statement has caused QuickBASIC to ignore everything
  20352.    between the TYPE and END TYPE statement. (Compile-time error)
  20353.  
  20354.  Statement cannot occur within "CLUDE file
  20355.  
  20356.    SUB...END SUB and FUNCTION...END FUNCTION statement blocks are not
  20357.    permitted in include files. Use the Merge command from the File menu to
  20358.    insert the include file into the current module, or load the include file
  20359.    as a separate module. If you load the include file as a separate module,
  20360.    some restructuring may be necessary because shared variables are shared
  20361.    only within the scope of the module. (Compile-time error)
  20362.  
  20363.  Statement cannot precede SUB/FUNCTION definition
  20364.  
  20365.    The only statements allowed before a procedure definition are the
  20366.    statements REM and DEFtype. (Compile-time error)
  20367.  
  20368.  Statement ignored
  20369.  
  20370.    You are using the BC command to compile a program that contains TRON and
  20371.    TROFF statements without using the /D option. This error is not "fatal" ;
  20372.    the program will execute, although the results may be incorrect.
  20373.    (Compile-time warning)
  20374.  
  20375.  Statement illegal in TYPE block
  20376.  
  20377.    The only statements allowed between the TYPE and END TYPE statements are
  20378.    REM and element AS typename. (Compile-time error)
  20379.  
  20380.  Statement unrecognizable
  20381.  
  20382.    You have probably mistyped a BASIC statement. (Compile-time error)
  20383.  
  20384.  Statements/labels illegal between SELECT CASE and CASE
  20385.  
  20386.    Statements and line labels are not permitted between SELECT CASE and the
  20387.    first CASE statement. Comments and statement separators are permitted.
  20388.    (Compile-time error)
  20389.  
  20390.  STOP in module name at address segment:offset
  20391.  
  20392.    A STOP statement was encountered in the program. (Run-time error)
  20393.  
  20394.  String assignment required
  20395.  
  20396.    The string assignment is missing from an RSET statement. (Compile-time
  20397.    error)
  20398.  
  20399.  String constant required for ALIAS
  20400.  
  20401.    The DECLARE statement ALIAS keyword requires a string-constant argument.
  20402.    (Compile-time error)
  20403.  
  20404.  String expression required
  20405.  
  20406.    The statement requires a string-expression argument. (Compile-time error)
  20407.  
  20408.  String formula too complex
  20409.  
  20410.    Either a string formula is too long or an INPUT statement requests more
  20411.    than 15 string variables. Break the formula or INPUT statement into parts
  20412.    for correct execution. (Run-time error)
  20413.  
  20414.    ERR code: 16
  20415.  
  20416.  String space corrupt
  20417.  
  20418.    This error occurs when an invalid string in string space is being deleted
  20419.    during heap compaction. The probable causes of this error are as follows:
  20420.  
  20421.    ■ A string descriptor or string back pointer has been improperly modified.
  20422.      This may occur if you use an assembly-language subroutine to modify
  20423.      strings.
  20424.  
  20425.    ■ Out-of-range array subscripts are used and string space is inadvertently
  20426.      modified. The Produce Debug Code option can be used at compile time to
  20427.      check for array subscripts that exceed the array bounds.
  20428.  
  20429.    ■ Incorrect use of the POKE and/or DEF SEG statements may modify string
  20430.      space improperly.
  20431.  
  20432.    ■ Mismatched COMMON declarations may occur between two chained programs.
  20433.  
  20434.    (Run-time error)
  20435.  
  20436.  String variable required
  20437.  
  20438.    The statement requires a string-variable argument. (Compile-time error)
  20439.  
  20440.  SUB or FUNCTION missing
  20441.  
  20442.    A DECLARE statement has no corresponding procedure. (Compile-time error)
  20443.  
  20444.  SUB/FUNCTION without END SUB/FUNCTION
  20445.  
  20446.    The terminating statement is missing from a procedure. (Compile-time
  20447.    error)
  20448.  
  20449.  Subprogram error
  20450.  
  20451.    This is a SUB or FUNCTION definition error and is usually caused by one of
  20452.    the following:
  20453.  
  20454.    ■ The SUB or FUNCTION is already defined.
  20455.  
  20456.    ■ The program contains incorrectly nested FUNCTION or SUB statements.
  20457.  
  20458.    ■ The SUB or FUNCTION does not terminate with an END SUB or END FUNCTION
  20459.      statement.
  20460.  
  20461.    (Compile-time error)
  20462.  
  20463.  Subprogram not defined
  20464.  
  20465.    A subprogram is called but never defined. (Compile-time error)
  20466.  
  20467.  Subprograms not allowed in control statements
  20468.  
  20469.    Subprogram FUNCTION definitions are not permitted inside control
  20470.    constructs such as IF...THEN...ELSE and SELECT CASE. (Compile-time error)
  20471.  
  20472.  Subscript out of range
  20473.  
  20474.    An array element was referenced with a subscript that was outside the
  20475.    dimensions of the array, or an element of an undimensioned dynamic array
  20476.    was accessed. This message may be generated if the Debug (/D) option was
  20477.    specified at compile time. You may also get this error if the array size
  20478.    exceeds 64K, the array is not dynamic, and the /AH option was not used.
  20479.    Reduce the size of the array, or make the array dynamic and use the /AH
  20480.    command-line option. (Run-time error)
  20481.  
  20482.    ERR code: 9
  20483.  
  20484.  Subscript syntax illegal
  20485.  
  20486.    An array subscript contains a syntax error: for example, an array
  20487.    subscript contains both string and integer data types. (Compile-time
  20488.    error)
  20489.  
  20490.  Syntax error
  20491.  
  20492.    Several conditions can cause this error. The most common cause at compile
  20493.    time is a mistyped BASIC keyword or argument. At run-time, it is often
  20494.    caused by an improperly formatted DATA statement. (Compile-time or
  20495.    run-time error)
  20496.  
  20497.    ERR code: 2
  20498.  
  20499.  Syntax error in numeric constant
  20500.  
  20501.    A numeric constant is not properly formed. (Compile-time error)
  20502.  
  20503.  THEN missing
  20504.  
  20505.    QuickBASIC expects a THEN keyword. (Compile-time error)
  20506.  
  20507.  TO missing
  20508.  
  20509.    QuickBASIC expects a TO keyword. (Compile-time error)
  20510.  
  20511.  Too many arguments in function call
  20512.  
  20513.    Function calls are limited to 60 arguments. (Compile-time error)
  20514.  
  20515.  Too many dimensions
  20516.  
  20517.    Arrays are limited to 60 dimensions. (Compile-time error)
  20518.  
  20519.  Too many files
  20520.  
  20521.    At compile time, this error occurs when include files are nested more than
  20522.    five levels deep. It occurs at run time when the 255-file directory
  20523.    maximum is exceeded by an attempt to create a new file with a SAVE or OPEN
  20524.    statement. (Compile-time or run-time error)
  20525.  
  20526.    ERR code: 67
  20527.  
  20528.  Too many labels
  20529.  
  20530.    The number of lines in the line list following an ON...GOTOor ON...GOSUB
  20531.    statement exceeds 255 (Compile-time error) or 59 (Run-time error in
  20532.    compiled applications).
  20533.  
  20534.  Too many named COMMON blocks
  20535.  
  20536.    The maximum number of named COMMON blocks permitted is 126. (Compile-time
  20537.    error)
  20538.  
  20539.  Too many TYPE definitions
  20540.  
  20541.    The maximum number of user-defined types permitted is 240. (Compile-time
  20542.    error)
  20543.  
  20544.  Too many variables for INPUT
  20545.  
  20546.    An INPUT statement is limited to 60 variables. (Compile-time error)
  20547.  
  20548.  Too many variables for LINE INPUT
  20549.  
  20550.    Only one variable is allowed in a LINE INPUT statement. (Compile-time
  20551.    error)
  20552.  
  20553.  Type mismatch
  20554.  
  20555.    The variable is not of the required type. For example, you are trying to
  20556.    use the SWAP statement with a string variable and a numeric variable.
  20557.    (Compile-time or run-time error)
  20558.  
  20559.    ERR code: 13
  20560.  
  20561.  TYPE missing
  20562.  
  20563.    The TYPE keyword is missing from an END TYPE statement. (Compile-time
  20564.    error)
  20565.  
  20566.  Type more than 65535 bytes
  20567.  
  20568.    A user-defined type cannot exceed 64K. (Compile-time error)
  20569.  
  20570.  Type not defined
  20571.  
  20572.    The usertype argument to the TYPE statement is not defined. (Compile-time
  20573.    error)
  20574.  
  20575.  TYPE statement improperly nested
  20576.  
  20577.    User-defined type definitions are not allowed in procedures. (Compile-time
  20578.    error)
  20579.  
  20580.  TYPE without END TYPE
  20581.  
  20582.    There is no END TYPE statement associated with a TYPE statement.
  20583.    (Compile-time error)
  20584.  
  20585.  Typed variable not allowed in expression
  20586.  
  20587.    Variables that are user-defined types are not permitted in expressions
  20588.    such as CALL ALPHA((X)), where Xis a user-defined type. (Compile-time
  20589.    error)
  20590.  
  20591.  Unexpected end of file in TYPE declaration
  20592.  
  20593.    There is an end-of-file character inside a TYPE...END TYPE block.
  20594.  
  20595.  Unprintable error
  20596.  
  20597.    An error message is not available for the error condition that exists.
  20598.    This may be caused by an ERROR statement that doesn't have a defined error
  20599.    code. (Run-time error)
  20600.  
  20601.  Unrecognized switch error: "QU"
  20602.  
  20603.    You are attempting to create an .EXE file or Quick library with an
  20604.    incorrect version of the Microsoft Overlay Linker. You must use the linker
  20605.    supplied on the QuickBASIC distribution disks to create an .EXE file or
  20606.    Quick library. (Compile-time error)
  20607.  
  20608.  Valid options: [/RUN] file /AH /B /C:buf /G /NOHI /H /L [lib] /MBF /CMD
  20609.  string
  20610.  
  20611.    This message appears when you invoke QuickBASIC with an invalid option.
  20612.    (QB invocation error)
  20613.  
  20614.  Variable-length string required
  20615.  
  20616.    Only variable-length strings are permitted in a FIELD statement.
  20617.    (Compile-time error)
  20618.  
  20619.  Variable name not unique
  20620.  
  20621.    You are attempting to define the variable x as a user-defined type after
  20622.    x.y has been used. (Compile-time error)
  20623.  
  20624.  Variable required
  20625.  
  20626.    QuickBASIC encountered an INPUT, LET, READ, or SHARED statement without a
  20627.    variable argument. (Compile-time error)
  20628.  
  20629.  Variable required
  20630.  
  20631.    A GET or PUT statement didn't specify a variable when an operation is
  20632.    performed on a file opened in BINARY mode. (Run-time error)
  20633.  
  20634.    ERR code: 40
  20635.  
  20636.  WEND without WHILE
  20637.  
  20638.    This error is caused when a WEND statement has no corresponding WHILE
  20639.    statement. (Compile-time error)
  20640.  
  20641.  WHILE without WEND
  20642.  
  20643.    This error is caused when a WHILE statement has no corresponding WEND
  20644.    statement. (Compile-time error)
  20645.  
  20646.  Wrong number of dimensions
  20647.  
  20648.    An array reference contains the wrong number of dimensions. (Compile-time
  20649.    error)
  20650.  
  20651.  
  20652.  I.3  LINK Error Messages
  20653.  
  20654.    This section lists and describes error messages generated by the Microsoft
  20655.    Overlay Linker, LINK.
  20656.  
  20657.    Fatal errors cause the linker to stop execution. Fatal error messages have
  20658.    the following format:
  20659.  
  20660.    location : fatal error L1xxx:messagetext
  20661.  
  20662.    Nonfatal errors indicate problems in the executable file. LINK produces
  20663.    the executable file. Nonfatal error messages have the following format:
  20664.  
  20665.    location : error L2xxx: messagetext
  20666.  
  20667.    Warnings indicate possible problems in the executable file. LINK produces
  20668.    the executable file. Warnings have the following format:
  20669.  
  20670.    location : warning L4xxx: messagetext
  20671.  
  20672.    In these messages, location is the input file associated with the error,
  20673.    or LINK if there is no input file.
  20674.  
  20675.    The following error messages may appear when you link object files with
  20676.    LINK:
  20677.  
  20678. ╓┌─┌──────────────┌──────────────────────────────────────────────────────────╖
  20679.    Number         LINK Error Message
  20680.    ──────────────────────────────────────────────────────────────────────────
  20681.    L1001          option : option name ambiguous
  20682.  
  20683.                   A unique option name did not appear after the option
  20684.                   indicator (/). For example, the command
  20685.  
  20686.                   LINK /N main;
  20687.    Number         LINK Error Message
  20688.    ──────────────────────────────────────────────────────────────────────────
  20689.                  LINK /N main;
  20690.  
  20691.                   generates this error, since LINK cannot tell which of the
  20692.                   three options beginning with the letter "N" was intended.
  20693.  
  20694.    L1002          option : unrecognized option name
  20695.  
  20696.                   An unrecognized character followed the option indicator
  20697.                   (/), as in the following example:
  20698.  
  20699.                   LINK /ABCDEF main;
  20700.  
  20701.    L1003          /QUICKLIB, /EXEPACK incompatible
  20702.  
  20703.                   You specified two options that cannot be used together:
  20704.                   /QUICKLIB and /EXEPACK.
  20705.  
  20706.    L1004          option : invalid numeric value
  20707.  
  20708.    Number         LINK Error Message
  20709.    ──────────────────────────────────────────────────────────────────────────
  20710. 
  20711.                   An incorrect value appeared for one of the LINK options.
  20712.                   For example, a character string was given for an option
  20713.                   that requires a numeric value.
  20714.  
  20715.    L1006          option : stack size exceeds 65535 bytes
  20716.  
  20717.                   The value given as a parameter to the /STACKSIZE option
  20718.                   exceeds the maximum allowed.
  20719.  
  20720.    L1007          option : interrupt number exceeds 255
  20721.  
  20722.                   For the /OVERLAYINTERRUPT option, a number greater than 255
  20723.                   was given as a value.
  20724.  
  20725.    L1008          option : segment limit set too high
  20726.  
  20727.                   The limit on the number of segments allowed was set to
  20728.                   greater than 3072 using the /SEGMENTS option.
  20729.    Number         LINK Error Message
  20730.    ──────────────────────────────────────────────────────────────────────────
  20731.                  greater than 3072 using the /SEGMENTS option.
  20732.  
  20733.    L1009          number : CPARMAXALLOC : illegal value
  20734.  
  20735.                   The number specified in the /CPARMAXALLOC option was not in
  20736.                   the range 1-65,535.
  20737.  
  20738.    L1020          no object modules specified
  20739.  
  20740.                   No object-file names were specified to LINK.
  20741.  
  20742.    L1021          cannot nest response files
  20743.  
  20744.                   A response file occurred within a response file.
  20745.  
  20746.    L1022          response line too long
  20747.  
  20748.                   A line in a response file was longer than 127 characters.
  20749.  
  20750.    Number         LINK Error Message
  20751.    ──────────────────────────────────────────────────────────────────────────
  20752. 
  20753.    L1023          terminated by user
  20754.  
  20755.                   You entered CTRL+C or CRTL+BREAK
  20756.  
  20757.    L1024          nested right parentheses
  20758.  
  20759.                   The contents of an overlay were typed incorrectly on the
  20760.                   command line.
  20761.  
  20762.    L1025          nested left parentheses
  20763.  
  20764.                   The contents of an overlay were typed incorrectly on the
  20765.                   command line.
  20766.  
  20767.    L1026          unmatched right parenthesis
  20768.  
  20769.                   A right parenthesis was missing from the contents
  20770.                   specification of an overlay on the command line.
  20771.    Number         LINK Error Message
  20772.    ──────────────────────────────────────────────────────────────────────────
  20773.                  specification of an overlay on the command line.
  20774.  
  20775.    L1027          unmatched left parenthesis
  20776.  
  20777.                   A left parenthesis was missing from the contents
  20778.                   specification of an overlay on the command line.
  20779.  
  20780.    L1043          relocation table overflow
  20781.  
  20782.                   More than 32,768 long calls, long jumps, or other long
  20783.                   pointers appeared in the program.
  20784.  
  20785.                   Try replacing long references with short references, where
  20786.                   possible, and recreate the object module.
  20787.  
  20788.    L1045          too many TYPDEF records
  20789.  
  20790.                   An object module contained more than 255 TYPDEF records.
  20791.                   These records describe communal variables. This error can
  20792.    Number         LINK Error Message
  20793.    ──────────────────────────────────────────────────────────────────────────
  20794.                  These records describe communal variables. This error can
  20795.                   appear only with programs produced by the Microsoft FORTRAN
  20796.                   Compiler or other compilers that support communal
  20797.                   variables. (TYPDEF is a DOS term. It is explained in the
  20798.                   Microsoft MS-DOS Programmer's Reference and in other
  20799.                   reference books on DOS.)
  20800.  
  20801.    L1046          too many external symbols in one module
  20802.  
  20803.                   An object module specified more than the limit of 1023
  20804.                   external symbols.
  20805.  
  20806.                   Break the module into smaller parts.
  20807.  
  20808.    L1047          too many group, segment, and class names in one module
  20809.  
  20810.                   The program contained too many group, segment, and class
  20811.                   names.
  20812.  
  20813.    Number         LINK Error Message
  20814.    ──────────────────────────────────────────────────────────────────────────
  20815. 
  20816.                   Reduce the number of groups, segments, or classes, and
  20817.                   recreate the object file.
  20818.  
  20819.    L1048          too many segments in one module
  20820.  
  20821.                   An object module had more than 255 segments.
  20822.  
  20823.                   Split the module or combine segments
  20824.  
  20825.    L1049          too many segments
  20826.  
  20827.                   The program had more than the maximum number of segments.
  20828.                   Use the /SEGMENTS option, which has a default value of 128,
  20829.                   to specify the maximum legal number of segments. The
  20830.                   default is 128 in the /SEGMENTS option, which specifies the
  20831.                   maximum legal number.
  20832.  
  20833.                   Relink using the /SEGMENTS option with an appropriate
  20834.    Number         LINK Error Message
  20835.    ──────────────────────────────────────────────────────────────────────────
  20836.                  Relink using the /SEGMENTS option with an appropriate
  20837.                   number of segments.
  20838.  
  20839.    L1050          too many groups in one module
  20840.  
  20841.                   LINK encountered over 21 group definitions (GRPDEF) in a
  20842.                   single module.
  20843.  
  20844.                   Reduce the number of group definitions or split the module.
  20845.                   (Group definitions are explained in the Microsoft MS-DOS
  20846.                   Programmer's Reference and in other reference books on
  20847.                   DOS.)
  20848.  
  20849.    L1051          too many groups
  20850.  
  20851.                   The program defined more than 20 groups, not counting
  20852.                   DGROUP.
  20853.  
  20854.                   Reduce the number of groups.
  20855.    Number         LINK Error Message
  20856.    ──────────────────────────────────────────────────────────────────────────
  20857.                  Reduce the number of groups.
  20858.  
  20859.    L1052          too many libraries
  20860.  
  20861.                   An attempt was made to link with more than 32 libraries.
  20862.  
  20863.                   Combine libraries, or use modules that require fewer
  20864.                   libraries.
  20865.  
  20866.    L1053          out of memory for symbol table
  20867.  
  20868.                   There is no fixed limit to the size of the symbol table.
  20869.                   However, it is limited by the amount of available memory.
  20870.  
  20871.                   Combine modules or segments and recreate the object files.
  20872.                   Eliminate as many public symbols as possible.
  20873.  
  20874.    L1054          requested segment limit too high
  20875.  
  20876.    Number         LINK Error Message
  20877.    ──────────────────────────────────────────────────────────────────────────
  20878. 
  20879.                   LINK did not have enough memory to allocate tables
  20880.                   describing the number of segments requested. (The default
  20881.                   is 128 or the value specified with the /SEGMENTS option.)
  20882.  
  20883.                   Try linking again using the /SEGMENTS option to select a
  20884.                   smaller number of segments (for example, use 64 if the
  20885.                   default was used previously), or free some memory by
  20886.                   eliminating resident programs or shells.
  20887.  
  20888.    L1056          too many overlays
  20889.  
  20890.                   The program defined more than 63 overlays.
  20891.  
  20892.    L1057          data record too large
  20893.  
  20894.                   A LEDATA record (in an object module) contained more than
  20895.                   1024 bytes of data. This is a translator error. (LEDATA is
  20896.                   a DOS term, which is explained in the Microsoft MS-DOS
  20897.    Number         LINK Error Message
  20898.    ──────────────────────────────────────────────────────────────────────────
  20899.                  a DOS term, which is explained in the Microsoft MS-DOS
  20900.                   Programmer's Reference and in other DOS reference books.)
  20901.  
  20902.                   Note which translator (compiler or assembler) produced the
  20903.                   incorrect object module and the circumstances. Please
  20904.                   report this error to Microsoft Corporation using the
  20905.                   Product Assistance Request form included with the
  20906.                   documentation.
  20907.  
  20908.    L1063          out of memory for CodeView information
  20909.  
  20910.                   Too many linked object (".OBJ") files contain debugging
  20911.                   information. Turn off the Produce Debug Code option in the
  20912.                   Make EXE file dialog box.
  20913.  
  20914.    L1070          segment size exceeds 64K
  20915.  
  20916.                   A single segment contained more than 64K of code or data.
  20917.  
  20918.    Number         LINK Error Message
  20919.    ──────────────────────────────────────────────────────────────────────────
  20920. 
  20921.                   Try compiling and linking using the large model.
  20922.  
  20923.    L1071          segment _TEXT larger than 65520 bytes
  20924.  
  20925.                   This error is likely to occur only in small-model C
  20926.                   programs, but it can occur when any program with a segment
  20927.                   named _TEXT is linked using the /DOSSEG option. Small-model
  20928.                   C programs must reserve code addresses 0 and 1; this range
  20929.                   is increased to 16 for alignment purposes.
  20930.  
  20931.    L1072          common area longer than 65536 bytes
  20932.  
  20933.                   The program had more than 64K of communal variables. This
  20934.                   error occurs only with programs produced by compilers that
  20935.                   support communal variables.
  20936.  
  20937.    L1080          cannot open list file
  20938.  
  20939.    Number         LINK Error Message
  20940.    ──────────────────────────────────────────────────────────────────────────
  20941. 
  20942.                   The disk or the root directory was full.
  20943.  
  20944.                   Delete or move files to make space.
  20945.  
  20946.    L1081          out of space for run file
  20947.  
  20948.                   The disk on which the executable file was being written was
  20949.                   full.
  20950.  
  20951.                   Free more space on the disk and restart LINK.
  20952.  
  20953.    L1083          cannot open run file
  20954.  
  20955.                   The disk or the root directory was full.
  20956.  
  20957.                   Delete or move files to make space.
  20958.  
  20959.    L1084          cannot create temporary file
  20960.    Number         LINK Error Message
  20961.    ──────────────────────────────────────────────────────────────────────────
  20962.   L1084          cannot create temporary file
  20963.  
  20964.                   The disk or root directory was full.
  20965.  
  20966.                   Free more space in the directory and restart LINK.
  20967.  
  20968.    L1085          cannot open temporary file
  20969.  
  20970.                   The disk or the root directory was full.
  20971.  
  20972.                   Delete or move files to make space.
  20973.  
  20974.    L1086          scratch file missing
  20975.  
  20976.                   An internal error has occurred.
  20977.  
  20978.                   Note the circumstances of the problem and contact Microsoft
  20979.                   Corporation using the Product Assistance Request form
  20980.                   included with the documentation.
  20981.    Number         LINK Error Message
  20982.    ──────────────────────────────────────────────────────────────────────────
  20983.                  included with the documentation.
  20984.  
  20985.    L1087          unexpected end-of-file on scratch file
  20986.  
  20987.                   The disk with the temporary output file from LINK was
  20988.                   removed.
  20989.  
  20990.    L1088          out of space for list file
  20991.  
  20992.                   The disk where the listing file is being written is full.
  20993.  
  20994.                   Free more space on the disk and restart LINK.
  20995.  
  20996.    L1089          filename : cannot open response file
  20997.  
  20998.                   LINK could not find the specified response file.
  20999.  
  21000.                   This usually indicates a typing error.
  21001.  
  21002.    Number         LINK Error Message
  21003.    ──────────────────────────────────────────────────────────────────────────
  21004. 
  21005.    L1090          cannot reopen list file
  21006.  
  21007.                   The original disk was not replaced at the prompt.
  21008.  
  21009.                   Restart LINK.
  21010.  
  21011.    L1091          unexpected end-of-file on library
  21012.  
  21013.                   The disk containing the library probably was removed.
  21014.  
  21015.                   Replace the disk containing the library and run LINK again.
  21016.  
  21017.    L1093          object not found
  21018.  
  21019.                   One of the object files specified in the input to LINK was
  21020.                   not found.
  21021.  
  21022.                   Restart LINK and specify the object file.
  21023.    Number         LINK Error Message
  21024.    ──────────────────────────────────────────────────────────────────────────
  21025.                  Restart LINK and specify the object file.
  21026.  
  21027.    L1101          invalid object module
  21028.  
  21029.                   One of the object modules was invalid.
  21030.  
  21031.                   If the error persists after recompiling, please contact
  21032.                   Microsoft Corporation using the Product Assistance Request
  21033.                   form included with the documentation.
  21034.  
  21035.    L1102          unexpected end-of-file
  21036.  
  21037.                   An invalid format for a library was encountered.
  21038.  
  21039.    L1103          attempt to access data outside segment bounds
  21040.  
  21041.                   A data record in an object module specified data extending
  21042.                   beyond the end of a segment. This is a translator error.
  21043.  
  21044.    Number         LINK Error Message
  21045.    ──────────────────────────────────────────────────────────────────────────
  21046. 
  21047.                   Note which translator (compiler or assembler) produced the
  21048.                   incorrect object module and the circumstances in which it
  21049.                   was produced. Please report this error to Microsoft
  21050.                   Corporation using the Product Assistance Request form
  21051.                   included with the documentation.
  21052.  
  21053.    L1104          filename : not valid library
  21054.  
  21055.                   The specified file was not a valid library file. This error
  21056.                   causes LINK to abort.
  21057.  
  21058.    L1113          unresolved COMDEF; internal error
  21059.  
  21060.                   Note the circumstances of the failure and contact Microsoft
  21061.                   Corporation using the Product Assistance Request form
  21062.                   included with the documentation.
  21063.  
  21064.    L1114          file not suitable for /EXEPACK; relink without
  21065.    Number         LINK Error Message
  21066.    ──────────────────────────────────────────────────────────────────────────
  21067.   L1114          file not suitable for /EXEPACK; relink without
  21068.  
  21069.                   For the linked program, the size of the packed load image
  21070.                   plus packing overhead was larger than that of the unpacked
  21071.                   load image.
  21072.  
  21073.                   Relink without the /EXEPACK option.
  21074.  
  21075.    L1115          /QUICKLIB, overlays incompatible
  21076.  
  21077.                   You specified overlays and used the /QUICKLIB option. These
  21078.                   cannot be used together.
  21079.  
  21080.    L2001          fixup(s) without data
  21081.  
  21082.                   A FIXUPP record occurred without a data record immediately
  21083.                   preceding it. This is probably a compiler error. (See the
  21084.                   Microsoft MS-DOS Programmer's Reference for more
  21085.                   information on FIXUPP.)
  21086.    Number         LINK Error Message
  21087.    ──────────────────────────────────────────────────────────────────────────
  21088.                  information on FIXUPP.)
  21089.  
  21090.    L2002          fixup overflow near number in frame seg segname target seg
  21091.                   segname target offset number
  21092.  
  21093.                   The following conditions can cause this error:
  21094.  
  21095.                   ■ A group is larger than 64K.
  21096.  
  21097.                   ■ The program contains an intersegment short jump or
  21098.                   intersegment short call.
  21099.  
  21100.                   ■ The name of a data item in the program conflicts with the
  21101.                   name of a library subroutine included in the link.
  21102.  
  21103.                   ■ An EXTRN declaration in an assembly-language source file
  21104.                   appeared inside the body of a segment, as in the following
  21105.                   example:
  21106.  
  21107.    Number         LINK Error Message
  21108.    ──────────────────────────────────────────────────────────────────────────
  21109. 
  21110.                   code   SEGMENT public 'CODE'
  21111.                          EXTRN   main:far
  21112.                   start  PROC    far
  21113.                          call    main
  21114.                          ret
  21115.                   start  ENDP
  21116.                   code   ENDS
  21117.  
  21118.                   The following construction is preferred:
  21119.  
  21120.                   EXTRN   main:far
  21121.                   code   SEGMENT public 'CODE'
  21122.                   start  PROC    far
  21123.                          call    main
  21124.                          ret
  21125.                   start  ENDP
  21126.                   code   ENDS
  21127.  
  21128.    Number         LINK Error Message
  21129.    ──────────────────────────────────────────────────────────────────────────
  21130. 
  21131.                   Revise the source file and recreate the object file. (See
  21132.                   the Microsoft MS-DOS Programmer's Reference for information
  21133.                   about frame and target segments.
  21134.  
  21135.    L2003          intersegment self-relative fixup at offset in segment
  21136.                   segname
  21137.  
  21138.                   You tried to make a near call or jump to a far entry in
  21139.                   segment segname at offset.
  21140.  
  21141.                   Change the call or jump to far or make the entry near.
  21142.  
  21143.    L2004          LOBYTE-type fixup overflow
  21144.  
  21145.                   A LOBYTE fixup generated an address overflow. (See the
  21146.                   Microsoft MS-DOS Programmer's Reference for more
  21147.                   information.)
  21148.  
  21149.    Number         LINK Error Message
  21150.    ──────────────────────────────────────────────────────────────────────────
  21151. 
  21152.    L2005          fixup type unsupported
  21153.  
  21154.                   A fixup type occurred that is not supported by the
  21155.                   Microsoft linker. This is probably a compiler error.
  21156.  
  21157.                   Note the circumstances of the failure and contact Microsoft
  21158.                   Corporation using the Product Assistance Request form
  21159.                   included with the documentation.
  21160.  
  21161.    L2011          name : NEAR/HUGE conflict
  21162.  
  21163.                   Conflicting NEAR and HUGE attributes were given for a
  21164.                   communal variable. This error can occur only with programs
  21165.                   produced by compilers that support communal variables.
  21166.  
  21167.    L2012          name : array-element size mismatch
  21168.  
  21169.                   A far communal array was declared with two or more
  21170.    Number         LINK Error Message
  21171.    ──────────────────────────────────────────────────────────────────────────
  21172.                  A far communal array was declared with two or more
  21173.                   different array-element sizes (for instance, an array was
  21174.                   declared once as an array of characters and once as an
  21175.                   array of real numbers). This error occurs only with
  21176.                   compilers that support far communal arrays.
  21177.  
  21178.    L2013          LIDATA record too large
  21179.  
  21180.                   A LIDATA record contains more than 512 bytes. This error is
  21181.                   usually caused by a compiler error.
  21182.  
  21183.    L2024          name : symbol already defined
  21184.  
  21185.                   LINK has found a public-symbol redefinition. Remove extra
  21186.                   definition(s).
  21187.  
  21188.    L2025          name : symbol defined more than once
  21189.  
  21190.                   Remove the extra symbol definition from the object file.
  21191.    Number         LINK Error Message
  21192.    ──────────────────────────────────────────────────────────────────────────
  21193.                  Remove the extra symbol definition from the object file.
  21194.  
  21195.    L2029          unresolved externals
  21196.  
  21197.                   One or more symbols were declared to be external in one or
  21198.                   more modules, but they were not publicly defined in any of
  21199.                   the modules or libraries. A list of the unresolved external
  21200.                   references appears after the message, as shown in the
  21201.                   following example:
  21202.  
  21203.                   unresolved externals
  21204.                   EXIT in file(s):
  21205.                    MAIN.OBJ (main.for)
  21206.                   OPEN in file(s):
  21207.                    MAIN.OBJ (main.for)
  21208.  
  21209.                   The name that comes before in file(s) is the unresolved
  21210.                   external symbol. On the next line is a list of object
  21211.                   modules that have made references to this symbol. This
  21212.    Number         LINK Error Message
  21213.    ──────────────────────────────────────────────────────────────────────────
  21214.                  modules that have made references to this symbol. This
  21215.                   message and the list are also written to the map file, if
  21216.                   one exists.
  21217.  
  21218.    L2041          stack plus data exceed 64K
  21219.  
  21220.                   The total size of near data and the stack exceeds 64K.
  21221.                   Reduce the stack size to control the error.
  21222.  
  21223.                   LINK tests for this condition only if the /DOSSEG option is
  21224.                   enabled. This option is automatically enabled by the
  21225.                   library startup module.
  21226.  
  21227.    L2043          Quick library support module missing
  21228.  
  21229.                   You did not specify, or LINK could not find, the object
  21230.                   module or library required for creating a Quick library. In
  21231.                   the case of QuickBASIC, the library provided is BQLB45.LIB.
  21232.  
  21233.    Number         LINK Error Message
  21234.    ──────────────────────────────────────────────────────────────────────────
  21235. 
  21236.    L2044          name : symbol multiply defined, use /NOE
  21237.  
  21238.                   LINK has found a possible public-symbol redefinition. This
  21239.                   error is often caused by redefining a symbol defined in a
  21240.                   library.
  21241.  
  21242.                   Relink using the /NOEXTDICTIONARY option.
  21243.  
  21244.                   This error in combination with error L2025 for the same
  21245.                   symbol indicates a real redefinition error.
  21246.  
  21247.    L4011          PACKCODE value exceeding 65500 unreliable
  21248.  
  21249.                   Packcode segment sizes that exceed 65,500 bytes may be
  21250.                   unreliable on the Intel(R) 80286 processor.
  21251.  
  21252.    L4012          load-high disables EXEPACK
  21253.  
  21254.    Number         LINK Error Message
  21255.    ──────────────────────────────────────────────────────────────────────────
  21256. 
  21257.                   The /HIGH and /EXEPACK options cannot be used at the same
  21258.                   time.
  21259.  
  21260.    L4015          /CODEVIEW disables /DSALLOCATE
  21261.  
  21262.                   The /CODEVIEW and /DSALLOCATE options cannot be used at the
  21263.                   same time.
  21264.  
  21265.    L4016          /CODEVIEW disables /EXEPACK
  21266.  
  21267.                   The /CODEVIEW and /EXEPACK options cannot be used at the
  21268.                   same time.
  21269.  
  21270.    L4020          name : code-segment size exceeds 65500
  21271.  
  21272.                   Code segments of 65,501-65,536 bytes in length may be
  21273.                   unreliable on the Intel 80286 processor.
  21274.  
  21275.    Number         LINK Error Message
  21276.    ──────────────────────────────────────────────────────────────────────────
  21277. 
  21278.    L4021          no stack segment
  21279.  
  21280.                   The program did not contain a stack segment defined with
  21281.                   STACK combine type. This message should not appear for
  21282.                   modules compiled with Microsoft QuickBASIC, but it could
  21283.                   appear for an assembly-language module.
  21284.  
  21285.                   Normally, every program should have a stack segment with
  21286.                   the combine type specified as STACK. You can ignore this
  21287.                   message if you have a specific reason for not defining a
  21288.                   stack or for defining one without the STACK combine type.
  21289.                   Linking with versions of LINK earlier than Version 2.40
  21290.                   might cause this message, since these linkers search
  21291.                   libraries only once.
  21292.  
  21293.    L4031          name : segment declared in more than one group
  21294.  
  21295.                   A segment was declared to be a member of two different
  21296.    Number         LINK Error Message
  21297.    ──────────────────────────────────────────────────────────────────────────
  21298.                  A segment was declared to be a member of two different
  21299.                   groups.
  21300.  
  21301.                   Correct the source file and recreate the object files.
  21302.  
  21303.    L4034          more than 239 overlay segments; extra put in root
  21304.  
  21305.                   The program designates more than 239 segments to go in
  21306.                   overlays. When this error occurs, segments beginning with
  21307.                   number 234 are placed in the root, the permanently resident
  21308.                   portion.
  21309.  
  21310.    L4045          name of output file is name
  21311.  
  21312.                   The prompt for the run-file field gave an inaccurate
  21313.                   default because the /QUICKLIB option was not used early
  21314.                   enough. The output will be a Quick library with the name
  21315.                   given in the error message.
  21316.  
  21317.    Number         LINK Error Message
  21318.    ──────────────────────────────────────────────────────────────────────────
  21319. 
  21320.    L4050          too many public symbols for sorting
  21321.  
  21322.                   The number of public symbols exceeds the space available
  21323.                   for sorting the symbols as requested by the /MAP option.
  21324.                   The symbols are left unsorted.
  21325.  
  21326.    L4051          filename : cannot find library
  21327.  
  21328.                   LINK could not find the specified file.
  21329.  
  21330.                   Enter a new file name, a new path specification, or both.
  21331.  
  21332.    L4053          VM.TMP : illegal file name; ignored
  21333.  
  21334.                   VM.TMP appeared as an object-file name. Rename the file and
  21335.                   rerun LINK.
  21336.  
  21337.    L4054          filename : cannot find file
  21338.    Number         LINK Error Message
  21339.    ──────────────────────────────────────────────────────────────────────────
  21340.   L4054          filename : cannot find file
  21341.  
  21342.                   LINK could not find the specified file. Enter a new file
  21343.                   name, a new path specification, or both.
  21344.    ──────────────────────────────────────────────────────────────────────────
  21345.  
  21346.  
  21347.  
  21348.  I.4  LIB Error Messages
  21349.  
  21350.    Error messages generated by the Microsoft Library Manager, LIB, have one
  21351.    of the following formats:
  21352.  
  21353.    {filename| LIB} : fatal error U1xxx: messagetext
  21354.    {filename| LIB} : error U2xxx: messagetext
  21355.    {filename| LIB} : warning U4xxx: messagetext
  21356.  
  21357.    The message begins with the input-file name (filename), if one exists, or
  21358.    with the name of the utility. If possible, LIB prints a warning and
  21359.    continues operation. In some cases errors are fatal, and LIB terminates
  21360.    processing.
  21361.  
  21362.    LIB may display the following error messages:
  21363.  
  21364.  
  21365.    Number                   LIB Error Message
  21366.    ──────────────────────────────────────────────────────────────────────────
  21367.    U1150                    page size too small
  21368.  
  21369.                             The page size of an input library was too small,
  21370.                             which indicates an invalid input .LIB file.
  21371.  
  21372.    U1151                    syntax error : illegal file specification
  21373.  
  21374.                             A command operator such as a minus sign (-) was
  21375.                             given without a following module name.
  21376.  
  21377.    U1152                    syntax error : option name missing
  21378.  
  21379.                             A forward slash (/) was given without an option
  21380.                             after it.
  21381.  
  21382.    U1153                    syntax error : option value missing
  21383.  
  21384.                             The /PAGESIZE option was given without a value
  21385.                             following it.
  21386.  
  21387.    U1154                    option unknown
  21388.  
  21389.                             An unknown option was given. Currently, LIB
  21390.                             recognizes only the /PAGESIZE option.
  21391.  
  21392.    U1155                    syntax error : illegal input
  21393.  
  21394.                             The given command did not follow correct LIB
  21395.                             syntax as specified in Appendix G, "Compiling
  21396.                             and Linking from DOS."
  21397.  
  21398.    U1156                    syntax error
  21399.  
  21400.                             The given command did not follow correct LIB
  21401.                             syntax as specified in Appendix G, "Compiling
  21402.                             and Linking from DOS."
  21403.  
  21404.    U1157                    comma or new line missing
  21405.  
  21406.                             A comma or carriage return was expected in the
  21407.                             command line but did not appear. This may
  21408.                             indicate an inappropriately placed comma, as in
  21409.                             the line that follows:
  21410.  
  21411.                             LIB math.lib,-mod1+mod2;
  21412.  
  21413.                             The line should have been entered as follows:
  21414.  
  21415.                             LIB math.lib -mod1+mod2;
  21416.  
  21417.    U1158                    terminator missing
  21418.  
  21419.                             Either the response to the "Output library"
  21420.                             prompt or the last line of the response file used
  21421.                             to start LIB did not end with a carriage return.
  21422.  
  21423.    U1161                    cannot rename old library
  21424.  
  21425.                             LIB could not rename the old library to have a
  21426.                             .BAK extension because the .BAK version already
  21427.                             existed with read-only protection.
  21428.  
  21429.                             Change the protection on the old .BAK version.
  21430.  
  21431.    U1162                    cannot reopen library
  21432.  
  21433.                             The old library could not be reopened after it
  21434.                             was renamed to have a .BAK extension.
  21435.  
  21436.    U1163                    error writing to cross-reference file
  21437.  
  21438.                             The disk or root directory was full.
  21439.  
  21440.                             Delete or move files to make space.
  21441.  
  21442.    U1170                    too many symbols
  21443.  
  21444.                             More than 4609 symbols appeared in the library
  21445.                             file.
  21446.  
  21447.    U1171                    insufficient memory
  21448.  
  21449.                             LIB did not have enough memory to run.
  21450.  
  21451.                             Remove any shells or resident programs and try
  21452.                             again, or add more memory.
  21453.  
  21454.    U1172                    no more virtual memory
  21455.  
  21456.                             Note the circumstances of the failure and notify
  21457.                             Microsoft Corporation using the Product Assistant
  21458.                             Request form included with the documentation.
  21459.  
  21460.    U1173                    internal failure
  21461.  
  21462.                             Note the circumstances of the failure and notify
  21463.                             Microsoft Corporation using the Product Assistant
  21464.                             Request form included with the documentation.
  21465.  
  21466.    U1174                    mark: not allocated
  21467.  
  21468.                             Note the circumstances of the failure and notify
  21469.                             Microsoft Corporation using the Product
  21470.                             Assistance Request form included with the
  21471.                             documentation.
  21472.  
  21473.    U1175                    free: not allocated
  21474.  
  21475.                             Note the circumstances of the failure and notify
  21476.                             Microsoft Corporation using the Product
  21477.                             Assistance Request form included with the
  21478.                             documentation.
  21479.  
  21480.    U1180                    write to extract file failed
  21481.  
  21482.                             The disk or root directory was full.
  21483.  
  21484.                             Delete or move files to make space.
  21485.  
  21486.    U1181                    write to library file failed
  21487.  
  21488.                             The disk or root directory was full.
  21489.  
  21490.                             Delete or move files to make space.
  21491.  
  21492.    U1182                    filename : cannot create extract file
  21493.  
  21494.                             The disk or root directory was full, or the
  21495.                             specified extract file already existed with
  21496.                             read-only protection.
  21497.  
  21498.                             Make space on the disk or change the protection
  21499.                             of the extract file.
  21500.  
  21501.    U1183                    cannot open response file
  21502.  
  21503.                             The response file was not found.
  21504.  
  21505.    U1184                    unexpected end-of-file on command input
  21506.  
  21507.                             An end-of-file character was received prematurely
  21508.                             in response to a prompt.
  21509.  
  21510.    U1185                    cannot create new library
  21511.  
  21512.                             The disk or root directory was full, or the
  21513.                             library file already existed with read-only
  21514.                             protection.
  21515.  
  21516.                             Make space on the disk or change the protection
  21517.                             of the library file.
  21518.  
  21519.    U1186                    error writing to new library
  21520.  
  21521.                             The disk or root directory was full.
  21522.  
  21523.                             Delete or move files to make space.
  21524.  
  21525.    U1187                    cannot open VM.TMP
  21526.  
  21527.                             The disk or root directory was full.
  21528.  
  21529.                             Delete or move files to make space.
  21530.  
  21531.    U1188                    cannot write to VM
  21532.  
  21533.                             Note the circumstances of the failure and notify
  21534.                             Microsoft Corporation using the Product
  21535.                             Assistance Request form.
  21536.  
  21537.    U1189                    cannot read from VM
  21538.  
  21539.                             Note the circumstances of the failure and notify
  21540.                             Microsoft Corporation using the Product
  21541.                             Assistance Request form.
  21542.  
  21543.    U1190                    interrupted by user
  21544.  
  21545.                             The user pressed CTRL+C or CTRL+BREAK.
  21546.  
  21547.    U1200                    name : invalid library header
  21548.  
  21549.                             The input library file had an invalid format. It
  21550.                             was either not a library file, or it had been
  21551.                             corrupted.
  21552.  
  21553.    U1203                    name : invalid object module near location
  21554.  
  21555.                             The module specified by name was not a valid
  21556.                             object module.
  21557.  
  21558.    U2152                    filename : cannot create listing
  21559.  
  21560.                             The directory or disk was full, or the
  21561.                             cross-reference-listing file already existed with
  21562.                             read-only protection.
  21563.  
  21564.                             Either make space on the disk or change the
  21565.                             protection of the cross-reference-listing file.
  21566.  
  21567.    U2155                    modulename : module not in library; ignored
  21568.  
  21569.                             The specified module was not found in the input
  21570.                             library.
  21571.  
  21572.    U2157                    filename : cannot access file
  21573.  
  21574.                             LIB was unable to open the specified file.
  21575.  
  21576.    U2158                    libraryname : invalid library header; file
  21577.                             ignored
  21578.  
  21579.                             The input library had an incorrect format.
  21580.  
  21581.    U2159                    filename : invalid format hexnumber; file ignored
  21582.  
  21583.                             The signature byte or word hexnumber of the given
  21584.                             file was not one of the following recognized
  21585.                             types: Microsoft library, Intel library,
  21586.                             Microsoft object, or XENIX(R) archive.
  21587.  
  21588.    U4150                    modulename : module redefinition ignored
  21589.  
  21590.                             A module was specified to be added to a library
  21591.                             but a module with the same name was already in
  21592.                             the library. Or, a module with the same name was
  21593.                             found more than once in the library.
  21594.  
  21595.    U4151                    symbol : symbol redefined in module modulename,
  21596.                             redefinition ignored
  21597.  
  21598.                             The specified symbol was defined in more than one
  21599.                             module.
  21600.  
  21601.    U4153                    number : page size too small; ignored
  21602.  
  21603.                             The value specified in the /PAGESIZE option was
  21604.                             less than 16.
  21605.  
  21606.    U4155                    modulename: module not in library
  21607.  
  21608.                             A module to be replaced is not in the library.
  21609.                             LIB adds the module to the library.
  21610.  
  21611.    U4156                    libraryname : output-library specification
  21612.                             ignored
  21613.  
  21614.                             An output library was specified in addition to a
  21615.                             new library name. For example, specifying
  21616.  
  21617.                             LIB new.lib+one.obj,new.lst,new.lib
  21618.  
  21619.                             where new.lib does not already exist causes this
  21620.                             error.
  21621.  
  21622.    U4157                    Insufficient memory, extended dictionary not
  21623.                             created.
  21624.  
  21625.                             LIB was unable to create the extended dictionary.
  21626.                             The library is still valid, but LINK cannot take
  21627.                             advantage of extended dictionaries to link
  21628.                             faster.
  21629.  
  21630.    U4158                    Internal error, extended dictionary not created.
  21631.  
  21632.                             LIB was unable to create the extended dictionary.
  21633.                             The library is still valid, but LINK cannot take
  21634.                             advantage of extended dictionaries to link
  21635.                             faster.
  21636.  
  21637.  
  21638.  
  21639.  ────────────────────────────────────────────────────────────────────────────
  21640.  Index
  21641.  
  21642.  
  21643.  Symbols
  21644.  
  21645.  #
  21646.  (+)
  21647.    operator, combining strings
  21648.  '
  21649.  *
  21650.  * (asterisk)
  21651.    AS,
  21652.    LIB command symbol
  21653.  , (comma)
  21654.    fields, ending
  21655.    variable separator
  21656.  $ (dollar sign), string-type suffix
  21657.  " (double quotes), ending
  21658.  / (forward slash), LINK option character
  21659.  (/), LINK option character
  21660.  - (minus sign)
  21661.  - (minus sign), LIB command symbol
  21662.  -* (minus sign-asterisk, LIB
  21663.  -+ (minus sign-plus sign), LIB command symbol
  21664.  "" (null string)
  21665.  + (plus)
  21666.    operator, combining strings
  21667.    sign, LIB command
  21668.  ; (semicolon)
  21669.    LIB
  21670.  ; (semicolon),
  21671.  ; (semicolon), LIB command symbol
  21672.  # USING
  21673.  
  21674.  A
  21675.  
  21676.  ,A option
  21677.    BASICA
  21678.    #INCLUDE files
  21679.  /A option (BC)
  21680.  ABS function
  21681.  ABSOLUTE
  21682.  Absolute
  21683.  ABSOLUTE statement
  21684.  access, contrasted with
  21685.  after input
  21686.  /AH option
  21687.  ALIAS, DECLARE
  21688.  aliasing
  21689.  Aliasing, variable
  21690.  all in a module
  21691.  allowable
  21692.  allowed
  21693.  Alphabetizing
  21694.  alternative
  21695.  among versions
  21696.  AND
  21697.    operator
  21698.  and functions. See individual statement and function names
  21699.    FIELD
  21700.    GET
  21701.    INPUT #
  21702.    PUT
  21703.    WRITE #
  21704.  and GW-BASIC
  21705.  AND option
  21706.    PUT
  21707.  and replacing
  21708.  Angle measurements
  21709.  Animate mode
  21710.  Animation
  21711.    GET and PUT
  21712.    graphics statements, simple
  21713.    image flicker,
  21714.    PALETTE USING
  21715.    screen pages
  21716.  Apostrophe (')
  21717.    entering
  21718.    introducing comments
  21719.  (apostrophe), introducing comments
  21720.  Arc
  21721.  Arctangent,
  21722.  Arguments
  21723.    correct type and number, checking for
  21724.    LINK options
  21725.    parameters
  21726.      agreement
  21727.      distinguished from
  21728.    passing
  21729.      by
  21730.      by value
  21731.      described
  21732.      limits on
  21733.    SUB procedures,
  21734.  arguments by reference
  21735.  Array-bound
  21736.  Array-bound functions
  21737.  Arrays
  21738.    dynamic
  21739.      ERASE
  21740.      REDIM statement
  21741.    elements, passing
  21742.    format
  21743.      argument list
  21744.      FUNCTION statement
  21745.      parameter
  21746.      parameter list
  21747.      SHARED statement
  21748.      SUB statement
  21749.    LBOUND function
  21750.    limits (table)
  21751.    lower-bound function
  21752.    memory allocation
  21753.    procedures
  21754.      passing
  21755.      passing to
  21756.      sharing
  21757.    row-order option
  21758.    static, ERASE statement
  21759.    subscripts,
  21760.    subscripts, specifying
  21761.      lower
  21762.    UBOUND (upper-bound) function
  21763.    variables
  21764.  arrays
  21765.    limits
  21766.  Arrow keys. See DIRECTION keys
  21767.  ASC function
  21768.  ASCII
  21769.    character
  21770.    character codes
  21771.      CHR$
  21772.      determining
  21773.      (table)
  21774.    files, reading as sequential
  21775.  Aspect ratio
  21776.    CIRCLE
  21777.    correction for
  21778.    defined
  21779.    screen size, computing for
  21780.    squares,
  21781.  Assembly-language listings
  21782.  Assignment statements
  21783.  (asterisk)
  21784.    AS, fixed-length string with
  21785.  Asterisk (*)
  21786.    fixed-length
  21787.  Asterisk (*)
  21788.  ATN function
  21789.  attribute
  21790.    described
  21791.    DIM
  21792.      described
  21793.      sharing
  21794.    REDIM
  21795.    variables, making global
  21796.  Attributes
  21797.    colors, assigning
  21798.    screen
  21799.    screen modes, EGA and VGA
  21800.    STATIC
  21801.  attributes. See Attributes
  21802.  automatic
  21803.  Automatic
  21804.  Automatic variables
  21805.  AUX (device name)
  21806.  
  21807.  B
  21808.  
  21809.  Background color default
  21810.  Background music
  21811.  .BAS file, execution by QuickBASIC
  21812.  BASIC
  21813.    error codes
  21814.    reserved words
  21815.    run-time errors
  21816.  BASIC, compatibility
  21817.  BASICA
  21818.    compatibility
  21819.    QuickBASIC, converting to
  21820.  /BATCH option (LINK)
  21821.  Batch file, when to use
  21822.  Baud rate
  21823.  BC command
  21824.    options
  21825.      /V
  21826.  BC
  21827.  BC command
  21828.    command line, invoking from
  21829.    file-name usage
  21830.    options
  21831.      /A
  21832.      /AH
  21833.      /C
  21834.      /D
  21835.      /E
  21836.      (list)
  21837.      /MBF
  21838.      new (table)
  21839.      not used (table)
  21840.      /O
  21841.      /R
  21842.      /S
  21843.      /V
  21844.      /W
  21845.      /X
  21846.      /ZD
  21847.      /ZI
  21848.    versions, differences among
  21849.  BC.EXE
  21850.  BEEP statement
  21851.  Binary
  21852.    file access
  21853.      OPEN statement syntax
  21854.      random
  21855.      versions, differences among
  21856.    input
  21857.    numbers, converting to hexadecimal
  21858.  Binary, differences from
  21859.  Binary format
  21860.    IEEE format, differences from
  21861.  Binary-access
  21862.  Binary-access files
  21863.    creating
  21864.    opening
  21865.    reading
  21866.    writing to
  21867.  Bit
  21868.  Bitwise operators. See Logical operators
  21869.  Blank COMMON block
  21870.  BLOAD statement
  21871.  block
  21872.  Block IF...THEN...ELSE
  21873.  Bold text, indicating keywords
  21874.  B_OnExit routine
  21875.  Boolean
  21876.    constants
  21877.    expressions
  21878.      definition
  21879.      logical operators
  21880.      other
  21881.      relational operators (table)
  21882.  bound
  21883.  bound for
  21884.  Boxes,
  21885.  Boxes, LINE statement
  21886.  BRUN40.LIB, default for linker
  21887.  BSAVE statement
  21888.  buffer
  21889.  BUILDLIB utility
  21890.  by QuickBASIC
  21891.  by value
  21892.    defined
  21893.  
  21894.  C
  21895.  
  21896.  /C option (BC)
  21897.  CALL
  21898.  CALL ABSOLUTE
  21899.  CALL INT86OLD statement
  21900.  CALL INT86XOLD statement
  21901.  CALL INTERRUPT
  21902.  CALL INTERRUPT statement
  21903.  CALL INTERRUPTX statement
  21904.  CALL statement
  21905.    DECLARE, used with
  21906.    described
  21907.    optional
  21908.    QuickBASIC/interpreter differences
  21909.    SUB procedure, calling
  21910.  calls
  21911.  CALLS statement
  21912.  CALLS statement (non-BASIC)
  21913.  Carriage-return-line-feed
  21914.  Cartesian coordinates. See View coordinates
  21915.  Case
  21916.    sensitivity
  21917.    significance,
  21918.  CASE clause. See SELECT CASE statement
  21919.  CASE$ function
  21920.  CDBL function
  21921.  CDECL, use in DECLARE statement
  21922.  CGA
  21923.    palette, changing
  21924.    screen modes supported by
  21925.  CHAIN
  21926.  CHAIN statement
  21927.    described
  21928.    QuickBASIC/interpreter differences
  21929.  Chaining programs,
  21930.  Chaining programs, statements used. See individual
  21931.  changing number of
  21932.  changing with
  21933.  Characters
  21934.    how stored
  21935.    limits
  21936.  CHDIR statement
  21937.  Checking between statements option
  21938.  Choosing
  21939.    commands,
  21940.    options, differences among versions
  21941.  CHR$ function
  21942.  CINT function
  21943.  CIRCLE
  21944.  CIRCLE statement
  21945.    arcs
  21946.    circles
  21947.    described
  21948.    ellipses
  21949.    pie shapes
  21950.  Circles, drawing
  21951.  clause
  21952.  CLEAR
  21953.  CLEAR statement
  21954.  CLNG function
  21955.  CLOSE statement
  21956.  CLS statement
  21957.  /CODEVIEW option (LINK)
  21958.  codes
  21959.    determining with the ASC function
  21960.    storing characters in memory
  21961.  CodeView
  21962.  COLOR
  21963.  Color
  21964.  Color Graphics Adapter. See CGA
  21965.  COLOR statement
  21966.    background color, controlling
  21967.    described
  21968.    foreground color, controlling
  21969.    palette, changing with
  21970.    screen mode 1, syntax in
  21971.  Colors
  21972.    background,
  21973.    CGA, using with
  21974.    clarity, tradeoff with
  21975.    foreground,
  21976.    foreground, controlling
  21977.    graphics statements, specifying in
  21978.    PALETTE
  21979.    PALETTE,
  21980.  Columns
  21981.    changing
  21982.    skipping
  21983.  COM
  21984.  COM devices
  21985.  COM statements
  21986.  Comma (,)
  21987.    ending fields
  21988.    variable separator
  21989.  command
  21990.    option
  21991.      /MBF
  21992.    /RUN option
  21993.  COMMAND$
  21994.  command, DRAW
  21995.  COMMAND$ function
  21996.    limits
  21997.  Command line
  21998.    BASIC program passing to
  21999.    Quick
  22000.  command line
  22001.  command symbol
  22002.  command-line
  22003.  Commands
  22004.    BC. See BC command
  22005.    Linker. See LINK
  22006.    versions,
  22007.  commands
  22008.  Commands QB. See QB command
  22009.  Comments
  22010.    REM statement
  22011.  Comments, introducing with apostrophe
  22012.  COMMON
  22013.  COMMON block
  22014.    blank
  22015.    named
  22016.  COMMON statement
  22017.    AS clause
  22018.    chaining programs
  22019.    QuickBASIC/interpreter differences
  22020.    SHARED
  22021.    SHARED attribute
  22022.      defined
  22023.      described
  22024.      variables, sharing across
  22025.    variables,
  22026.  compared with
  22027.  Comparing
  22028.  Comparing strings
  22029.    relational operators, with
  22030.  Compatibility
  22031.    BASICA
  22032.    versions,
  22033.  compatibility among
  22034.  Compile options
  22035.  Compile-time error messages
  22036.  Compiling from DOS
  22037.  Complex numbers, defined
  22038.  CON (device name)
  22039.  Concatenation, defined
  22040.  CONS
  22041.  CONST statement
  22042.  Constants
  22043.    input list
  22044.    procedures, passing to
  22045.    string, literal and symbolic
  22046.    symbolic
  22047.  constants
  22048.    format in program examples
  22049.    string
  22050.  contrasted with
  22051.  Control-flow
  22052.  Control-flow statements. See individual
  22053.    CALL
  22054.    CALL ABSOLUTE
  22055.    CALLS
  22056.    CHAIN
  22057.    DO...LOOP
  22058.    FUNCTION
  22059.    GOSUB...RETURN
  22060.    GOTO
  22061.    IF...THEN...ELSE
  22062.    ON GOTO
  22063.    ON...GOTO
  22064.    RETURN
  22065.    SELECT CASE
  22066.  Control-flow structures
  22067.    BASIC, used in (table)
  22068.    decision
  22069.    defined
  22070.    indenting
  22071.    new
  22072.  Controlling
  22073.    linker
  22074.    segments
  22075.    stack size
  22076.  controlling
  22077.  conventions
  22078.    BASIC programs
  22079.  Converting
  22080.    BASICA and GW-BASIC programs
  22081.    data
  22082.    IEEE format, program for
  22083.  converting to QuickBASIC
  22084.  Coordinates
  22085.    absolute
  22086.      STEP, specifying
  22087.      VIEW SCREEN, specifying
  22088.    physical
  22089.      GET
  22090.      pixels,
  22091.      view
  22092.    pixels, locating
  22093.    relative
  22094.      defined
  22095.      STEP
  22096.      VIEW
  22097.    view
  22098.      GET statement
  22099.      physical coordinates, translating
  22100.      WINDOW,
  22101.    viewport,
  22102.  coordinates. See Coordinates, absolute
  22103.    WINDOW statement
  22104.  coordinates, translating to
  22105.  COS
  22106.  (/CP)
  22107.  /CPARMAXALLOC option (LINK)
  22108.  creating outside QuickBASIC environment
  22109.  Cross-reference-file
  22110.  CSNG function
  22111.  CSRLIN function
  22112.  Cursor
  22113.    graphics
  22114.    text
  22115.      defined
  22116.      LOCATE, positioning
  22117.      location, finding
  22118.      shape, changing
  22119.  cursor
  22120.  CVD function
  22121.  CVDMBF
  22122.  CVDMBF function
  22123.  CVI function
  22124.  CVL
  22125.  CVL function
  22126.  CVS
  22127.  CVSMBF function
  22128.  CVtype statement
  22129.  
  22130.  D
  22131.  
  22132.  /D option (BC)
  22133.  Data
  22134.  Data files
  22135.    closing
  22136.    creating
  22137.    defined
  22138.    file numbers
  22139.    file-access errors,
  22140.    opening
  22141.    organization
  22142.    random-access
  22143.    reading
  22144.    records, adding
  22145.    sequential
  22146.  data, preventing
  22147.  DATA statement
  22148.  Data types
  22149.    TYPE statement
  22150.  Data-file buffer
  22151.  DATE$
  22152.  Date and time
  22153.    functions
  22154.      DATE$
  22155.      TIME$
  22156.    statements
  22157.      DATE$
  22158.      TIME$
  22159.  DATE$ statement
  22160.  Debug option
  22161.  debugger, debugging with
  22162.  debugger, LINK option for
  22163.  Debugging
  22164.    /CODEVIEW (LINK) option
  22165.    statements
  22166.    versions, differences among
  22167.  Decision
  22168.  Decision structures
  22169.    defined
  22170.    IF...THEN...ELSE
  22171.      block
  22172.      single-line
  22173.    SELECT CASE
  22174.  Declarations. See individual statement names
  22175.    CONST
  22176.    DECLARE statement (BASIC procedures)
  22177.    DECLARE statement (non-BASIC
  22178.    DEFtype
  22179.    DIM statement
  22180.  DECLARE
  22181.  DECLARE statement
  22182.    described
  22183.    include
  22184.    QuickBASIC,
  22185.    versions, differences among
  22186.    where required
  22187.  Declaring arrays
  22188.    limits
  22189.  DEF FN functions
  22190.    exit from, alternative
  22191.    FUNCTION procedure, contrasted with
  22192.    local
  22193.  DEF FN statement
  22194.  DEF SEG statement
  22195.  DEFDBL statement
  22196.  defining with
  22197.  definitions
  22198.  DEFINT statement
  22199.  DEFLNG statement
  22200.  DEFSNG statement
  22201.  DEFSTR
  22202.  DEFtype
  22203.    QuickBASIC/interpreter differences
  22204.  DEFtype
  22205.  Degrees
  22206.    compared with
  22207.    converting to radians
  22208.  deleting from, including, and replacing
  22209.  Device I/O, contrasted with file I/O
  22210.  (device name)
  22211.  Devices
  22212.    COM
  22213.    CONS
  22214.    function
  22215.    function handling
  22216.      IOCTL$
  22217.      PEN
  22218.    I/O modes, valid
  22219.    KEYBD
  22220.    LPT
  22221.    names
  22222.    SCRN
  22223.    statement handling
  22224.      IOCTL
  22225.      OPEN
  22226.      OUT
  22227.      WAIT
  22228.  Device-status information
  22229.  differences among
  22230.  Differences among versions
  22231.    file compatibility
  22232.    (table)
  22233.  differences among versions
  22234.  DIM
  22235.  DIM statement
  22236.    AS
  22237.    described
  22238.    QuickBASIC/interpreter differences
  22239.    SHARED attribute
  22240.      defined
  22241.      example,
  22242.      variables,
  22243.    TO clause
  22244.  Dimensioning
  22245.  DIRECTION
  22246.  keys, trapping
  22247.  Directory
  22248.  Directory statements
  22249.    CHDIR
  22250.    FILES
  22251.    MKDIR
  22252.    RMDIR
  22253.  Display memory, PCOPY statement
  22254.  displaying
  22255.  DO UNTIL statement
  22256.  DO WHILE statement
  22257.  Document conventions
  22258.  Dollar
  22259.  DO...LOOP
  22260.  DO...LOOP statement
  22261.    described
  22262.    exit from,
  22263.    exit from, alternative
  22264.    keyword
  22265.      UNTIL
  22266.      WHILE
  22267.    loop test, location of
  22268.    syntax
  22269.    WHILE...WEND,
  22270.  DOS
  22271.  DOS-level
  22272.  option (LINK)
  22273.  /DOSSEG
  22274.  Dotted lines, drawing
  22275.  Double quotes ("), ending fields
  22276.  Double-precision
  22277.  Double-precision numbers
  22278.    size limits
  22279.  DRAW statement
  22280.    described
  22281.    figures
  22282.      rotating
  22283.      scaling
  22284.    macro commands in
  22285.    QuickBASIC/interpreter differences
  22286.    VARPTR$
  22287.  drawing
  22288.  Dumb terminal, defined
  22289.  Dummy arguments, POS function
  22290.  #DYNAMIC metacommand
  22291.  Dynamic arrays
  22292.    #DYNAMIC metacommand
  22293.    ERASE
  22294.    REDIM
  22295.  
  22296.  E
  22297.  
  22298.  /E option
  22299.    BC
  22300.    QB
  22301.  /E option
  22302.    BC
  22303.  Editing, differences
  22304.  EGA, changing palette
  22305.  elements
  22306.  Ellipses, drawing
  22307.  ELSE clause
  22308.  ELSEIF clause
  22309.  END
  22310.  END DEF
  22311.  END FUNCTION statement
  22312.  END IF statement
  22313.  END SELECT
  22314.  END statement
  22315.  END SUB statement
  22316.  END TYPE statement
  22317.  End-of-line markers
  22318.  Enhanced Graphics Adapter. See EGA
  22319.  key, equivalent to SPACEBAR
  22320.  ENTER
  22321.  ENVIRON$ function
  22322.  ENVIRON statement
  22323.  environment variable
  22324.  Environment variables
  22325.    described
  22326.    LIB
  22327.    LINK
  22328.    TMP, used by LINK
  22329.  Environment-string
  22330.  EOF
  22331.  EOF function
  22332.  EQV
  22333.  ERASE statement
  22334.  Erasing
  22335.  ERDEV$
  22336.  ERDEV$ function
  22337.  ERL function
  22338.  ERR
  22339.    code
  22340.    function
  22341.  ERR
  22342.  ERRDEV function
  22343.  ERRDEV$ function
  22344.  Error
  22345.  Error codes
  22346.  Error messages
  22347.    compile-time
  22348.    described
  22349.    invocation
  22350.    LIB
  22351.    LINK
  22352.    numbers, limits (table)
  22353.    redirection
  22354.    run-time
  22355.  ERROR statement
  22356.  Error trapping
  22357.    ERR, identifying errors with
  22358.    ERROR statement
  22359.    error-handling routine
  22360.    file-access errors
  22361.    multiple modules
  22362.    Quick libraries
  22363.    screen modes, inappropriate
  22364.    SUB or FUNCTION procedures
  22365.    syntax,
  22366.  Error-handling
  22367.  Error-handling routines
  22368.    parts
  22369.    specifying
  22370.  Error-handling statements
  22371.    ERDEV
  22372.    ERR, ERL
  22373.  Error-message window
  22374.  event
  22375.  Event polling, event trapping, contrasted with
  22376.  Event trapping. See specific
  22377.    activating
  22378.    background music
  22379.    described
  22380.    disabling
  22381.    keystrokes
  22382.    multiple modules
  22383.    options,
  22384.    polling, contrasted with
  22385.    routines, event-handling
  22386.    statements and functions, summary of (table)
  22387.    SUB
  22388.    suspending
  22389.    syntax, error-trapping
  22390.    trappable events
  22391.    types
  22392.    types of
  22393.      COM
  22394.      KEY
  22395.      PEN
  22396.      PLAY
  22397.      TIMER
  22398.  event trapping
  22399.    PLAY ON statement
  22400.  Event trapping, Quick library
  22401.  Event-handling
  22402.  Event-handling routine
  22403.  Event-trapping
  22404.  Event-trapping option
  22405.  Event-trapping statements. See individual
  22406.    COM
  22407.    KEY LIST
  22408.    KEY OFF
  22409.    ON
  22410.    ON event
  22411.    PEN ON, OFF, and STOP
  22412.    PLAY ON, OFF, and STOP
  22413.    TIMER ON, OFF, and STOP
  22414.    UEVENT
  22415.  event-trapping syntax, contrasted with
  22416.  examples
  22417.  Executable
  22418.  /EXEPACK option (LINK)
  22419.  EXIT
  22420.  EXIT DEF statement
  22421.  EXIT DO statement
  22422.  EXIT FOR statement
  22423.  EXIT FUNCTION statement
  22424.  EXIT statement
  22425.  EXIT SUB statement
  22426.  Exiting, functions and procedures
  22427.  EXP function
  22428.  Expressions
  22429.    Boolean
  22430.    false
  22431.    lists
  22432.    procedures, passing to
  22433.    true
  22434.  expressions, comparing with
  22435.  Expressions, string. See Strings
  22436.  Extensions, file-name
  22437.  Extra files produced
  22438.  extracting and deleting
  22439.  
  22440.  F
  22441.  
  22442.  Factorial function
  22443.  False expressions
  22444.  FIELD
  22445.  FIELD statement
  22446.    described
  22447.    random-access
  22448.    TYPE...END
  22449.  Fields
  22450.    defined
  22451.    records
  22452.      random-access
  22453.      sequential
  22454.    sequential files, delimited
  22455.  fields
  22456.  fields, delimiting
  22457.  figures with DRAW
  22458.  File
  22459.    names
  22460.      characters,
  22461.      OPEN statement
  22462.    numbers
  22463.      CLOSE, freeing with
  22464.      FREEFILE, getting with
  22465.      freeing
  22466.      OPEN statement
  22467.      values, allowable
  22468.    pointers
  22469.  file
  22470.    LIB
  22471.  File
  22472.  File access
  22473.    LOCK statement
  22474.    UNLOCK
  22475.    UNLOCK statement
  22476.  File conversion
  22477.  File handling. See statements;individual statement names
  22478.    functions
  22479.      EOF
  22480.      FILEATTR
  22481.      FREEFILE
  22482.      LOC
  22483.      LOF
  22484.      SEEK
  22485.    statements
  22486.      CHDIR
  22487.      CLOSE
  22488.      FIELD
  22489.      GET
  22490.      INPUT #
  22491.      KILL
  22492.      LOCK
  22493.      NAME
  22494.      OPEN
  22495.      RESET
  22496.      SEEK
  22497.  File I/O
  22498.    defined
  22499.    device I/O contrasted
  22500.  File names
  22501.    case sensitivity
  22502.    described
  22503.    restrictions
  22504.    truncation
  22505.  file, temporary
  22506.  File-access
  22507.  File-access modes
  22508.    APPEND
  22509.    BINARY
  22510.    INPUT
  22511.    OUTPUT
  22512.    RANDOM
  22513.  FILEATTR function
  22514.  File-name extensions
  22515.  File-naming
  22516.  File-naming conventions
  22517.    BC command
  22518.    DOS
  22519.    LINK
  22520.    Quick libraries
  22521.  Files
  22522.    ASCII format
  22523.    attributes
  22524.    extra, produced by QuickBASIC
  22525.    #INCLUDE
  22526.    length,
  22527.    limits (table)
  22528.    map
  22529.    map (LINK)
  22530.    random-access,
  22531.    random-access, statements
  22532.    random-access, statements and functions. See individual statement and
  22533.    function names
  22534.    sequential,
  22535.    sequential, statements and functions. See individual
  22536.      INPUT
  22537.      WRITE
  22538.    versions,
  22539.  files
  22540.    adding to
  22541.    advantages of
  22542.    appending
  22543.    compact
  22544.    creating
  22545.    format
  22546.    number storage
  22547.    opening
  22548.    packing
  22549.    random-access files, contrasted with
  22550.    records
  22551.    statements and functions
  22552.      FIELD
  22553.      PRINT #
  22554.      PUT
  22555.      RSET
  22556.    statements not allowed
  22557.  FILES
  22558.  files, closing
  22559.  files, contrasted with
  22560.  files (LINK)
  22561.  files, placing in
  22562.  FILES statement
  22563.  Filling. See Painting
  22564.  filling
  22565.  FIX function
  22566.  fixed-length string with
  22567.  Fixed-length strings
  22568.    parameter lists
  22569.    record
  22570.    variable length, contrasted with
  22571.    variables, stand-alone
  22572.  Floating-point
  22573.    precision, within Quick libraries
  22574.  FOR statement
  22575.  Foreground color
  22576.    default
  22577.    screen mode 1
  22578.  form
  22579.  format
  22580.    numbers
  22581.      converting from
  22582.  Formatting text output
  22583.  FOR...NEXT
  22584.  FOR...NEXT loops
  22585.    described
  22586.    execution,
  22587.    exit from, alternative
  22588.    STEP keyword
  22589.  FOR...NEXT statement
  22590.  Forward reference problem
  22591.  Forward reference problem, DECLARE,
  22592.  Forward slash
  22593.  Fractal
  22594.  FRE function
  22595.  FRE statement
  22596.  FREEFILE
  22597.  FREEFILE function
  22598.  from, alternative
  22599.  FUNCTION
  22600.  function
  22601.  function
  22602.    data, reading
  22603.      files
  22604.    described
  22605.    DRAW, use with
  22606.    PLAY, use with
  22607.  FUNCTION
  22608.  function, arguments to
  22609.  function (cosine)
  22610.  Function keys, trapping
  22611.  function name
  22612.  function name
  22613.  function names
  22614.  FUNCTION procedures
  22615.    calling
  22616.    DECLARE statements
  22617.    described
  22618.    error
  22619.    event trapping
  22620.  FUNCTION statement
  22621.    AS
  22622.    described
  22623.    include files,
  22624.    include files, restrictions with
  22625.  function, using
  22626.  FUNCTION...END FUNCTION statements. See FUNCTION procedures
  22627.  Functions. See individual
  22628.    user defined
  22629.  functions
  22630.    CDBL
  22631.    CVL
  22632.    INPUT$
  22633.    INT
  22634.    SIN
  22635.  
  22636.  G
  22637.  
  22638.  GET
  22639.  GET statement
  22640.    described
  22641.    file I/O
  22642.      binary-access
  22643.      random-access
  22644.    graphics
  22645.      array, calculating size of
  22646.      syntax
  22647.    records, user-defined
  22648.  Global variables
  22649.    DEF FN function
  22650.    FUNCTION procedure
  22651.    GOSUB routine
  22652.    SHARED attribute
  22653.    variable aliasing
  22654.  GOSUB
  22655.  GOSUB, contrasted with
  22656.  GOSUB statement
  22657.  GOSUB subroutines
  22658.    SUB procedures,
  22659.  GOTO statement
  22660.    described
  22661.    #INCLUDE metacommand
  22662.  Graphics. See statements;individual statement names
  22663.    functions. See individual statement names
  22664.      PALETTE
  22665.      PMAP
  22666.      POINT
  22667.      VIEW
  22668.      WINDOW
  22669.    statements
  22670.      BLOAD
  22671.      BSAVE
  22672.      CIRCLE
  22673.      COLOR
  22674.      DRAW
  22675.      GET
  22676.      LINE
  22677.      PAINT
  22678.      PALETTE
  22679.      PALETTE
  22680.      PRESET
  22681.      PSET
  22682.      PUT
  22683.      VIEW
  22684.      WINDOW
  22685.  graphics
  22686.  Graphics Adapter), changing palette
  22687.  Graphics cursor. See Cursor, graphics
  22688.  Graphics screen modes. See Screen modes
  22689.  graphics statement, with
  22690.  Graphics statements and functions, summary (table)
  22691.  Graphics viewport. See Viewport,
  22692.  GW-BASIC
  22693.  
  22694.  H
  22695.  
  22696.  /H option (QB)
  22697.  handling
  22698.    functions. See individual function names
  22699.    LPOS
  22700.    statements. See individual statement names
  22701.      UNLOCK
  22702.  /HELP option (LINK)
  22703.  HEX$ function
  22704.  Hexadecimal
  22705.  High-resolution-display
  22706.  
  22707.  I
  22708.  
  22709.  IEEE
  22710.  IEEE format
  22711.    accuracy
  22712.    converting to
  22713.    /MBF
  22714.    numbers
  22715.      converting
  22716.      exponential,
  22717.      Microsoft
  22718.      printing
  22719.      ranges
  22720.  IF...THEN...ELSE
  22721.  IF...THEN...ELSE statement
  22722.    described
  22723.    SELECT CASE
  22724.  IF...THEN...ELSE statement, block
  22725.  IF...THEN...ELSE statement, block form
  22726.  (IGN)
  22727.  /IGNORECASE option (LIB)
  22728.  Ignore case
  22729.    LIB
  22730.    LINK
  22731.  ignoring
  22732.  Images
  22733.    GET, saving to memory with
  22734.    PUT, copying to screen with
  22735.  Immediate window, limits
  22736.  IMP operator
  22737.  in
  22738.  in map files
  22739.  #INCLUDE metacommand
  22740.    COMMON
  22741.    description
  22742.    procedure declarations
  22743.    restrictions
  22744.  Include
  22745.  Include files
  22746.    COMMON
  22747.    procedures
  22748.      declaring
  22749.      not allowed
  22750.  /INFORMATION option (LINK)
  22751.  INKEY$ function
  22752.  INP function
  22753.  INPUT
  22754.  input
  22755.    reading
  22756.  INPUT
  22757.  INPUT #
  22758.  INPUT$
  22759.  Input
  22760.  INPUT$ function
  22761.    data, reading
  22762.      communications device
  22763.      standard input
  22764.    described
  22765.    example
  22766.    INPUT #, contrasted with
  22767.    LINE INPUT #, contrasted with
  22768.    modem, communicating with
  22769.  Input functions. See individual
  22770.    COMMAND$
  22771.    INKEY$
  22772.    INP
  22773.  Input past end error
  22774.  INPUT # statement
  22775.    described
  22776.    example
  22777.    INPUT$,
  22778.    LINE INPUT #, contrasted with
  22779.  INPUT statement
  22780.    carriage-return-line-feed sequence, suppressing
  22781.    defined
  22782.    described
  22783.    error
  22784.    example
  22785.    LINE INPUT,
  22786.    variable
  22787.  Input statements. See individual
  22788.    DATA
  22789.    INPUT
  22790.    LINE
  22791.    READ
  22792.    RESTORE
  22793.  Input/Output. See I/O
  22794.  Insert mode, differences
  22795.  INSTR function
  22796.  INT function
  22797.  INT86, INT86X replacements
  22798.    CALL
  22799.    CALL INT86OLD statements
  22800.  INT86OLD
  22801.  Integers
  22802.    converting
  22803.    converting to
  22804.    FIX function
  22805.    limits, (table)
  22806.  Interpreted
  22807.  INTERRUPT
  22808.  Interrupt
  22809.  INTERRUPT statements
  22810.  Invocation error
  22811.  I/O
  22812.    binary-access
  22813.    defined
  22814.    devices, from and to
  22815.    files, from and to
  22816.    ports
  22817.    standard
  22818.  IOCTL$ function
  22819.  IOCTL statement
  22820.  Italic text, showing placeholders
  22821.  items
  22822.  
  22823.  J
  22824.  
  22825.  Joysticks
  22826.  
  22827.  K
  22828.  
  22829.  Key
  22830.  KEY LIST
  22831.  KEY OFF statement
  22832.  KEY ON statement
  22833.  KEY statement
  22834.  Key trapping
  22835.    activating
  22836.    keys
  22837.      DIRECTION
  22838.      user-defined
  22839.  key trapping
  22840.  KEYBD
  22841.  Keyboard, reading input from
  22842.  Keyboard scan codes
  22843.  KEY(n) statements
  22844.  Keys
  22845.    debugging, differences among versions
  22846.    DIRECTION,
  22847.    editing, differences among versions
  22848.    ENTER
  22849.    SPACEBAR
  22850.  Keywords, format in program examples
  22851.  KILL statement
  22852.  
  22853.  L
  22854.  
  22855.  (QB)
  22856.  /L option
  22857.  Labels
  22858.  Language differences among
  22859.  Last
  22860.  Last point referenced
  22861.  LBOUND function
  22862.  LCASE$
  22863.  LCASE$ function
  22864.  leading blank
  22865.  LEFT$
  22866.  LEFT$ function
  22867.  LEN
  22868.  LEN function
  22869.    described
  22870.    sample
  22871.    sample program application
  22872.    use of
  22873.  LET statement
  22874.  letters
  22875.    file names
  22876.  .LIB files. See Libraries, stand-alone
  22877.  LIB
  22878.    case sensitivity
  22879.    command
  22880.    command symbols
  22881.      plus
  22882.      plus sign (+)
  22883.    default responses
  22884.    described
  22885.    invoking
  22886.    libraries, combining
  22887.    library
  22888.    library modules
  22889.    listing files
  22890.    options
  22891.      case sensitivity
  22892.      dictionary, no extended
  22893.      /IGNORECASE (/P)
  22894.      /NOEXTDICTIONARY
  22895.      /NOIGNORECASE
  22896.      page size, specifying
  22897.      /PAGESIZE
  22898.    response file
  22899.    search path
  22900.  LIB command symbol
  22901.  LIB error messages
  22902.  LIB.EXE
  22903.  Libraries. See Quick libraries
  22904.    default,
  22905.    default, ignoring
  22906.    described
  22907.    LINK, specifying for
  22908.    search
  22909.    stand-alone
  22910.      combining
  22911.      defined
  22912.      described
  22913.      LIB
  22914.      listing
  22915.      modules,
  22916.      object
  22917.      object modules,
  22918.      object modules, deleting from, including,
  22919.      parallel
  22920.    types, contrasted
  22921.    user.
  22922.  libraries. See Quick Libraries
  22923.    CALL INT86OLD statement
  22924.    compatibility among versions
  22925.    compilation
  22926.    contents
  22927.      described
  22928.    use of
  22929.  libraries, creating
  22930.  library, creating from
  22931.  Library Manager. See LIB
  22932.  Limits, file size and complexity (table)
  22933.  /LINENUMBERS option (LINK)
  22934.  Line
  22935.  LINE INPUT
  22936.  LINE INPUT # statement
  22937.    described
  22938.    INPUT #, contrasted
  22939.    INPUT$, contrasted
  22940.  LINE INPUT statement
  22941.    described
  22942.  Line printer
  22943.  LINE statement
  22944.    coordinate pairs, order of
  22945.    described
  22946.    lines and boxes, drawing
  22947.    sample applications
  22948.    syntax
  22949.  Lines, drawing
  22950.  (LINK)
  22951.  LINK. See Libraries
  22952.    command line, invoking from
  22953.    defaults
  22954.    libraries, specifying
  22955.    options
  22956.      abbreviations
  22957.      arguments, numerical
  22958.      /BATCH (/B)
  22959.      BC, unsuitable for
  22960.      case sensitivity
  22961.      CodeView
  22962.      /CODEVIEW (/CO)
  22963.      command line, order
  22964.      /CPARMAXALLOC
  22965.      default libraries, ignoring
  22966.      displaying
  22967.      /DOSSEG (/DO)
  22968.      /EXEPACK (/E)
  22969.      /HELP (/HE)
  22970.      /IGNORECASE
  22971.      information,
  22972.      /INFORMATION (/I)
  22973.      line
  22974.      /LINENUMBERS (/LI)
  22975.      LINK
  22976.      linker
  22977.      map
  22978.      /MAP (/M)
  22979.      /NODEFAULTLIBRARYSEARCH
  22980.      /NOIGNORECASE
  22981.      /NOPACKCODE (/NOP)
  22982.      /PACKCODE (/PAC)
  22983.      paragraph space, allocating
  22984.      /PAUSE
  22985.      pausing
  22986.      Quick
  22987.      /QUICKLIB (/Q)
  22988.      segments
  22989.      /SEGMENTS
  22990.      segments,
  22991.      stack
  22992.      /STACK (/ST)
  22993.    output
  22994.    output file, temporary
  22995.    Quick libraries, other language routines
  22996.    response file
  22997.  LINK environment variable
  22998.  LINK error messages
  22999.  LINK options
  23000.  Linker. See LINK
  23001.  LINK.EXE
  23002.  Linking. See LINK
  23003.  Linking from DOS
  23004.  list
  23005.  list, format of
  23006.  listing
  23007.  Listing files, cross-reference (LIB)
  23008.  Literal constants,
  23009.  Loading Quick libraries
  23010.  LOC function
  23011.    described
  23012.    devices, with
  23013.    modem, communicating with
  23014.    SEEK,
  23015.  local
  23016.  Local variables
  23017.  LOCATE statement
  23018.    cursor
  23019.      changing
  23020.      positioning
  23021.    described
  23022.    example
  23023.  locating
  23024.  LOCK statement
  23025.  LOF
  23026.  LOF function
  23027.    described
  23028.    devices
  23029.    example
  23030.    files
  23031.  LOG function
  23032.  Logical
  23033.  Logical coordinates
  23034.    physical coordinates,
  23035.  Logical operators
  23036.  Long integers
  23037.    advantages of
  23038.    converting
  23039.    converting to
  23040.    limits (table)
  23041.  Looping
  23042.  Looping structures
  23043.    defined
  23044.    DO...LOOP
  23045.    WHILE...WEND
  23046.  loops
  23047.    nesting
  23048.  Lowercase
  23049.  Lowercase letters
  23050.    uppercase, converting to
  23051.  LPOS function
  23052.  LPRINT statement, SPC function
  23053.  LPRINT USING statement
  23054.  LPT devices
  23055.  LSET
  23056.  LSET statement
  23057.  .LST files. See Listing files
  23058.  LTRIM$ function
  23059.    blanks, leading, printing numbers without
  23060.    described
  23061.    spaces, leading, stripping
  23062.    spaces, leading, stripping
  23063.  
  23064.  M
  23065.  
  23066.  Macro
  23067.  Main module
  23068.  libraries, use with
  23069.  .MAK files, Quick
  23070.  Make Library command
  23071.  making global
  23072.  Mandelbrot set
  23073.  .MAP files. See Map files
  23074.  /MAP option (LINK)
  23075.  Map
  23076.  Map files
  23077.  Map files (LINK)
  23078.  mapping to
  23079.  Math functions
  23080.    ABS
  23081.    ATN
  23082.    COS
  23083.    CVSMBF
  23084.    EXP
  23085.    LOG
  23086.    MKSMBF$, MKDMBF$
  23087.    SIN
  23088.    SQR
  23089.    TAN
  23090.  /MBF option
  23091.    BC
  23092.    QB
  23093.  option, using with old programs
  23094.  Memory
  23095.    available, calculating
  23096.    requirements, Quick libraries
  23097.  Memory functions
  23098.  Memory management
  23099.    functions. See individual
  23100.      FRE
  23101.      SETMEM
  23102.    statements
  23103.      CLEAR
  23104.      DEF
  23105.      ERASE
  23106.      individual
  23107.      PCOPY
  23108.  Menu commands, differences among versions
  23109.  message, invalid-input
  23110.  messages
  23111.  Metacommands
  23112.    described
  23113.    #DYNAMIC
  23114.    #INCLUDE See also #INCLUDE metacommand
  23115.    #STATIC
  23116.  Microsoft
  23117.  Microsoft Binary format
  23118.    numbers
  23119.  Microsoft Library Manager. See LIB
  23120.  MID$
  23121.    function
  23122.  MID$
  23123.  MID$ function
  23124.  MID$ statement
  23125.  Minimize String Data option
  23126.  Mixed-language
  23127.  Mixed-language programming
  23128.    ALIAS, use of
  23129.    CALL,
  23130.    CDECL,
  23131.    DECLARE
  23132.    Quick libraries
  23133.  MKD$ function
  23134.  MKDIR statement
  23135.  MKDMBF$ function
  23136.  MKI$ function
  23137.  MKL$
  23138.  MKS$ function
  23139.  MKSMBF$ function
  23140.  MKtype statement
  23141.  MKtype$ statement
  23142.  MKtypeMBF$ statement
  23143.  mode 1
  23144.  Modem, communicating with
  23145.  modes
  23146.    BINARY
  23147.    INPUT
  23148.    OUTPUT
  23149.  modes, EGA and VGA
  23150.  Module-level code
  23151.  Modules. See Multiple
  23152.  modules
  23153.    event trapping
  23154.  modules
  23155.  modules, deleting from, including, and replacing
  23156.  monochrome
  23157.  Monochrome screen mode
  23158.  Moving images with PUT
  23159.  Multiple
  23160.  Multiple modules
  23161.    advantages
  23162.    error
  23163.    error trapping
  23164.    event trapping
  23165.    loading
  23166.    main module
  23167.    programming style
  23168.    Quick libraries
  23169.    size limits (table)
  23170.    variables,
  23171.    variables, sharing
  23172.    versions, differences among
  23173.  Music
  23174.    background
  23175.    statements
  23176.  Music
  23177.  Music event trapping
  23178.    ON PLAY GOSUB statement
  23179.  music option
  23180.  
  23181.  N
  23182.  
  23183.  NAME statement
  23184.  Named COMMON
  23185.  Named COMMON block
  23186.  names
  23187.  Names, devices
  23188.  nclude files
  23189.    nesting limits (table)
  23190.  New line. See Carriage-return-line-feed sequence
  23191.  NEXT statement
  23192.  No extended dictionary, library
  23193.  NOCOM.OBJ file
  23194.  (/NOD)
  23195.  /NODEFAULTLIBRARYSEARCH option (LINK)
  23196.  /NOEXTDICTIONARY option (LIB)
  23197.  (/NOI)
  23198.  /NOIGNORECASE option (LIB)
  23199.  /NOIGNORECASE option (LINK)
  23200.  non-BASIC procedures
  23201.  /NOPACKCODE option (LINK)
  23202.  NOT
  23203.  not generated by
  23204.  NOT operator
  23205.  notation
  23206.    placeholders
  23207.  Notational
  23208.  NUL (device name)
  23209.  Null
  23210.  NUL.MAP file
  23211.  number, displaying
  23212.  number of on screen
  23213.  Numbers
  23214.    positive, printing without leading blank
  23215.    random-access files, storage in
  23216.    screen,
  23217.    screen, printing on
  23218.    strings, representing as
  23219.  numbers
  23220.    converting to
  23221.  Numeric
  23222.  Numeric conversions
  23223.    CVD
  23224.    CVI
  23225.    CVL function
  23226.    CVS function
  23227.    double-precision
  23228.    integer
  23229.    single-precision
  23230.  Numeric functions. See individual function names
  23231.    CINT
  23232.    CLNG
  23233.    CSNG
  23234.    CVD
  23235.    CVI
  23236.    CVS
  23237.    FIX
  23238.    RND
  23239.    SGN
  23240.  
  23241.  O
  23242.  
  23243.  /O option (BC)
  23244.  Object
  23245.    files
  23246.    modules
  23247.  OCT$ function
  23248.  Octal conversion
  23249.  of
  23250.    STRIG
  23251.  of, printing
  23252.  on
  23253.  ON
  23254.  ON COM statement
  23255.  ON ERROR
  23256.  ON ERROR GOTO statement
  23257.    described
  23258.    example
  23259.    syntax
  23260.  ON event
  23261.  ON event GOSUB statements
  23262.  ON event statements
  23263.  ON expression statement
  23264.  ON PEN statement
  23265.  ON PLAY GOSUB statement
  23266.  ON PLAY statement
  23267.  ON statement
  23268.  ON STRIG
  23269.  ON TIMER statement
  23270.  ON UEVENT statement
  23271.  ON...GOSUB statement
  23272.  ON...GOTO statement
  23273.  OPEN
  23274.  OPEN COM statement
  23275.  OPEN statement
  23276.    described
  23277.    file names in
  23278.    file-access
  23279.    file-access modes
  23280.      APPEND
  23281.      INPUT
  23282.      OUTPUT
  23283.    LEN
  23284.  opening for I/O
  23285.  operator
  23286.  Operators
  23287.    logical
  23288.    relational
  23289.    relational,
  23290.  operators
  23291.    string comparisons
  23292.  option
  23293.  OPTION BASE statement
  23294.  option (QB)
  23295.  option required
  23296.  Options, BC. See BC command
  23297.  Options, LIB. See LIB
  23298.  Options, LINK. See LINK
  23299.  or FUNCTION procedures, within
  23300.  OR operator
  23301.  ordering
  23302.  OUT statement
  23303.  Output. See statements;individual function names
  23304.    functions. See individual function names
  23305.      LPOS
  23306.      POS
  23307.      TAB
  23308.    line
  23309.    statements
  23310.      BEEP
  23311.      CLS
  23312.      LPRINT
  23313.      OUT
  23314.      PRINT
  23315.      PRINT
  23316.      PRINT #
  23317.      PRINT USING
  23318.      PUT
  23319.      WRITE
  23320.      WRITE #
  23321.  Overlay linker. See LINK
  23322.  Overtype mode, differences among versions
  23323.  
  23324.  P
  23325.  
  23326.  (/P)
  23327.  /PACKCODE option (LINK)
  23328.  /PAGESIZE option (LIB)
  23329.  Page size, library
  23330.  Pages. See Screen
  23331.  pages
  23332.  pages
  23333.  PAINT
  23334.  PAINT statement
  23335.    argument
  23336.      background
  23337.      border
  23338.    described
  23339.    numeric expression
  23340.    shapes, filling
  23341.      colored
  23342.      patterned
  23343.    string expression
  23344.    tiling
  23345.      monochrome, defining
  23346.      multicolor, defining
  23347.  Painting
  23348.    colors
  23349.    exterior
  23350.    interior
  23351.      patterns,
  23352.    patterns
  23353.      described
  23354.      multicolor
  23355.  PALETTE
  23356.  PALETTE statement
  23357.  PALETTE USING statement
  23358.  Palettes
  23359.    COLOR, changing with
  23360.    PALETTE, changing with
  23361.    screen
  23362.  Paragraph space
  23363.  Parameter list, defined
  23364.  Parameters
  23365.    arguments
  23366.      agreement with
  23367.      distinguished from
  23368.    DECLARE, format in
  23369.    number and
  23370.  Passing
  23371.  Passing by reference
  23372.  Passing by value
  23373.    DEF FN, used in
  23374.  passing to
  23375.  path
  23376.  Path names, limits (table)
  23377.  Pattern tiles, editing on screen
  23378.  Patterns
  23379.    monochrome
  23380.    multicolor
  23381.    shapes,
  23382.    tile size
  23383.  (/PAU)
  23384.  /PAUSE option (LINK)
  23385.  pausing
  23386.  Pausing program execution, FOR...NEXT statement
  23387.  PCOPY
  23388.  PCOPY statement
  23389.  PEEK function
  23390.  PEN function
  23391.  PEN OFF statement
  23392.  PEN ON statement
  23393.  PEN STOP
  23394.  Peripheral devices
  23395.  Physical coordinates
  23396.  Pie shapes, drawing
  23397.  Pixels
  23398.    coordinates, locating with
  23399.    defined
  23400.    PRESET,
  23401.    PSET, plotting with
  23402.    text
  23403.  Place markers, limits (table)
  23404.  planes
  23405.  PLAY
  23406.  PLAY function
  23407.  PLAY OFF statement
  23408.  PLAY statement
  23409.    background
  23410.    described
  23411.    QuickBASIC/interpreter differences
  23412.    VARPTR$ function, using
  23413.  PLAY STOP
  23414.  plotting with
  23415.  Plus
  23416.  Plus (+)
  23417.    sign, LIB command symbol
  23418.  PMAP function
  23419.  PMAP statement
  23420.  POINT function
  23421.  point referenced
  23422.  POKE statement
  23423.  Polling
  23424.  POS function
  23425.  Positive numbers, printing without
  23426.  PRESET
  23427.  PRESET option, with PUT graphics statement
  23428.  PRESET statement
  23429.    color option, using with
  23430.    described
  23431.  previous
  23432.  PRINT
  23433.  PRINT # statement
  23434.    described
  23435.    record
  23436.    WRITE #, contrasted with
  23437.  PRINT statement
  23438.    described
  23439.    example
  23440.    text, wrapping
  23441.  PRINT # USING statement
  23442.  PRINT USING # statement
  23443.  PRINT USING statement
  23444.  Print zone
  23445.  Printing
  23446.    numbers
  23447.      negative
  23448.      positive
  23449.    text
  23450.      printer,
  23451.      screen, to
  23452.  printing
  23453.  printing on
  23454.  PRN
  23455.  Procedures
  23456.    arguments
  23457.      passing by reference
  23458.      passing by value
  23459.    arrays
  23460.    benefits
  23461.    calling
  23462.    constants
  23463.    defining
  23464.    described
  23465.    expressions
  23466.    format
  23467.      argument-list
  23468.      parameter-list
  23469.    include files, declarations in
  23470.    libraries, user
  23471.    limits (table)
  23472.    modules, multiple
  23473.    moving
  23474.    passing
  23475.    Quick
  23476.    records
  23477.    recursive
  23478.    statements
  23479.      FUNCTION...END
  23480.      FUNCTION...END FUNCTION
  23481.      SUB...END
  23482.      SUB...END SUB
  23483.      summary (table)
  23484.    statements not allowed
  23485.    STATIC variables
  23486.    variables
  23487.      global
  23488.      local
  23489.      sharing
  23490.    variables,
  23491.    variables, automatic
  23492.  procedures
  23493.    DEF FN function, contrasted with
  23494.    exit from, alternative
  23495.  procedures)
  23496.  procedures
  23497.  Procedures-only module
  23498.  Program
  23499.    suspension
  23500.    termination
  23501.  program application
  23502.  programming
  23503.    Quick libraries
  23504.  Programming environment, differences in versions
  23505.  Programming style
  23506.    multiple
  23507.  Programs
  23508.    BASICA, GW-BASIC,
  23509.  ProKey, using QuickBASIC with
  23510.  prompting, preventing
  23511.  PSET
  23512.  PSET statement
  23513.    described
  23514.    example
  23515.    STEP option
  23516.  PUT
  23517.  PUT statement
  23518.    described
  23519.    file
  23520.    file I/O
  23521.      binary-access
  23522.      random-access
  23523.    graphics
  23524.      animation
  23525.      interaction with background, controlling
  23526.      syntax
  23527.    records,
  23528.  
  23529.  Q
  23530.  
  23531.  QB
  23532.  QB command
  23533.    /AH
  23534.    /H option
  23535.    /L option
  23536.    /MBF
  23537.    /MBF option
  23538.    /RUN option
  23539.    versions, differences among
  23540.  QB.QLB
  23541.    library
  23542.    loading, automatic
  23543.  QLBDUMP.BAS
  23544.  Quick
  23545.  Quick libraries
  23546.    advantages
  23547.    CALL ABSOLUTE statement
  23548.    CALL INTERRUPT
  23549.    contents
  23550.      described
  23551.      listing
  23552.      reading
  23553.    creating
  23554.      command line, from
  23555.      described
  23556.      files needed
  23557.      LINK, using
  23558.      QuickBASIC, from within
  23559.    default
  23560.    described
  23561.    end user, delivery to
  23562.    errors, trapping in
  23563.    executable files, making compact
  23564.    files
  23565.      needed to create
  23566.      produced by
  23567.    floating-point precision
  23568.    include files, declaring procedures with
  23569.    loading
  23570.    .MAK file, updating
  23571.    memory
  23572.    mixed languages
  23573.    naming
  23574.    object code, linking
  23575.    routines, other languages
  23576.    search
  23577.    updating
  23578.  option (LINK)
  23579.  /QUICKLIB
  23580.  
  23581.  R
  23582.  
  23583.  /R option (BC)
  23584.  Radians
  23585.  radians
  23586.  Random access, contrasted with binary access
  23587.  Random numbers
  23588.  Random-access
  23589.  Random-access files
  23590.    opening
  23591.    records
  23592.      adding
  23593.      organizing
  23594.      reading
  23595.    sequential
  23596.    sequential files, contrasted with
  23597.    statements
  23598.  RANDOMIZE statement
  23599.  READ statement
  23600.  Record numbers
  23601.    limits (table)
  23602.    random-access files, indexing in
  23603.  Record numbers, random-access files
  23604.    indexing in
  23605.  Records
  23606.    binary-access files, writing
  23607.    data, overwriting
  23608.    defined
  23609.    defining
  23610.    described
  23611.    fixed-length
  23612.    procedures,
  23613.    procedures, passing to
  23614.    random-access
  23615.    random-access files
  23616.      reading
  23617.      storing
  23618.      writing
  23619.    sequential
  23620.    sequential files
  23621.      appending
  23622.      reading
  23623.      storing
  23624.    variable length
  23625.  records, defining
  23626.  Rectangles, specifying coordinates
  23627.  Recursive
  23628.  Recursive procedures
  23629.  REDIM
  23630.  REDIM statement
  23631.    described
  23632.    SHARED
  23633.    SHARED attribute
  23634.  reducing
  23635.  reference
  23636.  Relational
  23637.  Relational operators
  23638.    Boolean expressions
  23639.    SELECT CASE statement
  23640.  relative
  23641.  Relative coordinates. See Coordinates,
  23642.  REM statement
  23643.  representing as
  23644.  requirements
  23645.  RESET statement
  23646.  Response
  23647.  Response file
  23648.    example
  23649.    LINK
  23650.  RESTORE statement
  23651.  restrictions with
  23652.  RESUME
  23653.  Resume Next option
  23654.  RESUME NEXT statement
  23655.    described
  23656.    example
  23657.    RESUME,
  23658.  RESUME statement
  23659.    compiler
  23660.    compiler option required
  23661.    described
  23662.    example
  23663.    QuickBASIC/interpreter differences
  23664.    RESUME NEXT, contrasted with
  23665.  retrieving
  23666.    right side
  23667.  RETURN statement
  23668.  RIGHT$ function
  23669.  RMDIR statement
  23670.  RND function
  23671.  Rotating
  23672.  Rotating figures with DRAW
  23673.  routine
  23674.  Routine, B_OnExit
  23675.  routines
  23676.    ERR, identifying errors with
  23677.  Rows, changing number of
  23678.  RSET
  23679.  RSET statement
  23680.  RTRIM$
  23681.  RTRIM$ function
  23682.  /RUN option (QB)
  23683.  Run menu, Make Library command
  23684.  RUN statement
  23685.    data
  23686.  Run-time error messages
  23687.  
  23688.  S
  23689.  
  23690.  /S option (BC)
  23691.  SADD function
  23692.  SAVE statement (BASICA)
  23693.  Saving
  23694.    images, with GET
  23695.    programs, ASCII format
  23696.  Scan codes
  23697.    keyboard
  23698.    trapping keys, use
  23699.  Screen
  23700.    configuration
  23701.      graphics mode
  23702.      text mode
  23703.    functions
  23704.      CSRLIN
  23705.      individual function
  23706.      POS
  23707.      SCREEN
  23708.    resolution,
  23709.    statements. See individual statement names
  23710.      CLS
  23711.      COLOR
  23712.      LOCATE
  23713.      PCOPY
  23714.      SCREEN
  23715.      VIEW PRINT
  23716.      WIDTH
  23717.  Screen
  23718.  SCREEN function
  23719.  Screen modes
  23720.  Screen pages
  23721.  SCREEN statement
  23722.    aspect ratio, effect on
  23723.    described
  23724.    example
  23725.    screen
  23726.      page
  23727.      resolution, adjusting
  23728.    text mode, rows in
  23729.  SCRN
  23730.  Scrolling
  23731.  (/SE)
  23732.  Search paths
  23733.    libraries
  23734.    Quick libraries
  23735.  Searching
  23736.    strings
  23737.  See Quick libraries
  23738.  SEEK function
  23739.  SEEK statement
  23740.  SEG
  23741.  /SEGMENTS option (LINK)
  23742.  Segments
  23743.    lists, map files
  23744.    number
  23745.    order
  23746.    packing
  23747.  SELECT CASE
  23748.  SELECT CASE statement
  23749.    CASE clause
  23750.    CASE ELSE clause
  23751.    described
  23752.    END SELECT
  23753.    IF...THEN...ELSE
  23754.    ON expression
  23755.    routine, error-handling
  23756.    syntax
  23757.    versions, differences among
  23758.  Semicolon (;), LIB command symbol
  23759.  Separate-compilation method. See BC command
  23760.  sequence
  23761.  Sequential
  23762.  Sequential files
  23763.    creating
  23764.    fields
  23765.    opening
  23766.    random-access files, contrasted
  23767.    records
  23768.    statements
  23769.    statements and functions
  23770.      LINE INPUT #
  23771.  Serial communication
  23772.    defined
  23773.    input
  23774.    input buffer
  23775.  Serial ports,
  23776.  Set Main Module command, differences among versions
  23777.  SETMEM function
  23778.  setting
  23779.  SGN function
  23780.  shape of
  23781.  SHARED
  23782.  SHARED attribute
  23783.    COMMON
  23784.    DIM
  23785.      described
  23786.      example
  23787.      prohibited
  23788.    REDIM
  23789.  SHARED statement
  23790.  Shared variables, between modules
  23791.  sharing
  23792.  Shell escape (SHELL statement)
  23793.  Shifted keys, trapping
  23794.  SideKick,
  23795.  sign (+)
  23796.  sign ($), string-type suffix
  23797.  SIN function
  23798.  Sine, SIN function
  23799.  Sine wave, graphing
  23800.  Single-precision
  23801.  Single-precision numbers
  23802.    size limits (table)
  23803.  size
  23804.  size, setting
  23805.  Skipping
  23806.    columns
  23807.    spaces
  23808.  SLEEP statement
  23809.  Sorting,
  23810.  Sorting, examples
  23811.  SOUND statement
  23812.  Source
  23813.  Source files
  23814.    versions, compatibility among
  23815.  SPACE$
  23816.  SPACE$ function
  23817.  Spaces
  23818.    skipping
  23819.    trimming
  23820.  SPC
  23821.  SPC function
  23822.  SPC statement
  23823.  specifying
  23824.    maximum value
  23825.    number of
  23826.  specifying values outside
  23827.  SQR function
  23828.  Squares, drawing
  23829.  /STACK option (LINK)
  23830.  Stack size,
  23831.  Stack size, recursive procedures, adjusting for
  23832.  Stand-alone programs,
  23833.  Standard
  23834.  Standard input
  23835.    defined
  23836.    reading
  23837.    redirecting
  23838.  Standard I/O
  23839.    statements
  23840.  Standard output
  23841.  Standard places, libraries
  23842.  Statement
  23843.    modification required
  23844.  statement
  23845.  statement
  23846.  statement. See Painting
  23847.    arcs
  23848.    arguments, checking with
  23849.    AS clause
  23850.    BASIC procedures
  23851.    buffer allocation, FIELD statement
  23852.    CASE clause
  23853.    color option
  23854.    coordinates
  23855.    described
  23856.    exit from, alternative
  23857.    FIELD statement
  23858.    file numbers in
  23859.    file-access modes
  23860.      APPEND
  23861.      BINARY
  23862.      RANDOM
  23863.    flow control
  23864.    foreground color, controlling
  23865.    graphics
  23866.      animation
  23867.      images, copying to screen
  23868.      memory, copying images to
  23869.    #INCLUDE metacommand, used with
  23870.    INPUT, contrasted with INPUT
  23871.    prompting
  23872.    SHARED attribute
  23873.      prohibited
  23874.    single-line form
  23875.    SPC function
  23876.    STATIC attribute
  23877.    SUB procedure, calling
  23878.    TYPE...END TYPE, contrasted with
  23879.  statement and function names
  23880.  Statement block
  23881.  statement, block form
  23882.  statement, contrasted with
  23883.  statement names
  23884.  statement (non-BASIC)
  23885.  statement, use in
  23886.  Statements. See individual statement names
  23887.  statements. See Individual statement names; individual statement names
  23888.    DEF FN
  23889.    described
  23890.    ERROR
  23891.    FOR...NEXT
  23892.    INPUT #
  23893.    KEY ON
  23894.    KEY(n)
  23895.    NAME
  23896.    ON ERROR
  23897.    ON GOSUB
  23898.    ON...GOSUB
  23899.    RESUME
  23900.    STRIG
  23901.    WAIT
  23902.    WHILE...WEND
  23903.  statements and functions
  23904.    LINE INPUT #
  23905.    LSET
  23906.    PRINT #
  23907.    RSET
  23908.  statements used
  23909.    CHAIN
  23910.    COMMON
  23911.  #STATIC
  23912.    statement
  23913.    variables
  23914.  #STATIC metacommand
  23915.    arrays, dimensioned, implicitly
  23916.    arrays, memory allocation
  23917.  STATIC
  23918.    attribute
  23919.    statement
  23920.  Static arrays
  23921.    ERASE statement
  23922.    #STATIC metacommand
  23923.  STEP
  23924.    option
  23925.  STICK function
  23926.  Stop bits
  23927.  STOP statement
  23928.  STR$ function
  23929.  STRIG function
  23930.  STRIG OFF
  23931.  STRIG ON statement
  23932.  STRIG(n) statements
  23933.  STRING
  23934.  String
  23935.    expressions
  23936.      defined
  23937.      sequential files, delimiting in
  23938.    functions. See individual function names
  23939.      ASC
  23940.      CHR$
  23941.      DATE$
  23942.      HEX$
  23943.      INPUT$
  23944.      INSTR
  23945.      LCASE$
  23946.      LEFT$
  23947.      LEN
  23948.      LTRIM$
  23949.      MID$
  23950.      RIGHT$
  23951.      RTRIM$
  23952.      SADD
  23953.      SPACE$
  23954.      STR$
  23955.      STRING$
  23956.      UCASE$
  23957.      VAL
  23958.    statements. See individual statement names
  23959.      LSET
  23960.      MID$
  23961.      RSET
  23962.    variables. See Strings
  23963.  string
  23964.  STRING$
  23965.  string ("")
  23966.  STRING$ function
  23967.  String, processing. See Strings
  23968.  string with AS
  23969.  String-handling functions, new
  23970.  Strings
  23971.    alphabetizing
  23972.    characters,
  23973.    characters, retrieving
  23974.      left side
  23975.      middle
  23976.    combining
  23977.    comparing
  23978.    constants
  23979.    defined
  23980.    expressions
  23981.    fixed-length
  23982.      AS STRING
  23983.      record elements
  23984.      variable length, contrasted
  23985.    generating
  23986.    limits (table)
  23987.    numbers,
  23988.    replacing
  23989.    spaces,
  23990.    spaces, trimming
  23991.      right side
  23992.    statements and functions, summary of (table)
  23993.    substring, searching for
  23994.    variable-length
  23995.      AS
  23996.      defined
  23997.      fixed-length,
  23998.      maximum
  23999.    variables
  24000.  strings
  24001.    fixed- and variable-length
  24002.  structures
  24003.    FOR...NEXT
  24004.    IF...THEN...ELSE
  24005.      single-line
  24006.    looping
  24007.    SELECT CASE
  24008.  styling
  24009.  SUB
  24010.    procedures
  24011.      CALL
  24012.      DECLARE
  24013.      error trapping in
  24014.      event trapping in
  24015.      exit
  24016.      GOSUB, compared
  24017.      include
  24018.      #INCLUDE metacommand
  24019.      variables,
  24020.    statement
  24021.      AS clause
  24022.      described
  24023.      include files, not allowed in
  24024.      STATIC attribute
  24025.  SUB procedure. See SUB procedures
  24026.  SUB statement
  24027.  SUB...END
  24028.  Subprograms. See SUB
  24029.    CALL statement
  24030.    CALLS
  24031.    SUB statement
  24032.    variables
  24033.  Subroutines. See GOSUB...RETURN subroutine
  24034.  subroutines
  24035.    drawbacks in using
  24036.  Subscripts
  24037.    arrays, limits (table)
  24038.    lower bound, specifying
  24039.    maximum value, specifying
  24040.    number, specifying
  24041.    upper
  24042.  SuperKey,
  24043.  support routines
  24044.  SWAP statement
  24045.  symbol
  24046.  Symbol tables,
  24047.  Symbolic
  24048.  Symbolic constants
  24049.    CONST
  24050.    defined
  24051.    string
  24052.  symbols
  24053.    asterisk (*)
  24054.    minus sign-plus sign (-+)
  24055.  Syntax
  24056.  Syntax Checking command, differences
  24057.  syntax, contrasted with
  24058.  Syntax notation
  24059.    choices
  24060.    optional
  24061.  System
  24062.  System calls
  24063.  SYSTEM statement
  24064.  
  24065.  T
  24066.  
  24067.  TAB function
  24068.  TAB statement
  24069.  (table)
  24070.  table
  24071.  Text
  24072.    screen, printing on
  24073.    wrapping
  24074.  Text
  24075.  Text boxes, limits (table)
  24076.  Tiling. See Painting
  24077.  Time and date functions. See Date and time, functions
  24078.  TIME$ function
  24079.  TIME$ statement
  24080.  TIMER
  24081.  TIMER function
  24082.  TIMER OFF statement
  24083.  TIMER STOP statement
  24084.  Timing function
  24085.  TMP environment variable, LINK, used by
  24086.  to
  24087.  translating to
  24088.  Trapping. See Error trapping, Event trapping
  24089.    errors
  24090.    events
  24091.    multiple modules
  24092.    options, command-line, required by compiler
  24093.  trapping
  24094.    activating
  24095.    keys
  24096.      function
  24097.    statements and functions (table)
  24098.  trapping in
  24099.  Trigonometric
  24100.  Trigonometric functions
  24101.    ATN
  24102.    COS
  24103.    TAN
  24104.  trimming
  24105.    left side
  24106.  TROFF statement
  24107.  TRON statement
  24108.  True expressions
  24109.  TYPE command (DOS)
  24110.  TYPE, contrasted with
  24111.  type, declaring
  24112.  TYPE statement
  24113.    described
  24114.    FIELD, contrasted with
  24115.    versions, differences among
  24116.  TYPE...END
  24117.  TYPE...END TYPE statement
  24118.    example
  24119.    fixed-length strings in
  24120.    random-access records, defining
  24121.  Typeface
  24122.    key names
  24123.    keywords
  24124.    placeholders
  24125.    program
  24126.  types
  24127.    specifying
  24128.  Typographic conventions
  24129.  
  24130.  U
  24131.  
  24132.  UBOUND
  24133.  UBOUND function
  24134.  UCASE$
  24135.  UCASE$ function
  24136.  UEVENT
  24137.  UEVENT statement
  24138.  UNLOCK statement
  24139.  Uppercase letters
  24140.    file names
  24141.    lowercase, converting
  24142.  use of
  24143.  used in BASIC (table)
  24144.  User
  24145.  User libraries
  24146.  User-defined
  24147.    data
  24148.    events
  24149.    types
  24150.  user-defined
  24151.  USING
  24152.  USING, changing with
  24153.  using QuickBASIC with
  24154.  using to circumvent
  24155.  Utility, BUILDLIB
  24156.  
  24157.  V
  24158.  
  24159.  /V compiler option
  24160.    described
  24161.  /V option (BC)
  24162.    described
  24163.    versions, differences among
  24164.  VAL function
  24165.  Variable aliasing
  24166.  variable aliasing
  24167.  Variable-length strings
  24168.    defined
  24169.    fixed-length, compared with
  24170.    GET statement
  24171.    maximum size
  24172.    PUT
  24173.  Variables
  24174.    arrays
  24175.      described
  24176.      elements of, passing
  24177.      entire, passing
  24178.    automatic
  24179.    data type
  24180.    global
  24181.      described
  24182.      function
  24183.      sharing
  24184.      subprograms
  24185.      variable
  24186.    local
  24187.      described
  24188.      function definitions
  24189.      subprograms
  24190.    multiple modules, sharing
  24191.    names
  24192.      limits (table)
  24193.      program examples, format in
  24194.    procedures
  24195.      sharing
  24196.      sharing all in a module
  24197.    procedures, passing to
  24198.    programs, sharing
  24199.    simple, passing
  24200.    STATIC
  24201.    string. See Strings
  24202.    type, declaring
  24203.    values, exchanging, SWAP
  24204.  variables
  24205.  variables in
  24206.  VARPTR$
  24207.  VARPTR function
  24208.    described
  24209.    versions, differences among
  24210.  VARPTR$ function
  24211.    described
  24212.  VARSEG function
  24213.    described
  24214.    versions, differences among
  24215.  Version differences, file compatibility
  24216.  versions
  24217.  VGA (Video
  24218.  VIEW
  24219.  View coordinates
  24220.    physical coordinates,
  24221.    WINDOW, defining with
  24222.  VIEW PRINT statement
  24223.  VIEW SCREEN statement
  24224.  VIEW statement
  24225.  Viewport
  24226.    graphics
  24227.      advantages
  24228.      VIEW,
  24229.      VIEW SCREEN, defining with
  24230.    text
  24231.  viewport. See Viewport
  24232.  VM.TMP file
  24233.  
  24234.  W
  24235.  
  24236.  /W option (BC)
  24237.    described
  24238.    versions, differences among
  24239.  WAIT statement
  24240.  Watch expressions, limits
  24241.  Watchpoints, limits (table)
  24242.  WEND statement
  24243.    described
  24244.    versions, differences among
  24245.  WHILE statement
  24246.  WHILE...WEND
  24247.  WHILE...WEND statement
  24248.    DO...LOOP, contrasted with
  24249.    syntax
  24250.  width
  24251.  WIDTH
  24252.  WIDTH statement
  24253.    columns, changing number of
  24254.    described
  24255.    rows,
  24256.  WINDOW
  24257.  WINDOW SCREEN statement, WINDOW contrasted with
  24258.  WINDOW statement
  24259.    example
  24260.    GET, effect on
  24261.  Windows
  24262.    error-message
  24263.    Immediate, limits (table)
  24264.    versions, differences among
  24265.  with
  24266.  with CLOSE
  24267.  with the ASC function
  24268.  WordStar keys, similarity to
  24269.  Wrapping text
  24270.  WRITE # statement
  24271.    described
  24272.    PRINT #, contrasted
  24273.  WRITE statement
  24274.  
  24275.  X
  24276.  
  24277.  /X option
  24278.    described
  24279.  /X option (BC)
  24280.    described
  24281.    differences among versions
  24282.  XOR operator
  24283.  XOR option, PUT graphics
  24284.  
  24285.  Z
  24286.  
  24287.  /ZD option (BC)
  24288.  /ZI option (BC)
  24289.