home *** CD-ROM | disk | FTP | other *** search
Text File | 2013-11-08 | 853.5 KB | 21,340 lines |
- Microsoft QuickBASIC Programmer's Toolbox
-
-
- ════════════════════════════════════════════════════════════════════════════
-
-
- Microsoft(R) QuickBASIC Programmer's Toolbox
-
- By John Clark Craig
-
-
- ════════════════════════════════════════════════════════════════════════════
-
-
- PUBLISHED BY
- Microsoft Press
- A Division of Microsoft Corporation
- 16011 NE 36th Way, Box 97017, Redmond, Washington 98073-9717
- Copyright (C) 1988 by John Clark Craig
- All rights reserved. No part of the contents of this book may be
- reproduced or transmitted in any form or by any means without the written
- permission of the publisher.
- Library of Congress Cataloging in Publication Data
- Craig, John Clark.
- The Microsoft QuickBASIC programmer's toolbox.
- 1. BASIC (Computer program language) 2. Microsoft QuickBASIC
- (Computer program) I. Title.
- QA76.73.B3C7 1988 005.13'3 88-5115
- ISBN 1-55615-127-6
- Printed and bound in the United States of America.
- 1 2 3 4 5 6 7 8 9 MLML 3 2 1 0 9 8
- Distributed to the book trade in the
- United States by Harper & Row.
- Distributed to the book trade in
- Canada by General Publishing Company, Ltd.
- Distributed to the book trade outside the
- United States and Canada by Penguin Books Ltd.
- Penguin Books Ltd., Harmondsworth, Middlesex, England
- Penguin Books Australia Ltd., Ringwood, Victoria, Australia
- Penguin Books N.Z. Ltd., 182─190 Wairau Road, Auckland 10, New Zealand
- British Cataloging in Publication Data available
- ──────────────────────────────────────────────────────────────────────────
- Project Editor: Suzanne Viescas Manuscript Editor: Michele Tomiak
- Technical Editor: Jon Harshaw
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- Dedication
-
- This book is dedicated with love to
- the three most important people in my life:
- Jeanie, Jennifer, and Adam.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Contents
-
-
- PART I: GETTING STARTED
-
- QUICKBASIC AND TOOLBOXES
- Advantages of Structured Programming
- The Toolboxes in This Book
- MINICAL.BAS──A COMPLETE PROGRAM
- Modular Source-Code Editing
- Building a Quick Library
- Creating the Source Code for MINICAL
- Compiling and Running as an Executable (.EXE) Program
-
- PART II: QUICKBASIC TOOLBOXES AND PROGRAMS
- USING QUICKBASIC TOOLBOXES
- Special Requirements
- QuickBASIC vs Executable Files
- ATTRIB
- BIN2HEX
- BIOSCALL
- BITS
- CALENDAR
- CARTESIA
- CIPHER
- COLORS
- COMPLEX
- DOLLARS
- DOSCALLS
- EDIT
- ERROR
- FIGETPUT
- FILEINFO
- FRACTION
- GAMES
- HEX2BIN
- JUSTIFY
- KEYS
- LOOK
- MONTH
- MOUSGCRS
- MOUSSUBS
- MOUSTCRS
- OBJECT
- PARSE
- PROBSTAT
- QBFMT
- QBTREE
- QCAL
- QCALMATH
- RANDOMS
- STDOUT
- STRINGS
- TRIANGLE
- WINDOWS
- WORDCOUN
-
- PART III: MIXED-LANGUAGE TOOLBOXES
- USING MIXED-LANGUAGE TOOLBOXES
- Near and Far Addressing
- Passing Variables
- Creating Mixed-Language Toolboxes
- CDEMO1.BAS AND CTOOLS1.C
- CDEMO2.BAS AND CTOOLS2.C
-
- PART IV: APPENDIXES
- APPENDIX A Requirements for Running Toolboxes/Programs
- APPENDIX B Functions-to-Modules Cross Reference
- APPENDIX C Subprograms-to-Modules Cross Reference
- APPENDIX D Hexadecimal Format (.OBJ) Files
- APPENDIX E Line-Drawing Characters
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PART 1 GETTING STARTED
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter One QuickBASIC and Toolboxes
-
- Thanks to Microsoft QuickBASIC 4.0, BASIC has finally grown into a
- flexible, full-featured, and powerful programming language. By thumbing
- through this book and glancing at the program listings, you'll see that
- BASIC isn't what it used to be. Microsoft QuickBASIC is easier to read,
- has a faster learning curve, and gives you the power to quickly create
- sophisticated programs that would have been difficult, if not impossible,
- with traditional BASIC.
-
- A key difference between traditional BASIC and QuickBASIC is that
- QuickBASIC allows structured programming, an important feature that makes
- large programs easier to create and maintain.
-
-
- Advantages of Structured Programming
-
- With early versions of BASIC, a program was written and executed as a
- single block of program lines. Inexperienced programmers writing large
- programs could unknowingly create "spaghetti code" (programs that make
- frequent and improper use of GOTO statements) making them generally
- difficult to follow and maintain.
-
- A key feature of QuickBASIC is its ability to let you create structured
- programs──large programs constructed of small, individual program modules.
- Instead of having to create and work with a large (and often overwhelming)
- single block of code, the QuickBASIC programmer need only construct the
- program modules, which are in turn constructed from procedures called
- subprograms and functions. Each of these procedures performs a specific,
- well-defined task. By concentrating on the functionality of a single
- procedure, the programmer is freed from having to worry about other parts
- of the program and can devote full concentration to the task at hand. It's
- been proven that programmers can develop complex programs more quickly and
- accurately using this modular approach.
-
- An additional advantage to structured programming is that these modules
- and procedures can be organized and saved in such a way that they can be
- reused with other programs──avoiding duplication of effort from one
- programming project to another. By grouping modules with complementary
- functionality, a programmer can easily create "toolboxes" of useful
- routines that can, over time, make large programming projects progress
- quickly because major portions of the program are already written.
-
- After construction, a module can also be organized into a Quick Library,
- which is a file saved on disk in a special format. You can then load Quick
- Libraries with the QuickBASIC program, effectively adding the routines in
- the Quick Library to the ones built into QuickBASIC.
-
-
- The Toolboxes in This Book
-
- If you are using (or even thinking of using) QuickBASIC, this book will be
- a valuable reference. If you're only starting out and learning QuickBASIC
- as a first language, you'll find the book immediately useful for learning
- by example. If you're a seasoned, professional programmer using QuickBASIC
- as a software development system, you'll find the routines in this book to
- be valuable extensions to the QuickBASIC language.
-
- Part 1 provides step-by-step instructions for constructing a complete,
- working program called MINICAL. Beginning programmers in particular will
- find this tutorial helpful. Part II contains all the QuickBASIC toolboxes
- and begins with a brief section that explains how to load and run them.
- Part III describes the use of mixed-language toolboxes and contains
- several examples. Finally, five appendixes contain information on the
- requirements for running the toolboxes, cross references to functions and
- subprograms, and additional important information.
-
- If you're an experienced programmer, you may want to skip ahead to Part
- II and start using some of the toolboxes. If you're new to QuickBASIC,
- turn now to the next section. You'll create two modules containing
- functions and subprograms and use them to build a Quick Library. Once
- you've learned the steps needed to create your own programs and your own
- Quick Library, you can use the modules in Parts II and III of this book,
- as well as modules of your own, to create even more Quick Libraries.
- You'll soon have powerful toolboxes that you can use to build programs
- quickly.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter Two MINICAL.BAS──A Complete Program
-
- In this section we will start from scratch and build a complete, working
- program. We'll construct the program, build a Quick Library to extend the
- QuickBASIC language, and build a stand-alone, executable program.
-
- Before we begin, let's take a quick look at the capabilities of the
- QuickBASIC programming environment and at some of the major concepts
- involved. The sample program in this section is made up of two separate
- modules, each consisting of several subprograms and functions. Let's look
- at how QuickBASIC handles each of these.
-
-
- Modular Source-Code Editing
-
- One of the new features of Microsoft QuickBASIC 4.0 is the way that you
- review and edit programs from within the QuickBASIC environment. If you've
- programmed in QuickBASIC, perhaps you've noticed that a program comprising
- several subprograms and functions can't be shown and edited all in one
- piece on the screen. If you haven't yet programmed in QuickBASIC, you need
- only know at this point that you select one subprogram or function from a
- list of currently loaded subprograms and functions as the one you want to
- view and edit. All the other routines are hidden from view. This might
- seem strange at first, but after working on a few programs, you'll begin
- to appreciate the power that this modular editing provides.
-
- A second major advance in QuickBASIC 4.0 is its ability to load into
- memory more than one source-code file at a time. This opens the door to
- creating collections of subprograms and functions, stored in separate
- source-code files by subject, that several different programs can load and
- use independently.
-
- The important concepts about these new features can be summarized in this
- way: A program can be made up of one or more source-code files (modules),
- and each source-code file can be made up of one or more subprograms or
- functions. You can load several of these source files into the QuickBASIC
- environment simultaneously, and all modules can work together to make a
- complete program. Although you can display and edit only one portion of a
- source file at a time, it's easy to jump from one portion to another while
- editing a program.
-
-
- Building a Quick Library
-
- Wouldn't it be nice to create new QuickBASIC statements and functions that
- you could add to the language in such a way that they'd be available for
- your use every time you fired up QuickBASIC? That's what Quick Libraries
- can do for you!
-
- For example, suppose you use hyperbolic functions in almost every program
- you write. You could create these functions in a source-code file to be
- loaded into memory along with each main program you write, or you could
- create a Quick Library so that these functions load at the same time you
- load QuickBASIC. To build a Quick Library, you would simply load the
- hyperbolic function source-code file and select the appropriate menu
- choices from the Run menu.
-
-
- Creating the Source Code for MINICAL
-
- Let's walk through the creation of a complete programming project, step by
- step, to get your feet wet. Fire up your computer and follow along to get
- the maximum benefit. The MINICAL program performs five functions:
- addition, subtraction, multiplication, division, and square root. The
- program is simple in scope, yet it has most of the major components of
- much larger software projects.
-
- Before we start coding, let's look at how the program should run once we
- get it built. The MINICAL program uses Reverse Polish Notation (RPN) for
- input. Using RPN simplifies the programming considerably because it
- eliminates the coding necessary to rearrange those math commands
- enshrouded in parentheses.
-
- Using RPN, you enter numbers first, followed by the operators. For
- example, to add 3 and 4, you would enter:
-
-
- 3 4 +
-
- (We'll show how these numbers are actually entered later in the section.)
- To add 1 and 2 and then multiply the result by 3, you would enter:
-
-
- 1 2 + 3 *
-
- MINICAL uses double-precision numbers, so you can enter any type of
- integer or floating-point numeric values. Results are displayed using as
- many as 16 digits. For example, to divide 1.2 by -3.45, you would enter:
-
-
- 1.2 -3.45 /
-
- and the display would read:
-
-
- Result... -.3478260869565217
-
- NOTE: Because a computer keyboard does not have x and ÷ keys, an asterisk
- (*) is used for multiplication and a forward slash (/) is used for
- division.
-
- By the way, MINICAL uses a structure called a stack to hold the numbers
- and the operators while performing the calculations. (Technically, the
- structure used in MINICAL only mimics a traditional stack, but for
- discussion purposes it can be thought of as a stack.) A stack is a
- sequential series of memory locations set aside to hold a number of
- separate items──in this case, the numbers and operators provided by the
- user. RPN is used for specifying numbers and operators primarily because
- of the existence of the stack──the RPN syntax is ideal for stack-based
- calculations. The alternative method, parsing, involves "reading" the
- equation entered by the user, rearranging and selecting the separate
- elements, and acting on them. This latter method involves much more
- coding.
-
- The stack in MINICAL can hold as many as 20 values plus the associated
- operators. You can enter numbers as explained above, or you can enter all
- numbers and then the operators. For example, to add the numbers 1 through
- 5, you can enter either of these two command lines:
-
-
- 1 2 + 3 + 4 + 5 +
- 1 2 3 4 5 + + + +
-
- The MINIMATH Module
-
- This project consists of two parts: the MINIMATH module and the MINICAL
- module. Let's begin with MINIMATH.
-
- If you haven't done so yet, at the system prompt type QB and press Enter
- to start QuickBASIC. Type in the title block on the following page.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MINIMATH **
- ' ** Type: Toolbox **
- ' ** Module: MINIMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Collection of math subprograms for the MINICAL
- ' program.
- ──────────────────────────────────────────────────────────────────────────
-
- At this point, it's convenient to tell QuickBASIC this module's name. Pull
- down the File menu and choose Save As. Type the filename MINIMATH, and
- press the Enter key or move your mouse pointer to the OK box and click the
- left mouse button. The file is then saved to disk, and you're ready to
- continue entering more of the program. Note that if you omit the .BAS
- extension, as you did here, QuickBASIC automatically adds it for you.
-
- This first module will be made up of the five subprograms that perform the
- math functions. First, let's create the Add subprogram. Pull down the Edit
- menu and choose New SUB. When you're asked for the name of the subprogram,
- respond with Add. QuickBASIC then creates the first and last lines of your
- new subprogram:
-
-
- SUB Add
- END SUB
-
- Note that QuickBASIC also adjusts the editing window so that only the Add
- subprogram is displayed, allowing you to concentrate on this subprogram
- only. (You'll greatly appreciate this feature later on, when your
- programming projects become larger.) The next step is to add comment
- information before the first line of the subprogram and to insert the
- "guts" of the subprogram between the two lines displayed by QuickBASIC.
-
- Start by adding comments. Move the cursor to the first character of the
- first line of the subprogram and press Enter. When you do, a dialog box
- appears with the message Blank lines not allowed before SUB/FUNCTION line.
- Is remark OK? Since a remark (comment) is what you want, choose OK.
- QuickBASIC then inserts a blank line preceded by a ' character for the
- comment. After you type the first comment line (taken from the lines on
- the following page) and press Enter, the dialog box appears again. Click
- OK and then type the next comment line.
-
- Use the lines below to build the Add subprogram. Note the locations of the
- SUB Add and END SUB lines, and note that you need to append items to the
- SUB Add line. Also note that some lines are indented: Although this
- indention is not required, it is good programming style to indent
- subordinate lines so that the program is easier to read and relationships
- between lines are visually apparent. When you're done, your Add subprogram
- should look exactly like this:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Add **
- ' ** Type: Subprogram **
- ' ** Module: MINIMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Performs addition for the MINICAL program.
- '
- SUB Add (stack#(), ptr%) STATIC
- ptr% = ptr% - 1
- IF ptr% THEN
- stack#(ptr%) = stack#(ptr%) + stack#(ptr% + 1)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
- You can save your work at any point. (It's a good idea to back up your
- work often to prevent losing your work in case of a power failure or other
- disaster.) Do so now by pulling down the File menu and choosing Save All.
-
- You're well on your way now! You will create and edit the other four math
- subprograms (shown on pages 11-12) in the same way.
-
- Here's a tip that can speed up the process. Notice that the initial
- comment lines for each of the five subprograms are nearly identical. So,
- instead of retyping each one, you'll copy the lines you typed in for the
- Add subprogram and paste them into the other subprograms. Let's do that
- now.
-
- First, set up the new subprograms. For the Subtract subprogram, choose
- New SUB from the Edit menu, enter the name Subtract, and press Enter.
- After the two lines of the Subtract subprogram are displayed, repeat the
- New SUB process for the Multiply, Divide, and SquareRoot subprograms.
- Be sure you type the subprogram names as shown here──each starts with a
- capital letter, and no space is allowed in the subprogram name SquareRoot.
-
- Next, make a copy of the comment lines in the Add subprogram. Pull down
- the View menu and choose SUBS. QuickBASIC displays a list of all
- subprogram names you entered. Here's where the power of QuickBASIC is
- really apparent: Using the SUBS command, you can jump to any subprogram
- for editing by simply selecting the name of the desired subprogram. You do
- this by double-clicking on the desired subprogram name with your mouse or
- by using the cursor movement keys followed by the Enter key. For now,
- choose Add.
-
- To copy the comment lines, move the cursor to the first character of the
- first comment line, and then (using the keyboard) hold down either Shift
- key and press the Down arrow key until all comment lines are highlighted;
- or (using the mouse) move the mouse pointer to the location of the cursor,
- hold down the left mouse button, and drag down until all comment lines are
- highlighted. Finally, choose Copy from the Edit menu to copy the
- highlighted lines to the Clipboard.
-
- Next, copy those lines into the four other subprograms. Choose SUBS from
- the View menu to again display a list of subprograms. Select Subtract,
- move the cursor to the first character of the first line, pull down the
- Edit menu, and choose Paste. The lines copied from the Add subprogram
- should appear. (If they don't or if you get a dialog box telling you that
- blank lines can't appear before a subprogram, go back to the Add
- subprogram and repeat the Edit-Copy process. Remember to copy only comment
- lines──those preceded by a ' character.)
-
- Select the remaining subprogram names in the same way, and repeat the
- Edit-Paste process. You don't have to repeat the Copy operation, because
- an item copied to the Clipboard stays there until something else is copied
- to the Clipboard or until you quit QuickBASIC. When you're done, go back
- to each subprogram. Edit the comment lines and enter the program lines as
- you did for the Add subprogram. Be sure to choose Save All from the File
- menu after completing each subprogram. Also, be sure to go back and review
- your work──the ability to view each subprogram separately using the SUBS
- option on the View menu makes this important task easier and your program
- clearer to read. Your results should match the four subprograms on the
- following two pages.
-
- NOTE: Don't forget to edit the comments! Remember──the comments you pasted
- in were the comments for the Add subprogram. You must change the name in
- each comment block and the information on the line below the block to
- reflect the subprogram the comments identify.
-
- The following is the Subtract subprogram:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Subtract **
- ' ** Type: Subprogram **
- ' ** Module: MINIMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Performs subtraction for the MINICAL program.
- '
- SUB Subtract (stack#(), ptr%) STATIC
- ptr% = ptr% - 1
- IF ptr% THEN
- stack#(ptr%) = stack#(ptr%) - stack#(ptr% + 1)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
- The following is the Multiply subprogram:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Multiply **
- ' ** Type: Subprogram **
- ' ** Module: MINIMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Performs multiplication for the MINICAL program.
- '
- SUB Multiply (stack#(), ptr%) STATIC
- ptr% = ptr% - 1
- IF ptr% THEN
- stack#(ptr%) = stack#(ptr%) * stack#(ptr% + 1)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
- The following is the Divide subprogram:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Divide **
- ' ** Type: Subprogram **
- ' ** Module: MINIMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Performs division for the MINICAL program.
- '
- SUB Divide (stack#(), ptr%) STATIC
- ptr% = ptr% - 1
- IF ptr% THEN
- stack#(ptr%) = stack#(ptr%) / stack#(ptr% + 1)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
- The following is the SquareRoot subprogram:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SquareRoot **
- ' ** Type: Subprogram **
- ' ** Module: MINIMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Determines square root for the MINICAL program.
- '
- SUB SquareRoot (stack#(), ptr%) STATIC
- stack#(ptr%) = SQR(stack#(ptr%))
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
- This completes the first part of the MINICAL program. The subprograms you
- created and saved as MINIMATH form the heart of MINICAL because they
- perform the actual calculations. The next part involves creating MINICAL
- itself. MINICAL performs the overhead work──taking the numbers the user
- wants to calculate, passing them to the appropriate subprograms in
- MINIMATH, and displaying the result.
-
- The MINICAL Module
-
- From here, you can proceed in one of two ways. Because both MINIMATH and
- MINICAL are small, you can build the MINICAL program entirely in memory by
- creating a second module named MINICAL. (You do this by choosing Create
- File from the File menu, accepting the default choice of Module, and then
- choosing OK.) Or you can turn MINIMATH into a Quick Library and load it
- with the QuickBASIC system so that it becomes an extension to the
- language. We'll use the second method to see how easy it is to use this
- advanced QuickBASIC feature.
-
- To create a Quick Library, pull down the Run menu and choose Make Library.
- You'll be asked to name the library. MINIMATH will be fine, because
- QuickBASIC automatically appends a default extension of .QLB for the Quick
- Library and .LIB for the normal library it also builds. After you type
- MINIMATH, choose Make Library. (You can ignore the other options in the
- dialog box for now.) When completed, QuickBASIC will have created two new
- files in the current directory: MINIMATH.QLB and MINIMATH.LIB.
-
- Now quit QuickBASIC so that you can restart it and load the new Quick
- Library with it. To do this, pull down the File menu and choose Exit. Then
- start QuickBASIC from the system prompt by entering:
-
-
- QB /L MINIMATH
-
- You'll see no obvious sign that anything is different, but a very exciting
- event has actually taken place! Your QuickBASIC has been extended. It's
- now more than it used to be. The subprograms in MINIMATH are part of the
- QuickBASIC language, ready to be used like many of the other QuickBASIC
- keywords. In fact, because you can optionally use the CALL keyword when
- calling subprograms, these new subprograms will appear much like new
- keywords in QuickBASIC.
-
- Proceed with the rest of the program now so that you can try out the new,
- extended QuickBASIC. Be sure QuickBASIC is loaded, as described earlier,
- with the MINIMATH Quick Library as part of the system. Then type in the
- following program, MINICAL.BAS:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MINICAL **
- ' ** Type: Program **
- ' ** Module: MINICAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
-
- ' Functions
- DECLARE FUNCTION NextParameter$ (cmd$)
-
- ' Subprograms
- DECLARE SUB Process (cmd$, stack#(), ptr%)
- DECLARE SUB DisplayStack (stack#(), ptr%)
- DECLARE SUB Add (stack#(), ptr%)
- DECLARE SUB Subtract (stack#(), ptr%)
- DECLARE SUB Multiply (stack#(), ptr%)
- DECLARE SUB Divide (stack#(), ptr%)
- DECLARE SUB SquareRoot (stack#(), ptr%)
-
- ' Get the command line
- cmd$ = COMMAND$
-
- ' Create a pseudo stack
- DIM stack#(1 TO 20)
- ptr% = 0
-
- ' Process each part of the command line
- DO UNTIL cmd$ = ""
- parm$ = NextParameter$(cmd$)
- Process parm$, stack#(), ptr%
- IF ptr% < 1 THEN
- PRINT "Not enough stack values"
- SYSTEM
- END IF
- LOOP
-
- ' Display results
- DisplayStack stack#(), ptr%
-
- ' All done
- END
- ──────────────────────────────────────────────────────────────────────────
-
- This is the main part of the MINICAL program, where all the action begins.
- Note the first two lines in the DO-LOOP structure, the ones that read
- parm$ = NextParameter$(cmd$) and Process parm$, stack#(), ptr%. The first
- line calls the user-defined function named NextParameter$, and the second
- line calls the user-defined subprogram named Process. (No, you haven't
- defined them yet. That's next on the list of tasks to do.) Notice that the
- keyword CALL was not used to call the Process subprogram. You can use CALL
- if desired, but there's no need to anymore. Because of the way QuickBASIC
- deals with subprograms, the Process subprogram that you'll create shortly
- will be more like part of the QuickBASIC system, rather than part of the
- program, because you can't list it or modify it while this portion of the
- program is on the screen. You also don't have to think about it or
- recompile it! Your creative energies are free to tackle the next higher
- level of the program's complexity.
-
- Once you've entered the main program's lines, it's again time to save this
- module to disk. Select Save As from the File menu and enter the filename
- MINICAL.
-
- You still have a few pieces of coding to do before you can try the
- program. To create the one function of this program, select New Function
- from the Edit menu. Type in the function name NextParameter$, and press
- the Enter key. Creating and editing functions are really no different from
- creating and editing subprograms. In fact, the only major difference
- between a function and a subprogram is that a function returns a value to
- be used in a calculation or assigned to a QuickBASIC variable. Subprograms
- return values only through passed variables. Follow the same steps you
- used to create the subprograms in MINIMATH to create the function
- NextParameter$:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: NextParameter$ **
- ' ** Type: Function **
- ' ** Module: MINICAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Extracts parameters from the front of the
- ' command line. Parameters are groups of any
- ' characters separated by spaces.
- '
- FUNCTION NextParameter$ (cmd$) STATIC
- parm$ = ""
- DO WHILE LEFT$(cmd$, 1) <> " " AND cmd$ <> ""
- parm$ = parm$ + LEFT$(cmd$, 1)
- cmd$ = MID$(cmd$, 2)
- LOOP
- DO WHILE LEFT$(cmd$, 1) = " " AND cmd$ <> ""
- cmd$ = MID$(cmd$, 2)
- LOOP
- NextParameter$ = parm$
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
- Now create and edit the following two subprograms as part of the MINICAL
- module.
-
- Create the subprogram DisplayStack:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DisplayStack **
- ' ** Type: Subprogram **
- ' ** Module: MINICAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Displays anything left on the stack when MINICAL
- ' finishes processing the command line.
- '
- SUB DisplayStack (stack#(), ptr%) STATIC
- PRINT
- IF ptr% > 1 THEN
- PRINT "Stack... ",
- ELSE
- PRINT "Result... ",
- END IF
- FOR i% = 1 TO ptr%
- PRINT stack#(i%),
- NEXT i%
- PRINT
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
- Next create the subprogram Process:
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Process **
- ' ** Type: Subprogram **
- ' ** Module: MINICAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Processes each command parameter for the MINICAL
- ' program.
- '
- SUB Process (parm$, stack#(), ptr%) STATIC
- SELECT CASE parm$
- CASE "+"
- Add stack#(), ptr%
- CASE "-"
- Subtract stack#(), ptr%
- CASE "*"
- Multiply stack#(), ptr%
- CASE "/"
- Divide stack#(), ptr%
- CASE "SQR"
- SquareRoot stack#(), ptr%
- CASE ELSE
- ptr% = ptr% + 1
- stack#(ptr%) = VAL(parm$)
- END SELECT
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
- Be sure you save your efforts on disk by selecting Save All from the File
- menu.
-
- You've done it! One last detail remains, however. This program reads the
- command line and assumes that numbers and operators were typed in
- following the name of the program at the system prompt. Fortunately,
- QuickBASIC provides a mechanism to let you type in a command line, even
- though you're currently going to be running the program in memory from the
- QuickBASIC system. From the Run menu select Modify COMMAND$. You'll be
- asked to enter a new command line. Enter this for the first try:
-
-
- 3 4 +
-
- Everything should be in place now, so try running the program. Select
- Start from the Run menu. If all is well, you'll see the following:
-
-
- Result... 7
-
- If all is not well, you'll probably find yourself staring at an error
- message from QuickBASIC, describing an error that's probably the indirect
- result of a typographical error. If so, double-check your typing, and
- rebuild the library if the problem was in the MINIMATH module.
-
- Once you get the program working, take a little time to try different
- command line parameters. See what happens if several numbers are placed on
- the stack but not enough operators are given to reduce the stack to a
- final result. For example, try entering:
-
-
- 3 4 5 6 7 + *
-
- Also, find out what happens if not enough numbers are on the stack. For
- example, enter:
-
-
- 3 4 + *
-
-
- Compiling and Running as an Executable (.EXE) Program
-
- Finally, to see how you can create programs that you can run from MS-DOS,
- select Make EXE File from the Run menu. You can create two types of .EXE
- files. The first type results in a smaller MINICAL.EXE file, but it
- requires access to the QuickBASIC file named BRUN40.EXE at runtime. The
- second type results in a larger MINICAL.EXE file that stands completely on
- its own. When you select Make EXE File from the Run menu, you are prompted
- to select the type of .EXE file you want to create. Try it both ways. Take
- a look at the resulting file sizes, and note that the BRUN40.EXE file must
- be accessible in the current directory or in a place defined by the MS-DOS
- PATH setting. (Your QuickBASIC manual discusses this subject in more
- detail.)
-
- Either way, running the MINICAL.EXE program from the system prompt uses
- the command line in the way that COMMAND$ expects. For example, to
- subtract 5 from 17, enter the following at the system prompt:
-
-
- MINICAL 17 5 -
-
- While building MINICAL, you've learned how easy it is to create toolboxes
- of your own or to edit existing toolboxes. Turn now to Part II of this
- book. Be sure to read the first section, which explains how to use the
- QuickBASIC toolboxes. Then choose a toolbox that interests you, and have
- fun.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PART 2 QUICKBASIC TOOLBOXES AND PROGRAMS
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter Three Using QuickBASIC Toolboxes
-
- The toolboxes in Part II cover a wide range of topics and are presented
- alphabetically by subject. Each is designed to be loaded and called by
- user-written application software. You can run the demo module that begins
- each toolbox to illustrate the routines within the toolbox, you can ignore
- the demo module and use the routines as they are written, or you can
- restructure the routines so that they meet your application requirements.
-
- The toolboxes and utility programs do not require any knowledge of
- previously presented toolboxes, so you can run them in any order. Try them
- all at least once, and review the code as you run them. You'll find unique
- techniques and programming concepts in most of the listings. You'll also
- find that these toolbox routines, along with your own creations, will be
- useful in your future programming projects.
-
- Many of the utility programs use command line input or the COMMAND$
- variable from within QuickBASIC to pass values or parameters to the
- program. Others (those using toolboxes from different programs) might
- require an associated .MAK file. A few programs require color and graphics
- capability, and others require a mouse. Check the comments at the
- beginning of each listing or Appendix A to determine environmental and
- running requirements for each toolbox and utility program.
-
-
- Special Requirements
-
- The following toolboxes require that the MIXED.QLB Quick Library be loaded
- into memory with QuickBASIC: BIOSCALL, CDEMO1, CDEMO2, COLORS,
- DOSCALLS, FILEINFO, MOUSGCRS, MOUSSUBS, MOUSTCRS, QBTREE, STDOUT,
- and WINDOWS. MIXED.QLB consists of a handful of subprograms and functions
- written in assembly language and in Microsoft QuickC. (The
- assembly-language and C source listings for MIXED.QLB are in Part III.)
-
- Although MIXED.QLB isn't required by all toolboxes in this book, it's a
- good idea to load it each time you start QuickBASIC to use the toolboxes
- in this book. Toolboxes that do not require its presence will not be
- affected if MIXED.QLB is loaded.
-
- Below are instructions for creating MIXED.QLB, which was written in
- Microsoft QuickC and assembly language to demonstrate how other languages
- can be used with QuickBASIC. It is beyond the scope of this book to
- explain in detail mixed-language programming concepts, so simply follow
- the steps presented here to create MIXED.QLB. In Part III of the book, you
- will have the opportunity to try some examples of mixed-language programs.
-
- Creating MIXED.QLB
-
- If you own Microsoft QuickC, the first step is to compile an object-code
- file for CTOOLS1.C and CTOOLS2.C.
-
- You can load the C source-code files from the companion disk if you have
- purchased it, or you can type them in yourself. You will find CTOOLS1.C
- on page 445, and CTOOLS2.C on page 462. Once you have these files, enter
- the following commands at the system prompt to compile the CTOOLS1.C and
- CTOOLS2.C source-code files to create object-code files:
-
-
- QCL /Ox /AM /Gs /c CTOOLS1.C
- QCL /Ox /AM /Gs /c CTOOLS2.C
-
- NOTE: If you don't have QuickC, you can still create MIXED.QLB. Compile
- the assembly-language source-code files as explained below. You will then
- be able to run all toolboxes in this book except CDEMO1 and CDEMO2.
-
- If you have version 5.0 or later of the Microsoft Macro Assembler, load
- the assembly-language source-code files from the companion disk or type
- them in. MOUSE.ASM is on page 437 and CASEMAP.ASM is on page 436. The
- third assembly-language file, INTRPT.ASM, is part of QuickBASIC itself and
- can be found on the disk that comes with the program. Then, enter the
- following commands at the system prompt to compile the source-code files
- into object-code files:
-
-
- MASM MOUSE;
- MASM CASEMAP;
- MASM INTRPT;
-
- If you have an earlier version of the Microsoft Macro Assembler, follow
- the guidelines in your QuickBASIC documentation to replace the .MODEL
- directives with appropriate statements.
-
- If you don't have the Microsoft Macro Assembler, you can use HEX2BIN (on
- pages 210 and 211) to convert the MOUSE.HEX, CASEMAP.HEX, and INTRPT.HEX
- files into object-code files. The hexadecimal character files are listed
- in Appendix D.
-
- Once you've created the object-code files, you can build the MIXED library
- files to use with QuickBASIC. (Note that two files will be created:
- MIXED.QLB and MIXED.LIB. MIXED.QLB will be loaded with the QuickBASIC
- program because it is needed by some toolboxes; MIXED.LIB will be used for
- creating stand-alone programs that can be executed directly from MS-DOS.)
- The following commands accomplish this task:
-
-
- LINK /Q INTRPT+MOUSE+CASEMAP+CTOOLS1+CTOOLS2,MIXED.QLB,,BQLB40.LIB;
- DEL MIXED.LIB
- LIB MIXED.LIB+INTRPT+MOUSE+CASEMAP+CTOOLS1+CTOOLS2;
-
- NOTE: If you don't have QuickC, remember that you cannot run CDEMO1 and
- CDEMO2; therefore, you must delete +CTOOLS1 and +CTOOLS2 from the above
- commands.
-
- If you have a problem, the cause might be that the necessary files can't
- be located. Try moving all the files and programs into the current
- directory, including the programs LINK.EXE and LIB.EXE; the QuickBASIC
- library file, BQLB40.LIB; and, if you have Quick C, MLIBCE.LIB.
-
- Finally, after the MIXED.QLB and MIXED.LIB files are successfully created,
- enter the following lines to create a file named Q.BAT:
-
-
- COPY CON Q.BAT
- QB /L MIXED.QLB
- ^Z
-
- NOTE: The ^Z is obtained by pressing F6 or Ctrl-Z.
-
- Using this batch file automates the loading process so that MIXED.QLB
- loads along with QuickBASIC. To use it, type Q and press the Enter key at
- the system prompt.
-
- Using a .MAK File
-
- Those toolboxes that consist of more than one module require a .MAK file.
- When you save a program consisting of more than one module, QuickBASIC
- automatically creates a .MAK file so that it knows where to locate each
- module the next time it loads the program. If the .MAK file is not
- available, or if you must create a new .MAK file, you must load each
- module from within QuickBASIC by selecting Load File from the File menu,
- selecting the module to load, and then repeating the process for each
- additional module. After loading all the modules, choose Save All from the
- File menu and QuickBASIC creates the new .MAK file. Appendix A lists all
- toolboxes and required .MAK files.
-
-
- QuickBASIC vs Executable Files
-
- You can run the demo modules and utility programs from within the
- QuickBASIC environment by selecting the applicable source-code file, or
- you can compile the code and create files to execute directly from MS-DOS.
- Source-code files are those with the .BAS file extension. Executable files
- are created from .BAS files from within the QuickBASIC environment and are
- saved with a .EXE file extension. All toolbox and utility programs on the
- companion diskettes are .BAS files. The steps necessary for loading and
- running the programs and toolboxes are simple.
-
- Running Programs from the QuickBASIC Environment
-
- Check your QuickBASIC manual, "Learning and Using Microsoft QuickBASIC,"
- for starting QuickBASIC on your system. When the program starts, you are
- ready to load and run a demo module or utility program. Using the
- keyboard, the steps are:
-
- 1. Press the Alt key and then F to display the File menu.
-
- 2. Press O to choose the Open Program command.
-
- 3. Select the demo module or program from the list of .BAS files shown.
- If the file is not shown, you must set the path to the drive and
- directory where the file resides. First, type the correct path in the
- File Name box and press Enter to display the .BAS files in that path.
- Then type the name of the file you want to load, or use the Tab key to
- move to the list box and use the arrow keys to select the filename you
- want and press Enter. Filenames are displayed in all lowercase,
- directory names in all uppercase. You can also select directory names,
- including the parent(..) directory, in the list box until the .BAS
- files you want are displayed.
-
- 4. If command line parameters are required for execution, press Alt and
- then R to pull down the Run menu, and then press C to choose the
- Modify COMMAND$ option. Type the value(s) or input parameter(s)
- separated by spaces in the dialog box provided, and press the Enter
- key. You are now ready to execute the program and can do so by
- pressing Alt-R again and then S (or in this case Enter because the
- option is already highlighted) to choose the Start option.
-
- NOTE: Each listing contains a USAGE line within the comments to let you
- know when user input is expected and in what format. Parameters might be
- other filenames, numeric values, alphanumeric characters, math functions,
- drive designators, paths to directories and subdirectories, or symbols.
- You can also find parameters in Appendix A.
-
- 5. If no command line parameters are required, simply press Alt-R and
- then S to start the selected module. (You can also press Shift-F5 to
- start.)
-
- These steps are basically the same for systems using a mouse device.
- Instead of pressing the Alt key, however, you move the mouse pointer to
- the desired menu names, menu options, and dialog box fields and press the
- left mouse button to make dialog box selections and execute menu commands.
-
- If you receive no response or the program doesn't seem to work correctly,
- look up the module in Appendix A and check that .MAK files, libraries
- (including MIXED.QLB), color graphics requirements, and so on are resident
- and that the paths to them are properly set.
-
- Running Programs as Executable Files
-
- Some of the utility programs, especially those expecting command line
- variable input, are more conveniently run as stand-alone executable files
- (.EXE). If you plan to develop commercial or public domain software, the
- .EXE format is usually preferable.
-
- Before you can run the toolboxes and utility programs directly from
- MS-DOS, you must first compile a .BAS file or files using a special option
- to create a .EXE file. Two options are available for compiling programs.
- The first option is to compile the source code into a stand-alone .EXE
- file that runs by itself when executed from MS-DOS. The file, however,
- will be quite large, even if it is a simple application or module. The
- second option is to create a .EXE file that requires another file,
- BRUN40.EXE, to be in the same drive and directory at runtime (when you
- execute the program). The resulting compiled program file will be much
- smaller, but BRUN40.EXE must always accompany the executable file.
-
- To create a stand-alone executable file from within QuickBASIC, follow the
- steps below. Refer to your QuickBASIC manual for instructions on how to
- create other .EXE files from within the QuickBASIC environment or from
- MS-DOS using BC.EXE.
-
- 1. Load the file using steps 1 through 3 above in "Running Programs from
- the QuickBASIC Environment."
-
- 2. Press Alt-R to display the Run Menu.
-
- 3. Press X (Make EXE File).
-
- 4. Press Alt-A to select the Stand-Alone .EXE File option. (This method
- produces a file with the same filename as the .BAS file but appends
- the .EXE file extension. To change the filename, type over the
- displayed name before pressing Alt-A.)
-
- 5. Press E to choose the Make EXE and Exit command.
-
- QuickBASIC then creates the executable file, the QuickBASIC program is
- terminated, and you return to the system prompt. To verify that the file
- exists, type DIR and press Enter, and look for that program's filename
- with a .EXE extension.
-
- To run the program as a stand-alone .EXE file, type the filename (without
- the .EXE extension) from the system prompt. Type any command line values
- or input parameters after the filename, with spaces between the filename
- and parameters. The program or toolbox module begins executing as soon as
- you press the Enter key.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- ATTRIB
-
- The ATTRIB program generates a table showing combinations of text-mode
- character attributes, including all combinations of foreground and
- background colors. Only the blink attribute isn't demonstrated, but it is
- described at the head of the table. Use this program as a utility program.
- Compile it as a stand-alone executable program, and run it to decide what
- colors to use in your own programs.
-
- The sole purpose of the ATTRIB main program is to call the single
- subprogram, also named Attrib. Actually, the program has only enough
- supporting module-level code to demonstrate the subprogram.
-
- The Attrib subprogram may be called by other programs, either by loading
- the entire ATTRIB module into memory or by copying only the Attrib
- subprogram into another module. Refer to the MOUSTCRS program for an
- example.
-
-
- Program Module: ATTRIB
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ATTRIB **
- ' ** Type: Program **
- ' ** Module: ATTRIB.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Displays all combinations of text mode character
- ' attributes on the screen for review.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' .MAK FILE: (none)
- ' FUNCTIONS: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- DECLARE SUB Attrib ()
-
- ' Call the subprogram
- Attrib
-
- ' All done
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Attrib
-
- Creates the color attribute table on the screen for the ATTRIB module.
- Sixteen foreground and eight background color attributes are available in
- the default SCREEN 0 text mode, not counting the blink attribute for the
- foreground color. This subprogram displays all 128 combinations in a way
- that makes it easy to see which numbers result in which colors.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Attrib **
- ' ** Type: Subprogram **
- ' ** Module: ATTRIB.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Displays table of color attributes for text mode.
- '
- ' EXAMPLE OF USE: Attrib
- ' PARAMETERS: (none)
- ' VARIABLES: bgd% Background number for COLOR statement
- ' fgd% Foreground number for COLOR statement
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Attrib ()
- '
- SUB Attrib STATIC
- SCREEN 0
- CLS
- PRINT "Attributes for the COLOR statement in text mode (SCREEN 0)."
- PRINT "Add 16 to the foreground to cause the character to blink."
- FOR bgd% = 0 TO 7
- COLOR bgd% XOR 7, bgd%
- PRINT
- PRINT "Background%"; STR$(bgd%),
- PRINT "Foreground% ..."; SPACE$(41)
- FOR fgd% = 0 TO 15
- COLOR fgd%, bgd%
- PRINT STR$(fgd%); " ";
- NEXT fgd%
- NEXT bgd%
- COLOR 7, 0
- PRINT
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- BIN2HEX
-
- The BIN2HEX program is a utility that creates hexadecimal format files
- showing the contents of a given binary file. In this book, its most useful
- purpose is in displaying the contents of .OBJ files created by the
- Microsoft Macro Assembler. This enables you to create the necessary files
- for using the assembly-language routines in this book, even if you don't
- have the Macro Assembler.
-
- The program reads bytes of the input file using binary mode, converts each
- to a two-character hexadecimal string, and then formats the output by
- blocking the hexadecimal numbers into two groups of eight bytes per line.
- The output file can be listed or printed and can easily be transferred
- over a modem using conventional ASCII protocol.
-
- The HEX2BIN program performs the opposite function of this program,
- converting a hexadecimal listing back to a binary file.
-
- You will find several assembly-language subprograms in Part III of this
- book, and Microsoft provides two assembly listings with the QuickBASIC
- language. The suggested method of creating the .OBJ files from these
- listings is to use the Microsoft Macro Assembler, version 5.0. However, if
- you don't have the Macro Assembler, type in the hexadecimal files using
- the QuickBASIC Document editing capability, and then run the HEX2BIN
- program to convert each to the required .OBJ file.
-
- To use BIN2HEX, type the input filename and output filename on the command
- line when you run the program. For example, to convert MOUSE.OBJ to the
- hexadecimal listing MOUSE.HEX, enter these two command line parameters:
-
-
- MOUSE.OBJ MOUSE.HEX
-
- Be sure to use the full filename, including the extension. Separate
- filenames with spaces, as shown, or with commas if preferred.
-
- The BIN2HEX program was used to create the hexadecimal listings in
- Appendix D.
-
- Also review the HEX2BIN program for more information on using these
- routines.
-
-
- Program Module: BIN2HEX
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BIN2HEX **
- ' ** Type: Program **
- ' ** Module: BIN2HEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reads in any file and writes out a hexadecimal format file
- ' suitable for rebuilding the original file using the HEX2BIN
- ' program.
- '
- ' USAGE: BIN2HEX inFileName.ext outFileName.ext
- ' .MAK FILE: BIN2HEX.BAS
- ' PARSE.BAS
- ' PARAMETERS: inFileName Name of file to be duplicated in hexadeci
- ' format
- ' outFileName Name of hexadecimal format file to be cre
- ' VARIABLES: cmd$ Working copy of the command line
- ' inFile$ Name of input file
- ' outFile$ Name of output file
- ' byte$ Buffer for binary file access
- ' i& Index to each byte of input file
- ' h$ Pair of hexadecimal characters representi
- ' each byte
-
- DECLARE SUB ParseWord (a$, sep$, word$)
- ' Initialization
- CLS
- PRINT "BIN2HEX "; COMMAND$
- PRINT
-
- ' Get the input and output filenames from the command line
- cmd$ = COMMAND$
- ParseWord cmd$, " ,", inFile$
- ParseWord cmd$, " ,", outFile$
-
- ' Verify that both filenames were given
- IF outFile$ = "" THEN
- PRINT
- PRINT "Usage: BIN2HEX inFileName outFileName"
- SYSTEM
- END IF
-
- ' Open the input file
- OPEN inFile$ FOR BINARY AS #1 LEN = 1
- IF LOF(1) = 0 THEN
- CLOSE #1
- KILL inFile$
- PRINT
- PRINT "File not found - "; inFile$
- SYSTEM
- END IF
-
- ' Open the output file
- OPEN outFile$ FOR OUTPUT AS #2
-
- ' Process each byte of the file
- byte$ = SPACE$(1)
- FOR i& = 1 TO LOF(1)
- GET #1, , byte$
- h$ = RIGHT$("0" + HEX$(ASC(byte$)), 2)
- PRINT #2, h$; SPACE$(1);
- IF i& = LOF(1) THEN
- PRINT #2, ""
- ELSEIF i& MOD 16 = 0 THEN
- PRINT #2, ""
- ELSEIF i& MOD 8 = 0 THEN
- PRINT #2, "- ";
- END IF
- NEXT i&
-
- ' Clean up and quit
- CLOSE
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- BIOSCALL
-
- The BIOSCALL toolbox provides a collection of utility BIOS system calls.
-
- Several useful routines and data tables are in your computer's BIOS ROM
- (Basic Input/Output Services, Read Only Memory), ready to be tapped into
- by your QuickBASIC programs. This toolbox of routines provides a sampler
- of the most useful interrupt calls that return the information provided by
- BIOS. With QuickBASIC, it's easy to access the BIOS ROM.
-
- The module-level code provides demonstrations of the available subprograms
- when BIOSCALL is the designated main program. Later, load the BIOSCALL
- module along with any program you're developing when you need any
- information provided by the subprograms.
-
- Be aware that whenever you use the BIOSCALL toolbox, the mixed-language
- subprograms Interrupt and InterruptX must be accessible. Refer to "Using
- QuickBASIC Toolboxes" on page 21 for instructions on creating and loading
- the Quick Library MIXED.QLB with the QuickBASIC system.
-
- The Scroll subprogram, demonstrated first, prints a block of fifteen
- lines of uppercase characters on the screen. The first line is filled with
- As, the second with Bs, and so on. Each line is also printed in a
- different color scheme to make it easier to see exactly which characters
- are scrolled. The Scroll subprogram scrolls the rectangular area (from
- row 2, column 3 to row 6, column 16) up 3 lines. The attribute byte is set
- to green foreground on blue background, the same as the attribute byte at
- row 2, column 3. Study the displayed result, and notice that the lines
- moved up three rows and that the three blank lines show the blue
- background.
-
- The Equipment subprogram determines the computer equipment settings as
- maintained by BIOS. A short table is displayed, listing the availability
- or count of the printers, the game adapter, the serial I/O ports, the
- floppy disk drives, and the math coprocessor. Also displayed is the
- initial video state at boot-up time.
-
- VideoState, the next subprogram demonstrated, determines the current
- video state. The current video mode, number of text columns, and current
- active video page are displayed. Finally, GetShiftStates displays a table
- of the shift keys and shift states. This table is continuously updated
- until you press the Enter key, allowing you to try out the various shift
- keys. For example, press the left and right shift keys, singly or
- together, and notice how the state of each is monitored independently.
-
- In the demo module, two subprograms, PrintScreen and ReBoot, are
- commented out, as the actions they take are a bit extreme. To demo these
- subprograms, remove the apostrophes in front of these statements, which
- you'll find near the end of the module-level code. Don't forget that once
- you reboot, everything currently in memory is erased, and you'll be
- starting fresh.
-
- For more information on the available BIOS calls, refer to the technical
- reference manual for your computer.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- BIOSCALL.BAS Demo module
- Equipment Sub Equipment/hardware information
- GetShiftStates Sub Shift key states
- PrintScreen Sub Screen dump
- ReBoot Sub System reboot
- Scroll Sub Moves text in designated area of screen
- VideoState Sub Mode, col, and page display of current
- state
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: BIOSCALL
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BIOSCALL **
- ' ** Type: Toolbox **
- ' ** Module: BIOSCALL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates several interrupt calls to the ROM BIOS.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: MIXED.QLB/.LIB
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: i% Loop index for creating lines to scroll
- ' equip Structure of type EquipmentType
- ' mode% Video mode returned by VideoState
- ' columns% Video columns returned by VideoState
- ' page% Video page returned by VideoState
- ' shift Structure of type ShiftType
-
-
- ' Constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Declare the Type structures
- TYPE RegType
- ax AS INTEGER
- bx AS INTEGER
- cx AS INTEGER
- dx AS INTEGER
- Bp AS INTEGER
- si AS INTEGER
- di AS INTEGER
- flags AS INTEGER
- END TYPE
-
- TYPE RegTypeX
- ax AS INTEGER
- bx AS INTEGER
- cx AS INTEGER
- dx AS INTEGER
- Bp AS INTEGER
- si AS INTEGER
- di AS INTEGER
- flags AS INTEGER
- ds AS INTEGER
- es AS INTEGER
- END TYPE
-
- TYPE EquipmentType
- printers AS INTEGER
- gameAdapter AS INTEGER
- serial AS INTEGER
- floppies AS INTEGER
- initialVideo AS INTEGER
- coprocessor AS INTEGER
- END TYPE
-
- TYPE ShiftType
- right AS INTEGER
- left AS INTEGER
- ctrl AS INTEGER
- alt AS INTEGER
- scrollLockState AS INTEGER
- numLockState AS INTEGER
- capsLockState AS INTEGER
- insertState AS INTEGER
- END TYPE
-
- DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegType)
- DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegTypeX)
- DECLARE SUB PrintScreen ()
- DECLARE SUB Scroll (row1%, col1%, row2%, col2%, lines%, attribute%)
- DECLARE SUB Equipment (equip AS EquipmentType)
- DECLARE SUB VideoState (mode%, columns%, page%)
- DECLARE SUB GetShiftStates (shift AS ShiftType)
- DECLARE SUB ReBoot ()
-
- ' Demonstrate the Scroll subprogram
- CLS
- FOR i% = 1 TO 15
- COLOR i%, i% - 1
- PRINT STRING$(25, i% + 64)
- NEXT i%
- COLOR 7, 0
- PRINT
- PRINT "Press <Enter> to scroll part of the screen"
- DO
- LOOP UNTIL INKEY$ = CHR$(13)
- Scroll 2, 3, 6, 16, 3, SCREEN(2, 3, 1)
-
- ' Wait for user before continuing
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
- CLS
-
- ' Determine the equipment information
- DIM equip AS EquipmentType
- Equipment equip
- PRINT "Printers:", equip.printers
- PRINT "Game adapter:", equip.gameAdapter
- PRINT "Serial IO:", equip.serial
- PRINT "Floppies:", equip.floppies
- PRINT "Video:", equip.initialVideo
- PRINT "Coprocessor:", equip.coprocessor
-
- ' Determine the current video state
- PRINT
- VideoState mode%, columns%, page%
- PRINT "Video mode:", mode%
- PRINT "Text columns:", columns%
- PRINT "Video page:", page%
-
- ' Wait for user before continuing
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' Demonstrate the shift key states
- CLS
- PRINT "(Press shift keys, then <Enter> to continue...)"
- DIM shift AS ShiftType
- DO
- LOCATE 4, 1
- PRINT "Shift states:"
- GetShiftStates shift
- PRINT
- PRINT "Left shift:", shift.left
- PRINT "Right shift:", shift.right
- PRINT "Ctrl:", shift.ctrl
- PRINT "Alt:", shift.alt
- PRINT "Scroll Lock:", shift.scrollLockState
- PRINT "Num Lock:", shift.numLockState
- PRINT "Caps Lock:", shift.capsLockState
- PRINT "Insert:", shift.insertState
- LOOP UNTIL INKEY$ = CHR$(13)
-
- ' Uncomment the following line to cause a screen dump to printer....
- ' PrintScreen
-
- ' Uncomment the following line only if you want to reboot....
- ' ReBoot
-
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Equipment
-
- Returns information about the available computer hardware by calling the
- BIOS service at interrupt 11H, which returns bit patterns indicating the
- equipment configuration. The definition of the data structure named
- EquipmentType lists the items that this call can determine.
-
- This subprogram allows your program to decide how to handle input and
- output chores. As one example, the user can be prompted to Remove the
- first disk and insert the second or to Insert the second disk in drive B,
- depending on whether the computer has one or two floppy disk drives
- available.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Equipment **
- ' ** Type: Subprogram **
- ' ** Module: BIOSCALL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns equipment configuration information from BIOS.
- '
- ' EXAMPLE OF USE: Equipment equip
- ' PARAMETERS: equip Structure of type EquipmentType
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' Bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' TYPE EquipmentType
- ' printers AS INTEGER
- ' gameAdapter AS INTEGER
- ' serial AS INTEGER
- ' floppies AS INTEGER
- ' initialVideo AS INTEGER
- ' coprocessor AS INTEGER
- ' END TYPE
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegType
- ' DECLARE SUB Equipment (equip AS EquipmentType)
- '
- SUB Equipment (equip AS EquipmentType) STATIC
- DIM reg AS RegType
- Interrupt &H11, reg, reg
- equip.printers = (reg.ax AND &HC000&) \ 16384
- equip.gameAdapter = (reg.ax AND &H1000) \ 4096
- equip.serial = (reg.ax AND &HE00) \ 512
- equip.floppies = (reg.ax AND &HC0) \ 64 + 1
- equip.initialVideo = (reg.ax AND &H30) \ 16
- equip.coprocessor = (reg.ax AND 2) \ 2
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: GetShiftStates
-
- Returns the state of each shift key at the moment the subprogram is called
- and the current shift key states.
-
- The left Shift, right Shift, Ctrl, and Alt keys return a 1 in the
- appropriate structure variables if they are pressed at the moment this
- subprogram is called. If not pressed, a 0 is returned instead.
-
- This subprogram can also monitor the four shift states. If active, the
- Scroll Lock, Num Lock, Caps Lock, and Insert states return a value of 1 in
- the appropriate variable. If your keyboard has lights indicating the
- current states of these shift keys, this subprogram returns a 1 whenever a
- light is on and a 0 when the light is off.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetShiftStates **
- ' ** Type: Subprogram **
- ' ** Module: BIOSCALL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns state of the various shift keys.
- '
- ' EXAMPLE OF USE: GetShiftStates shift
- ' PARAMETERS: shift Structure of type ShiftType
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' Bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' TYPE ShiftType
- ' right AS INTEGER
- ' left AS INTEGER
- ' ctrl AS INTEGER
- ' alt AS INTEGER
- ' scrollLockState AS INTEGER
- ' numLockState AS INTEGER
- ' capsLockState AS INTEGER
- ' insertState AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB GetShiftStates (shift AS ShiftType)
- '
- SUB GetShiftStates (shift AS ShiftType) STATIC
- DIM reg AS RegType
- reg.ax = &H200
- Interrupt &H16, reg, reg
- shift.right = reg.ax AND 1
- shift.left = (reg.ax AND 2) \ 2
- shift.ctrl = (reg.ax AND 4) \ 4
- shift.alt = (reg.ax AND 8) \ 8
- shift.scrollLockState = (reg.ax AND 16) \ 16
- shift.numLockState = (reg.ax AND 32) \ 32
- shift.capsLockState = (reg.ax AND 64) \ 64
- shift.insertState = (reg.ax AND 128) \ 128
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: PrintScreen
-
- Performs exactly the same screen-to-printer dump that occurs when the
- Shift-Print Screen keys are pressed.
-
- Whenever you press the Shift-Print Screen keys, the operating system
- performs an interrupt 5 to activate the BIOS-level code for performing the
- screen dump. With the PrintScreen subprogram, you can program such a
- screen dump at any point in the operation of a running program without
- requiring user intervention.
-
- Because the screen dump BIOS routine is interrupt driven, any changes to
- the screen dump code are automatically taken into account. For example, if
- your computer loads and patches in an improved version of the screen dump
- at boot-up time, this subprogram activates the new routine with no
- problem. That's one of the nice features of the interrupt mechanism
- provided by the 8086 family of computers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: PrintScreen **
- ' ** Type: Subprogram **
- ' ** Module: BIOSCALL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Activates interrupt 5 to cause a dump of the
- ' screen's contents to the printer.
- '
- ' EXAMPLE OF USE: PrintScreen
- ' PARAMETERS: (none)
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' Bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB PrintScreen ()
- '
- SUB PrintScreen STATIC
- DIM reg AS RegType
- Interrupt 5, reg, reg
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ReBoot
-
- Causes the system to reboot. Depending on the computer and its
- configuration, this reboot won't always work perfectly. Be sure to test
- the subprogram carefully for your specific circumstances if you plan to
- use it on a routine basis.
-
- Perhaps the best and safest use for this subprogram is as an escape route
- for unauthorized access to software, because rebooting can frustrate
- attempts to overcome copy protection schemes. For example, try rebooting
- after a user fails a password check for the third time or if an
- unauthorized copy of a program is detected.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ReBoot **
- ' ** Type: Subprogram **
- ' ** Module: BIOSCALL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Causes the computer to reboot.
- '
- ' EXAMPLE OF USE: ReBoot
- ' PARAMETERS: (none)
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' Bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB ReBoot ()
- '
- SUB ReBoot STATIC
- DIM reg AS RegType
- Interrupt &H19, reg, reg
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Scroll
-
- Provides a quick scroll of text lines in a rectangular area of the
- display. The BIOS video interrupt 10H is set up to scroll. You place the
- correct parameters in the processor registers, and the BIOS code does the
- rest.
-
- Six parameters are passed to this subprogram. The first four define the
- upper left and lower right corners of the area to be scrolled. These
- coordinates refer to text-mode character locations, with the upper left
- corner of the screen defined as row 1, column 1. The lower right corner of
- the screen is defined as row 25, column 80 for 80-column text mode, or row
- 25, column 40 for 40-column text mode.
-
- The last two parameters provide the line count and the color attribute. If
- the line count is a positive number, the lines scroll up by the indicated
- number of rows, leaving blank lines at the bottom of the scrolled area. If
- the line count is negative, the lines scroll down. The blank lines are
- filled with space characters, and the color attribute is set by the
- attribute byte passed in the sixth parameter.
-
- Usually this subprogram is used to scroll text one line at a time, such as
- when displaying the contents of a long file using the MS-DOS TYPE command.
- A handy feature is the subprogram's ability to completely clear any or all
- of the screen, setting the background color at the same time. To do this,
- pass a line count of 0. The BIOS routine will fill the entire rectangular
- area with spaces, much faster than if you were to PRINT the same number of
- space strings.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Scroll **
- ' ** Type: Subprogram **
- ' ** Module: BIOSCALL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Scrolls the screen in the rectangular area defined
- ' by the row and col parameters. Positive line count
- ' moves the lines up, leaving blank lines at bottom;
- ' negative line count moves the lines down.
- '
- ' EXAMPLE OF USE: Scroll row1%, col1%, row2%, col2%, lines%, attr%
- ' PARAMETERS: row1% Upper left character row defining rectangular
- ' scroll area
- ' col1 Upper left character column defining rectangu
- ' scroll area
- ' row2% Lower right character row defining rectangula
- ' scroll area
- ' col2% Lower right character column defining
- ' rectangular scroll area
- ' lines% Number of character lines to scroll
- ' attr% Color attribute byte to be used in new text
- ' lines scrolled onto the screen
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' Bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB Scroll (row1%, col1%, row2%, col2%, lines%, attribute%
- '
- SUB Scroll (row1%, col1%, row2%, col2%, lines%, attribute%) STATIC
- DIM reg AS RegType
- IF lines% > 0 THEN
- reg.ax = &H600 + lines% MOD 256
- ELSE
- reg.ax = &H700 + ABS(lines%) MOD 256
- END IF
- reg.bx = (attribute% * 256&) AND &HFF00
- reg.cx = (row1% - 1) * 256 + col1% - 1
- reg.dx = (row2% - 1) * 256 + col2% - 1
- Interrupt &H10, reg, reg
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: VideoState
-
- Returns the current mode, the number of columns, and the page of the
- display.
-
- This subprogram returns information about the current video mode. The
- mode% parameter returned by the ROM BIOS is different from the number used
- in the SCREEN statement to set a video mode. The two parameters do
- correlate, however, and the following table provides a useful comparison:
-
- SCREEN Mode WIDTH Mode% (from VideoState)
- ──────────────────────────────────────────────────────────────────────────
- 0 40 1
- 0 80 3
- 1 40 4
- 2 80 6
- 7 40 13
- 8 80 14
- 9 80 16
- 10 80 15
- 11 80 17
- 12 80 18
- 13 40 19
- ──────────────────────────────────────────────────────────────────────────
-
- The column% parameter is always 40 or 80, depending on the current SCREEN
- and WIDTH settings.
-
- The page% parameter is the currently active page number as set by the
- SCREEN statement. The default is page 0, and the maximum active page
- number is a function of the current screen mode. See the SCREEN statement
- in your QuickBASIC documentation for more information about active and
- virtual pages as set by the SCREEN statement.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: VideoState **
- ' ** Type: Subprogram **
- ' ** Module: BIOSCALL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Determines the current video mode parameters.
- '
- ' EXAMPLE OF USE: VideoState mode%, columns%, page%
- ' PARAMETERS: mode% Current video mode
- ' columns% Current number of text columns
- ' page% Current active display page
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' Bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB VideoState (mode%, columns%, page%)
- '
- SUB VideoState (mode%, columns%, page%) STATIC
- DIM reg AS RegType
- reg.ax = &HF00
- Interrupt &H10, reg, reg
- mode% = reg.ax AND &HFF
- columns% = (CLNG(reg.ax) AND &HFF00) \ 256
- page% = (CLNG(reg.bx) AND &HFF00) \ 256
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- BITS
-
- The BITS toolbox provides four bit manipulation routines. The
- Bin2BinStr$ and BinStr2Bin% functions convert integer numbers to and
- from binary string representations. This action is similar to that of the
- QuickBASIC HEX$, OCT$, and VAL functions, except that the conversions deal
- with base 2 representations.
-
- The BitGet and BitPut subprograms let you store and retrieve single bits
- from any location in any string. Up to 32767 bits can be accessed in a
- single string, which results in a string of 4096 bytes. These subprograms
- would be useful for data acquisition and process control applications
- involving a large number of contact closures. The famous sieve of
- Eratosthenes for finding prime numbers is used to demonstrate these two
- subprograms. Prime numbers from 1 through 1000 are found and printed by
- keeping track of a string of bits, each representing an integer from 1
- through 1000.
-
- You can change the value of max% in this demonstration to find prime
- numbers up to about 10937. Larger values of max% will cause overflow, but
- by reprogramming the variables involved, you can probably find even bigger
- primes.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- BITS.BAS Demo module
- Bin2BinStr$ Func Integer to 16-character binary string
- BinStr2Bin% Func 16-character binary string to integer
- BitGet Sub Value from any bit position in a string
- BitPut Sub Sets or clears bit at location in a string
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: BITS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BITS **
- ' ** Type: Toolbox **
- ' ** Module: BITS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates the bit manipulation functions
- ' and subprograms.
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: max% Upper limit for the prime number generator
- ' b$ Bit string for finding prime numbers
- ' n% Loop index for sieve of Eratosthenes
- ' bit% Bit retrieved from b$
- ' i% Bit loop index
- ' q$ The double quote character
-
- DECLARE FUNCTION BinStr2Bin% (b$)
- DECLARE FUNCTION Bin2BinStr$ (b%)
-
- ' Subprograms
- DECLARE SUB BitGet (a$, bitIndex%, bit%)
- DECLARE SUB BitPut (b$, bitIndex%, bit%)
-
- ' Prime numbers less than max%, using bit fields in B$
- CLS
- max% = 1000
- PRINT "Primes up to"; max%; "using BitGet and BitPut for sieve..."
- PRINT
- PRINT 1; 2;
- b$ = STRING$(max% \ 8 + 1, 0)
- FOR n% = 3 TO max% STEP 2
- BitGet b$, n%, bit%
- IF bit% = 0 THEN
- PRINT n%;
- FOR i% = 3 * n% TO max% STEP n% + n%
- BitPut b$, i%, 1
- NEXT i%
- END IF
- NEXT n%
- PRINT
-
- ' Demonstration of the Bin2BinStr$ function
- PRINT
- PRINT "Bin2BinStr$(12345) = "; Bin2BinStr$(12345)
-
- ' Demonstration of the BinStr2Bin% function
- PRINT
- q$ = CHR$(34)
- PRINT "BinStr2Bin%("; q$; "1001011"; q$; ") = ";
- PRINT BinStr2Bin%("1001011")
-
- ' That's all
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Bin2BinStr$
-
- Returns a 16-character binary representation of an integer value. This
- function is similar to QuickBASIC's HEX$ and OCT$ functions, except that
- the conversion base is 2 instead of 16 or 8, and that 16 characters are
- always returned. For example, Bin2BinStr$(7) returns 0000000000000111, and
- Bin2BinStr$(-1) returns 1111111111111111.
-
- You can easily remove leading zeros in the 16-character string by using
- the LtrimSet$ function, as shown in the STRINGS module:
-
-
- bin$ = LtrimSet$(bin$, "0")
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Bin2BinStr$ **
- ' ** Type: Function **
- ' ** Module: BITS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string of sixteen "0" and "1" characters
- ' that represent the binary value of b%.
- '
- ' EXAMPLE OF USE: PRINT Bin2BinStr$(b%)
- ' PARAMETERS: b% Integer number
- ' VARIABLES: t$ Working string space for forming
- binary string
- ' b% Integer number
- ' mask% Bit isolation mask
- ' i% Looping index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Bin2BinStr$ (b%)
- '
- FUNCTION Bin2BinStr$ (b%) STATIC
- t$ = STRING$(16, "0")
- IF b% THEN
- IF b% < 0 THEN
- MID$(t$, 1, 1) = "1"
- END IF
- mask% = &H4000
- FOR i% = 2 TO 16
- IF b% AND mask% THEN
- MID$(t$, i%, 1) = "1"
- END IF
- mask% = mask% \ 2
- NEXT i%
- END IF
- Bin2BinStr$ = t$
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: BinStr2Bin%
-
- Returns the integer represented by a string of up to 16 0s and 1s. For
- example, BinStr2Bin%("111") returns 7; BinStr2Bin%("000101") returns 5.
-
- If the string has more than 16 characters, only the rightmost 16 are used.
- Any character other than 1 is treated as 0.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BinStr2Bin% **
- ' ** Type: Function **
- ' ** Module: BITS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the integer represented by a string of up
- ' to 16 "0" and "1" characters.
- '
- ' EXAMPLE OF USE: PRINT BinStr2Bin%(b$)
- ' PARAMETERS: b$ Binary representation string
- ' VARIABLES: bin% Working variable for finding value
- ' t$ Working copy of b$
- ' mask% Bit mask for forming value
- ' i% Looping index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION BinStr2Bin% (b$)
- '
- FUNCTION BinStr2Bin% (b$) STATIC
- bin% = 0
- t$ = RIGHT$(STRING$(16, "0") + b$, 16)
- IF LEFT$(t$, 1) = "1" THEN
- bin% = &H8000
- END IF
- mask% = &H4000
- FOR i% = 2 TO 16
- IF MID$(t$, i%, 1) = "1" THEN
- bin% = bin% OR mask%
- END IF
- mask% = mask% \ 2
- NEXT i%
- BinStr2Bin% = bin%
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: BitGet
-
- Returns a bit value extracted from any bit position in a string. The bits
- are numbered consecutively, starting with bit 1 in the most significant
- bit position of the first byte of the string. Bit 8 is the least
- significant bit of this same byte, bit 9 is the most significant bit of
- the second byte, and so on. This subprogram can access up to 32767 bits,
- in which case the string must be 4096 bytes in length. For example:
-
-
-
- a$ = "A B C" 0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1
-
- BitGet (a$, 17, bit%) ... bit% = 0
- BitGet (a$, 18, bit%) ... bit% = 1
-
- The BitPut subprogram lets you set the bits in a string as desired.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BitGet **
- ' ** Type: Subprogram **
- ' ** Module: BITS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Extracts the bit at bitIndex% into a$ and returns
- ' either 0 or 1 in bit%. The value of bitIndex%
- ' can range from 1 to 8 * LEN(a$).
- '
- ' EXAMPLE OF USE: BitGet a$, bitIndex%, bit%
- ' PARAMETERS: a$ String where bit is stored
- ' bitIndex% Bit position in string
- ' bit% Extracted bit value, 0 or 1
- ' VARIABLES: byte% Byte location in string of the bit
- ' mask% Bit isolation mask for given bit
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB BitGet (a$, bitIndex%, bit%)
- '
- SUB BitGet (a$, bitIndex%, bit%) STATIC
- byte% = (bitIndex% - 1) \ 8 + 1
- SELECT CASE bitIndex% MOD 8
- CASE 1
- mask% = 128
- CASE 2
- mask% = 64
- CASE 3
- mask% = 32
- CASE 4
- mask% = 16
- CASE 5
- mask% = 8
- CASE 6
- mask% = 4
- CASE 7
- mask% = 2
- CASE 0
- mask% = 1
- END SELECT
- IF ASC(MID$(a$, byte%, 1)) AND mask% THEN
- bit% = 1
- ELSE
- bit% = 0
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: BitPut
-
- Sets or clears a single bit at any bit location in a string. The string
- can be up to 4096 bytes in length, allowing access of up to 32767 bits.
- Bits are numbered from left to right; the most significant bit of the
- first byte is bit 1, the least significant bit of the first byte is bit 8,
- the most significant bit of the second byte is bit 9, and so on. You can
- use the BitGet subprogram to get the bit values from the string as
- necessary. To initialize a string to all zeros or ones, use the STRING$
- function. For example, STRING$(4096, 0) returns a string of 32767 cleared
- bits, and STRING$(4096, 255) returns a string of 32767 set bits.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BitPut **
- ' ** Type: Subprogram **
- ' ** Module: BITS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' If bit% is non-zero, then the bit at bitIndex% into
- ' a$ is set to 1; otherwise, it's set to 0. The value
- ' of bitIndex% can range from 1 to 8 * LEN(a$).
- '
- ' EXAMPLE OF USE: BitPut a$, bitIndex%, bit%
- ' PARAMETERS: a$ String containing the bits
- ' bitIndex% Index to the bit of concern
- ' bit% Value of bit (1 to set, 0 to clear)
- ' VARIABLES: bytePtr% Pointer to the byte position in the string
- ' mask% Bit isolation mask
- ' byteNow% Current numeric value of string byte
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB BitPut (b$, bitIndex%, bit%)
- '
- SUB BitPut (a$, bitIndex%, bit%) STATIC
- bytePtr% = bitIndex% \ 8 + 1
- SELECT CASE bitIndex% MOD 8
- CASE 1
- mask% = 128
- CASE 2
- mask% = 64
- CASE 3
- mask% = 32
- CASE 4
- mask% = 16
- CASE 5
- mask% = 8
- CASE 6
- mask% = 4
- CASE 7
- mask% = 2
- CASE 0
- mask% = 1
- bytePtr% = bytePtr% - 1
- END SELECT
- byteNow% = ASC(MID$(a$, bytePtr%, 1))
- IF byteNow% AND mask% THEN
- IF bit% = 0 THEN
- MID$(a$, bytePtr%, 1) = CHR$(byteNow% XOR mask%)
- END IF
- ELSE
- IF bit% THEN
- MID$(a$, bytePtr%, 1) = CHR$(byteNow% XOR mask%)
- END IF
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- CALENDAR
-
- The CALENDAR toolbox is a collection of easy-to-use functions and
- subprograms for date and time conversions and calculations. See the
- MONTH program for an example of how this module can be loaded as a
- toolbox for use by another main program.
-
- Wherever possible, dates and times are passed in a string format identical
- to that used by the QuickBASIC DATE$ and TIME$ functions. This makes the
- required parameters easier to remember and makes it possible to define
- many of the routines as functions that would otherwise have to be defined
- as subprograms. For example, the Julian2Date$ function returns a date in
- the string format mentioned. Alternative approaches would require defining
- three functions (one for returning the year, one for the month, and one
- for the day) or defining a subprogram that returned the three numbers in
- the parameter list. Returning dates in this string format also eliminates
- output numeric formatting because the string is ready to be printed as is.
-
- The Julian day number is an astronomical convention that allows dates to
- be cataloged by a single, large integer. A useful feature of the Julian
- day number is that a simple subtraction can calculate the number of days
- between any two dates. Leap years and the strange pattern of days in the
- various months make this calculation difficult when dealing with the usual
- month, day, and year numbers. The Date2Julian& and Julian2Date$
- conversion functions take care of all the details for you, making calendar
- calculations a breeze. Other functions return the day of the week, day of
- the year, day of the century, name of each month, and other related
- details──just about everything you ever wanted to know, but were afraid to
- ask, about dates and time.
-
- The calculations are usually accurate for dates from 1583 to the
- indefinite future, although some functions generate errors for dates
- between 1583 and 1599 if the calculations involve earlier dates. For
- example, consider how the DayOfTheCentury& function would attempt to
- calculate the day of the century for July 4, 1599. First, the function
- calculates the Julian day number for 07-04-1599 and then it attempts to
- subtract from that the Julian day number for the last day of the previous
- century. Because 12-31-1499 is earlier than 1583, the function will not
- work correctly.
-
- ╓┌─┌─────────────────────────────┌─────────────┌─────────────────────────────╖
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- CALENDAR.BAS Demo module
- CheckDate% Func Validates date with return of
- TRUE/FALSE
- Date2Day% Func Day of month number from date
- string
- Date2Julian& Func Julian day number for a given
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- Date2Julian& Func Julian day number for a given
- date
- Date2Month% Func Month number from date string
- Date2Year% Func Year number from date string
- DayOfTheCentury& Func Day of the given century
- DayOfTheWeek$ Func Name of day of the week for
- given date
- DayOfTheYear% Func Day of the year (1 through
- 366) for given date
- DaysBetweenDates& Func Number of days between two
- dates
- HMS2Time$ Func Time string for given hour,
- minute, and second
- Julian2Date$ Func Date string from given Julian
- day number
- MDY2Date$ Func Date string from given month,
- day, and year
- MonthName$ Func Name of month for a given date
- OneMonthCalendar Sub One-month calendar for given
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- OneMonthCalendar Sub One-month calendar for given
- date
- Second2Date$ Func Seconds from last of 1979 to
- date given
- Second2Time$ Func Time of day from seconds since
- last of 1979
- Time2Hour% Func Hour number from time string
- Time2Minute% Func Minute number from time string
- Time2Second% Func Seconds number from time
- string
- TimeDate2Second& Func Seconds from last of 1979 from
- date/time
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- Demo Module: CALENDAR
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CALENDAR **
- ' ** Type: Toolbox **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: month% Month for demonstration
- ' day% Day for demonstration
- ' year% Year for demonstration
- ' dat$ Date for demonstration
- ' j& Julian day number
- ' tim$ System time right now
- ' hour% Hour right now
- ' minute% Minute right now
- ' second% Second right now
- ' sec& Seconds since last second of 1979
-
-
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Functions
- DECLARE FUNCTION CheckDate% (dat$)
- DECLARE FUNCTION Date2Day% (dat$)
- DECLARE FUNCTION Date2Julian& (dat$)
- DECLARE FUNCTION Date2Month% (dat$)
- DECLARE FUNCTION Date2Year% (dat$)
- DECLARE FUNCTION DayOfTheCentury& (dat$)
- DECLARE FUNCTION DayOfTheWeek$ (dat$)
- DECLARE FUNCTION DayOfTheYear% (dat$)
- DECLARE FUNCTION DaysBetweenDates& (dat1$, dat2$)
- DECLARE FUNCTION HMS2Time$ (hour%, minute%, second%)
- DECLARE FUNCTION Julian2Date$ (julian&)
- DECLARE FUNCTION MDY2Date$ (month%, day%, year%)
- DECLARE FUNCTION MonthName$ (dat$)
- DECLARE FUNCTION Second2Date$ (second&)
- DECLARE FUNCTION Second2Time$ (second&)
- DECLARE FUNCTION Time2Hour% (tim$)
- DECLARE FUNCTION Time2Minute% (tim$)
- DECLARE FUNCTION Time2Second% (tim$)
- DECLARE FUNCTION TimeDate2Second& (tim$, dat$)
-
- ' Subprograms
- DECLARE SUB OneMonthCalendar (dat$, row%, col%)
-
- ' Let's choose the fourth of July for the demonstration
- CLS
- PRINT "All about the fourth of July for this year..."
- month% = 7
- day% = 4
- year% = Date2Year%(DATE$)
-
- ' Demonstrate the conversion to dat$
- PRINT
- dat$ = MDY2Date$(month%, day%, year%)
- PRINT "QuickBASIC string format for this date is "; dat$
-
- ' Check the validity of this date
- IF CheckDate%(dat$) = FALSE THEN
- PRINT "The date you entered is faulty... " + dat$
- SYSTEM
- END IF
-
- ' Day of the week and name of the month
- PRINT "The day of the week is "; DayOfTheWeek$(dat$); "."
-
- ' Astronomical Julian day number
- j& = Date2Julian&(dat$)
- PRINT "The Julian day number is"; j&
-
- ' Conversion of Julian number to date
- PRINT "Date for the given Julian number is "; Julian2Date$(j&); "."
-
- ' Convert the date string to numbers
- PRINT "The month, day, and year numbers are ";
- PRINT Date2Month%(dat$); ","; Date2Day%(dat$); ","; Date2Year%(dat$)
-
- ' The month name
- PRINT "The month name is "; MonthName$(dat$)
-
- ' Day of the year
- PRINT "The day of the year is"; DayOfTheYear%(dat$)
-
- ' Day of the century
- PRINT "The day of the century is"; DayOfTheCentury&(dat$)
-
- ' Days from right now
- IF Date2Julian&(dat$) < Date2Julian&(DATE$) THEN
- PRINT "That was"; DaysBetweenDates&(dat$, DATE$); "days ago."
- ELSEIF Date2Julian&(dat$) > Date2Julian&(DATE$) THEN
- PRINT "That is"; DaysBetweenDates&(dat$, DATE$); "days from now."
- ELSE
- PRINT "The date you entered is today's date."
- END IF
-
- ' Print a one-month calendar
- OneMonthCalendar dat$, 14, 25
-
- ' Wait for user
- LOCATE 23, 1
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
- CLS
-
- ' Demonstrate extracting hour, minute, and second from tim$
- dat$ = DATE$
- tim$ = TIME$
- hour% = Time2Hour%(tim$)
- minute% = Time2Minute%(tim$)
- second% = Time2Second%(tim$)
- PRINT "The date today... "; dat$
- PRINT "The time now ... "; tim$
- PRINT "The hour, minute, and second numbers are ";
- PRINT hour%; ","; minute%; ","; second%
-
- ' Now put it all back together again
- PRINT "Time string created from hour, minute, and second is ";
- PRINT HMS2Time$(hour%, minute%, second%)
-
- ' Seconds since end of 1979
- dat$ = DATE$
- PRINT "The number of seconds since the last second of 1979 is";
- sec& = TimeDate2Second&(tim$, dat$)
- PRINT sec&
- PRINT "From this number we can extract the date and time..."
- PRINT Second2Date$(sec&); " and "; Second2Time$(sec&); "."
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: CheckDate%
-
- Returns TRUE if date is valid or FALSE if date is faulty.
-
- Was February 29, 1726, a real date? The CheckDate% function quickly finds
- the answer to this question. If the date checks out as valid, a value of
- TRUE (non-zero) is returned. If the date is faulty, a value of FALSE (0)
- is returned.
-
- This function is useful in any program that prompts the user to enter a
- date. A quick check can be made of the entered date, and the user can be
- asked to repeat the input if the entered date is faulty.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CheckDate% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns TRUE if the given date represents a real
- ' date or FALSE if the date is in error.
- '
- ' EXAMPLE OF USE: test% = CheckDate%(dat$)
- ' PARAMETERS: dat$ Date to be checked
- ' VARIABLES: julian& Julian day number for the date
- ' test$ Date string for given Julian day number
- ' MODULE LEVEL
- ' DECLARATIONS: CONST FALSE = 0
- ' CONST TRUE = NOT FALSE
- '
- ' DECLARE FUNCTION CheckDate% (dat$)
- ' DECLARE FUNCTION Date2Julian& (dat$)
- ' DECLARE FUNCTION Julian2Date$ (julian&)
- '
- FUNCTION CheckDate% (dat$) STATIC
- julian& = Date2Julian&(dat$)
- test$ = Julian2Date$(julian&)
- IF dat$ = test$ THEN
- CheckDate% = TRUE
- ELSE
- CheckDate% = FALSE
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Date2Day%
-
- Extracts the day number from a date string that is in the standard format
- MM-DD-YYYY.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Date2Day% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the day number given a date in the
- ' QuickBASIC string format MM-DD-YYYY.
- '
- ' EXAMPLE OF USE: day% = Date2Day%(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Date2Day% (dat$)
- '
- FUNCTION Date2Day% (dat$) STATIC
- Date2Day% = VAL(MID$(dat$, 4, 2))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Date2Julian&
-
- Returns the Julian day number for a given date. This function and the
- related function Julian2Date$ are at the heart of many of the other
- functions in this toolbox. This function calculates the astronomical
- Julian day number for any date from January 1, 1583, into the indefinite
- future, accounting for leap years and century adjustments.
-
- The main advantage of converting dates to long integer numbers is in being
- able to easily calculate the number of days between dates and the day of
- the week for any date. Further, if you need to store a large number of
- dates in a disk file, storing them as four-byte, long integers is more
- efficient than storing them in the longer string format or as separate
- integers representing the month, day, and year.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Date2Julian& **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the astronomical Julian day number given a
- ' date in the QuickBASIC string format MM-DD-YYYY.
- '
- ' EXAMPLE OF USE: j& = Date2Julian&(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: month% Month number for given date
- ' day% Day number for given date
- ' year% Year number for given date
- ' ta& First term of the Julian day number calcula
- ' tb& Second term of the Julian day number calcul
- ' tc& Third term of the Julian day number calcula
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Date2Day% (dat$)
- ' DECLARE FUNCTION Date2Julian& (dat$)
- ' DECLARE FUNCTION Date2Month% (dat$)
- ' DECLARE FUNCTION Date2Year% (dat$)
- '
- FUNCTION Date2Julian& (dat$) STATIC
- month% = Date2Month%(dat$)
- day% = Date2Day%(dat$)
- year% = Date2Year%(dat$)
- IF year% < 1583 THEN
- PRINT "Date2Julian: Year is less than 1583"
- SYSTEM
- END IF
- IF month% > 2 THEN
- month% = month% - 3
- ELSE
- month% = month% + 9
- year% = year% - 1
- END IF
- ta& = 146097 * (year% \ 100) \ 4
- tb& = 1461& * (year% MOD 100) \ 4
- tc& = (153 * month% + 2) \ 5 + day% + 1721119
- Date2Julian& = ta& + tb& + tc&
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Date2Month%
-
- Extracts the month number from a date string that is in the standard
- format MM-DD-YYYY.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Date2Month% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the month number given a date in the
- ' QuickBASIC string format MM-DD-YYYY.
- '
- ' EXAMPLE OF USE: month% = Date2Month%(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Date2Month% (dat$)
- '
- FUNCTION Date2Month% (dat$) STATIC
- Date2Month% = VAL(MID$(dat$, 1, 2))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Date2Year%
-
- Extracts the year number from a date string that is in the standard format
- MM-DD-YYYY.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Date2Year% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the year number given a date in the
- ' QuickBASIC string format MM-DD-YYYY.
- '
- ' EXAMPLE OF USE: year% = Date2Year%(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Date2Year% (dat$)
- '
- FUNCTION Date2Year% (dat$) STATIC
- Date2Year% = VAL(MID$(dat$, 7))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: DayOfTheCentury&
-
- Returns the day of the given century. Each century has more than 32767
- days, requiring this function to be declared as returning a long integer
- result.
-
- Dates before 01-01-1600 generate an error. See page 55 for an
- explanation.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DayOfTheCentury% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the number of the day of the century.
- '
- ' EXAMPLE OF USE: cDay& = DayOfTheCentury&(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: year% Year for given date
- ' dat1$ Date for last day of previous century
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION DayOfTheCentury& (dat$)
- '
- FUNCTION DayOfTheCentury& (dat$)
- year% = Date2Year%(dat$)
- dat1$ = MDY2Date$(12, 31, year% - (year% MOD 100) - 1)
- DayOfTheCentury& = DaysBetweenDates&(dat1$, dat$)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: DayOfTheWeek$
-
- Finds the name of the day of the week for any date. In displaying calendar
- calculation results, it's often desirable to be able to print the name of
- the day of the week. This function lets you conveniently do so.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DayOfTheWeek$ **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string stating the day of the week.
- ' Input is a date expressed in the QuickBASIC string
- ' format MM-DD-YYYY.
- '
- ' EXAMPLE OF USE: PRINT "The day of the week is "; DayOfTheWeek$(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION DayOfTheWeek$ (dat$)
- '
- FUNCTION DayOfTheWeek$ (dat$) STATIC
- SELECT CASE Date2Julian&(dat$) MOD 7
- CASE 0
- DayOfTheWeek$ = "Monday"
- CASE 1
- DayOfTheWeek$ = "Tuesday"
- CASE 2
- DayOfTheWeek$ = "Wednesday"
- CASE 3
- DayOfTheWeek$ = "Thursday"
- CASE 4
- DayOfTheWeek$ = "Friday"
- CASE 5
- DayOfTheWeek$ = "Saturday"
- CASE 6
- DayOfTheWeek$ = "Sunday"
- END SELECT
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: DayOfTheYear%
-
- Returns a number in the range 1 through 366, indicating the day of the
- year for the given date, by subtracting the Julian day number for the last
- day of the previous year from that of the given date. This calculation
- generates an error if the date is before January 1, 1584.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DayOfTheYear% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the number of the day of the year (1-366).
- '
- ' EXAMPLE OF USE: PRINT "The day of the year is"; DayOfTheYear%(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: dat1$ Date of last day of previous year
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION DayOfTheYear% (dat$)
- '
- FUNCTION DayOfTheYear% (dat$) STATIC
- dat1$ = MDY2Date$(12, 31, Date2Year%(dat$) - 1)
- DayOfTheYear% = DaysBetweenDates&(dat1$, dat$)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: DaysBetweenDates&
-
- Returns the number of days between two dates by subtracting the Julian day
- numbers of the dates. The absolute value of the difference is returned, so
- the first date can be earlier or later than the second. The number of days
- returned will always be a positive value.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DaysBetweenDates& **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the number of days between any two dates.
- '
- ' EXAMPLE OF USE: days& = DaysBetweenDates&(dat1$, dat2$)
- ' PARAMETERS: dat1$ First date
- ' dat2$ Second date
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION DaysBetweenDates& (dat1$, dat2$)
- '
- FUNCTION DaysBetweenDates& (dat1$, dat2$) STATIC
- DaysBetweenDates& = ABS(Date2Julian&(dat1$) - Date2Julian&(dat2$))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: HMS2Time$
-
- Given hour, minute, and second numbers, returns a time string, in the same
- format as the string returned by QuickBASIC's TIME$ function. For example,
- HMS2Time$(23, 59, 59) returns 23:59:59.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: HMS2Time$ **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the time in the QuickBASIC string format
- ' HH:MM:SS given hour%, minute%, and second%.
- '
- ' EXAMPLE OF USE: PRINT HMS2Time$(hour%, minute%, second%)
- ' PARAMETERS: hour% Hour number
- ' minute% Minutes number
- ' second% Seconds number
- ' VARIABLES: t$ Workspace for building the time string
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION HMS2Time$ (hour%, minute%, second%)
- '
- FUNCTION HMS2Time$ (hour%, minute%, second%) STATIC
- t$ = RIGHT$("0" + MID$(STR$(hour%), 2), 2) + ":"
- t$ = t$ + RIGHT$("0" + MID$(STR$(minute%), 2), 2) + ":"
- HMS2Time$ = t$ + RIGHT$("0" + MID$(STR$(second%), 2), 2)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Julian2Date$
-
- Converts a Julian day number to a date. The smallest long integer number
- that can be passed to this function without generating an error is
- 2299239, the Julian number for the date 01-01-1583.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Julian2Date$ **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a date in the QuickBASIC string format
- ' MM-DD-YYYY as calculated from a Julian day number.
- '
- ' EXAMPLE OF USE:
- ' PRINT "Date for the given Julian number is ";Julian2Date$(j&)
- ' PARAMETERS: j& Julian day number
- ' VARIABLES: x& Temporary calculation variable
- ' y& Temporary calculation variable
- ' d& Day number in long integer form
- ' m& Month number before adjustment
- ' month% Month number
- ' year% Year number
- ' day% Day number
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Julian2Date$ (julian&)
- '
- FUNCTION Julian2Date$ (julian&) STATIC
-
- x& = 4 * julian& - 6884477
- y& = (x& \ 146097) * 100
- d& = (x& MOD 146097) \ 4
-
- x& = 4 * d& + 3
- y& = (x& \ 1461) + y&
- d& = (x& MOD 1461) \ 4 + 1
-
- x& = 5 * d& - 3
- m& = x& \ 153 + 1
- d& = (x& MOD 153) \ 5 + 1
-
- IF m& < 11 THEN
- month% = m& + 2
- ELSE
- month% = m& - 10
- END IF
- day% = d&
- year% = y& + m& \ 11
-
- dat$ = MDY2Date$(month%, day%, year%)
- Julian2Date$ = dat$
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: MDY2Date$
-
- Creates a date string from the numeric values of month, day, and year for
- a given date. The string format is the same as that returned by the
- QuickBASIC DATE$ function, MM-DD-YYYY.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MDY2Date$ **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts month%, day%, and year% to a date string
- ' in the QuickBASIC string format MM-DD-YYYY.
- '
- ' EXAMPLE OF USE: dat$ = MDY2Date$(month%, day%, year%)
- ' PARAMETERS: month% Month for the date
- ' day% Day of the month
- ' year% Year number
- ' VARIABLES: y$ Temporary year string
- ' m$ Temporary month string
- ' d$ Temporary day string
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION MDY2Date$ (month%, day%, year%)
- '
- FUNCTION MDY2Date$ (month%, day%, year%) STATIC
- y$ = RIGHT$("000" + MID$(STR$(year%), 2), 4)
- m$ = RIGHT$("0" + MID$(STR$(month%), 2), 2)
- d$ = RIGHT$("0" + MID$(STR$(day%), 2), 2)
- MDY2Date$ = m$ + "-" + d$ + "-" + y$
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: MonthName$
-
- Returns the name of the month for a given date. If the passed date string
- has the wrong number of characters, the returned name defaults to
- MM-DD-YYYY to remind you of the required format for date strings. If the
- string is the right length but the first two characters don't represent a
- valid month number, ?MonthName? is returned.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MonthName$ **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string stating the month as indicated
- ' in dat$ (QuickBASIC string format MM-DD-YYYY).
- '
- ' EXAMPLE OF USE: PRINT MonthName$(dat$)
- ' PARAMETERS: dat$ Date of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION MonthName$ (dat$)
- '
- FUNCTION MonthName$ (dat$) STATIC
-
- IF LEN(dat$) <> 10 THEN
- dat$ = "MM-DD-YYYY"
- END IF
-
- SELECT CASE LEFT$(dat$, 2)
- CASE "01"
- MonthName$ = "January"
- CASE "02"
- MonthName$ = "February"
- CASE "03"
- MonthName$ = "March"
- CASE "04"
- MonthName$ = "April"
- CASE "05"
- MonthName$ = "May"
- CASE "06"
- MonthName$ = "June"
- CASE "07"
- MonthName$ = "July"
- CASE "08"
- MonthName$ = "August"
- CASE "09"
- MonthName$ = "September"
- CASE "10"
- MonthName$ = "October"
- CASE "11"
- MonthName$ = "November"
- CASE "12"
- MonthName$ = "December"
- CASE ELSE
- MonthName$ = "?MonthName?"
- END SELECT
-
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: OneMonthCalendar
-
- Uses several functions from the CALENDAR toolbox to print a small,
- one-month calendar at any location on the screen. The stand-alone program
- named MONTH provides a good demonstration of this subprogram at work.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: OneMonthCalendar **
- ' ** Type: Subprogram **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Prints a small, one-month calendar at the row%
- ' and col% indicated.
- '
- ' EXAMPLE OF USE: OneMonthCalendar dat$, row%, col%
- ' PARAMETERS: dat$ Date of concern
- ' row% Screen row for upper left corner of calenda
- ' col% Screen column for upper left corner of cale
- ' VARIABLES: mname$ Name of given month
- ' month% Month number
- ' day% Day number
- ' year% Year number
- ' dat1$ Date for first of the given month
- ' j& Julian day number for each day of the month
- ' heading$ Title line for calendar
- ' wa% Day of the week for each day of the month
- ' rowloc% Row for printing each day number
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB OneMonthCalendar (dat$, row%, col%)
- '
- SUB OneMonthCalendar (dat$, row%, col%) STATIC
- mname$ = MonthName$(dat$)
- LOCATE row%, col% + 12 - LEN(mname$) \ 2
- PRINT mname$; ","; Date2Year%(dat$)
- month% = Date2Month%(dat$)
- day% = 1
- year% = Date2Year%(dat$)
- dat1$ = MDY2Date$(month%, day%, year%)
- j& = Date2Julian&(dat1$)
- heading$ = " Sun Mon Tue Wed Thu Fri Sat"
- wa% = INSTR(heading$, LEFT$(DayOfTheWeek$(dat1$), 3)) \ 4
- LOCATE row% + 1, col%
- PRINT heading$
- rowloc% = row% + 2
- LOCATE rowloc%, col% + 4 * wa%
- DO
- PRINT USING "####"; day%;
- IF wa% = 6 THEN
- rowloc% = rowloc% + 1
- LOCATE rowloc%, col%
- END IF
- wa% = (wa% + 1) MOD 7
- j& = j& + 1
- day% = Date2Day%(Julian2Date$(j&))
- LOOP UNTIL day% = 1
- PRINT
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Second2Date$
-
- Returns a date string given the number of seconds since the last second of
- 1979. The number of seconds is limited to the range of positive long
- integers (1 to 2147483647). Given the largest possible long integer, the
- function returns the date 01-19-2048.
-
- Related functions are Second2Time$ and TimeDate2Second&. The
- Second2Time$ function finds the time string for a given second, and the
- TimeDate2Second$ function finds the seconds since 1979 for a given date
- and time.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Second2Date$ **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the date in the QuickBASIC string format
- ' MM-DD-YYYY given a number of seconds since the
- ' last second of 1979. Use Second2Time$ to find
- ' the time of day at the indicated second.
- '
- ' EXAMPLE OF USE: dat$ = Second2Date$(second&)
- ' PARAMETERS: second& Number of seconds since the last second of
- ' VARIABLES: days& Julian day number of the date
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Second2Date$ (second&)
- '
- FUNCTION Second2Date$ (second&) STATIC
- days& = second& \ 86400 + 2444240
- Second2Date$ = Julian2Date$(days&)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Second2Time$
-
- Returns a time string given the number of seconds since the last second of
- 1979.
-
- Related functions are Second2Date$ and TimeDate2Second&. The
- Second2Date$ function finds the date string for a given second, and the
- TimeDate2Second$ function finds the seconds since 1979 for a given date
- and time.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Second2Time$ **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the time in the QuickBASIC string format
- ' HH:MM:SS given the number of seconds since the
- ' last second of 1979. Use Second2Date$ to find
- ' the date at the indicated second.
- '
- ' EXAMPLE OF USE: tim$ = Second2Time$(second&)
- ' PARAMETERS: second& Number of seconds since the last second of
- ' VARIABLES: time& Number of seconds in current day
- ' second% Current second of the minute
- ' minute% Current minute of the hour
- ' hour% Current hour of the day
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Second2Time$ (second&)
- '
- FUNCTION Second2Time$ (second&) STATIC
- IF second& > 0 THEN
- time& = second& MOD 86400
- second% = time& MOD 60
- time& = time& \ 60
- minute% = time& MOD 60
- hour% = time& \ 60
- Second2Time$ = HMS2Time$(hour%, minute%, second%)
- ELSE
- Second2Time$ = "HH:MM:SS"
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Time2Hour%
-
- Extracts the numeric value of the hour from a time string if in the
- standard TIME$ format HH:MM:SS.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Time2Hour% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the hour number as indicated in a time
- ' string in the format HH:MM:SS.
- '
- ' EXAMPLE OF USE: hour% = Time2Hour%(tim$)
- ' PARAMETERS: tim$ Time of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Time2Hour% (tim$)
- '
- FUNCTION Time2Hour% (tim$) STATIC
- Time2Hour% = VAL(LEFT$(tim$, 2))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Time2Minute%
-
- Extracts the numeric value of the hour from a time string that is in the
- standard TIME$ format HH:MM:SS.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Time2Minute% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the minute number as indicated in a time
- ' string in the format HH:MM:SS.
- '
- ' EXAMPLE OF USE: minute% = Time2Minute%(tim$)
- ' PARAMETERS: tim$ Time of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Time2Minute% (tim$)
- '
- FUNCTION Time2Minute% (tim$) STATIC
- Time2Minute% = VAL(MID$(tim$, 4, 2))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Time2Second%
-
- Extracts the numeric value of the seconds from a time string that is in
- the standard TIME$ format HH:MM:SS.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Time2Second% **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the second number as indicated in a time
- ' string in the format HH:MM:SS.
- '
- ' EXAMPLE OF USE: second% = Time2Second%(tim$)
- ' PARAMETERS: tim$ Time of concern
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Time2Second% (tim$)
- '
- FUNCTION Time2Second% (tim$) STATIC
- Time2Second% = VAL(MID$(tim$, 7))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: TimeDate2Second&
-
- Returns the number of seconds since the last second of 1979 given any date
- and time between the first second of 1980 and a moment in the year 2048.
-
- The largest positive long integer that can be stored in four bytes using
- two's complement notation is 2147483647. From the arbitrary point in time
- at the start of 1980, counting in seconds reaches this largest possible
- positive integer at 03:14:07 on 01-19-2048.
-
- One advantage of converting date and time to a number of seconds is that
- this long integer is more compact; this is an advantage, for example, when
- a large number of dates and times must be recorded in a disk file. Event
- logging, data acquisition, and business transaction time stamping are
- examples of the use of this type of subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: TimeDate2Second& **
- ' ** Type: Function **
- ' ** Module: CALENDAR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the number of seconds since the last
- ' second of 1979. If the date is not in the years
- ' 1980 to 2047, an error message is output.
- '
- ' EXAMPLE OF USE: sec& = TimeDate2Second&(tim$, dat$)
- ' PARAMETERS: tim$ Time of concern
- ' dat$ Date of concern
- ' VARIABLES: days& Days since 12-31-1979
- ' hour% Hour of the day
- ' minute% Minute of the hour
- ' second% Second of the minute
- ' secs& Working number of total seconds
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION TimeDate2Second& (tim$, dat$)
- '
- FUNCTION TimeDate2Second& (tim$, dat$) STATIC
- days& = Date2Julian&(dat$) - 2444240
- hour% = VAL(LEFT$(tim$, 2))
- minute% = VAL(MID$(tim$, 4, 2))
- second% = VAL(RIGHT$(tim$, 2))
- secs& = CLNG(hour%) * 3600 + minute% * 60 + second%
- IF days& >= 0 AND days& < 24857 THEN
- TimeDate2Second& = days& * 86400 + secs&
- ELSE
- PRINT "TimeDate2Second: Not in range 1980 to 2047"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- CARTESIA
-
- The CARTESIA toolbox contains two subprograms and two functions that
- convert between Cartesian and polar coordinates. The program first prompts
- you to enter x and y values defining a point on the Cartesian plane and
- then prints the equivalent coordinate in polar notation.
-
- ┌────────────────────────────────────────────────────────────────────────┐
- │ This figure can be found on p.78 of the printed version of the book. │
- └────────────────────────────────────────────────────────────────────────┘
-
- All of the variables in this module are defined as single-precision,
- floating-point values. If you need greater precision, globally change all
- exclamation point characters to pound sign characters. You'll also want to
- change the CONST PI statement in the Angle! function to provide a
- double-precision value for PI.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- CARTESIA.BAS Demo module
- Angle! Func Angle between X axis and line to x, y
- point
- Magnitude! Func Distance from origin to x, y point
- Pol2Rec Sub Polar to Cartesian conversion
- Rec2Pol Sub Cartesian to polar conversion
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: CARTESIA
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CARTESIA **
- ' ** Type: Toolbox **
- ' ** Module: CARTESIA.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates a set of functions and subprograms
- ' dealing with Cartesian coordinates.
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: x! X value of Cartesian coordinate
- ' y! Y value of Cartesian coordinate
- ' r! Polar notation distance from origin
- ' theta! Polar notation angle from X axis
-
- DECLARE FUNCTION Angle! (x!, y!)
- DECLARE FUNCTION Magnitude! (x!, y!)
-
- DECLARE SUB Pol2Rec (r!, theta!, x!, y!)
- DECLARE SUB Rec2Pol (x!, y!, r!, theta!)
-
- CLS
- INPUT "Enter X ", x!
- INPUT "Enter Y ", y!
- PRINT
- PRINT "Magnitude!(x!, y!)", Magnitude!(x!, y!)
- PRINT "Angle!(x!, y!)", Angle!(x!, y!)
- PRINT
- Rec2Pol x!, y!, r!, theta!
- PRINT "Rec2Pol", , r!; theta!
- Pol2Rec r!, theta!, x!, y!
- PRINT "Pol2Rec", , x!; y!
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Angle!
-
- Returns the angle from the origin to a given Cartesian coordinate,
- measured from the positive X axis. The angle, expressed in radians, is
- returned in the range -PI < Angle! <= +PI.
-
- This function has a good example of an IF-ELSEIF-ELSE-ENDIF structured
- statement. Notice that even though this function contains quite a few
- statements, the routine quickly skips over the unnecessary instructions.
- These tests let the function cover all the special case situations, such
- as when the coordinate falls on one or both axes.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Angle! **
- ' ** Type: Function **
- ' ** Module: CARTESIA.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the angle (in radians) between the X axis
- ' and the line from the origin to the point x!,y!
- '
- ' EXAMPLE OF USE: a! = Angle!(x!, y!)
- ' PARAMETERS: x! X part of the Cartesian coordinate
- ' y! Y part of the Cartesian coordinate
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Angle! (x!, y!)
- '
- FUNCTION Angle! (x!, y!) STATIC
-
- CONST PI = 3.141593
- CONST HALFPI = PI / 2
-
- IF x! = 0! THEN
- IF y! > 0! THEN
- Angle! = HALFPI
- ELSEIF y! < 0! THEN
- Angle! = -HALFPI
- ELSE
- Angle! = 0!
- END IF
- ELSEIF y! = 0! THEN
- IF x! < 0! THEN
- Angle! = PI
- ELSE
- Angle! = 0!
- END IF
- ELSE
- IF x! < 0! THEN
- IF y! > 0! THEN
- Angle! = ATN(y! / x!) + PI
- ELSE
- Angle! = ATN(y! / x!) - PI
- END IF
- ELSE
- Angle! = ATN(y! / x!)
- END IF
- END IF
-
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Magnitude!
-
- Returns the distance from the origin to a given Cartesian coordinate.
-
- This function, together with the Angle! function, provides the
- calculations that perform rectangular to polar coordinate conversions.
- They are both called by the Rec2Pol subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Magnitude! **
- ' ** Type: Function **
- ' ** Module: CARTESIA.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the distance from the origin to the
- ' point x!,y!
- '
- ' EXAMPLE OF USE: r! = Magnitude!(x!, y!)
- ' PARAMETERS: x! X part of the Cartesian coordinate
- ' y! Y part of the Cartesian coordinate
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Magnitude! (x!, y!)
- '
- FUNCTION Magnitude! (x!, y!) STATIC
- Magnitude! = SQR(x! * x! + y! * y!)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Pol2Rec
-
- Converts a polar notation point (magnitude, angle) to its equivalent (x,
- y) Cartesian coordinates. The conversion assumes that theta! is expressed
- in radians and uses the built-in QuickBASIC functions for finding the sine
- and cosine of this angle.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Pol2rec **
- ' ** Type: Subprogram **
- ' ** Module: CARTESIA.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts polar coordinates to Cartesian notation.
- '
- ' EXAMPLE OF USE: Pol2Rec r!, theta!, x!, y!
- ' PARAMETERS: r! Distance of point from the origin
- ' theta! Angle of point from the X axis
- ' x! X coordinate of the point
- ' y! Y coordinate of the point
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Pol2Rec (r!, theta!, x!, y!)
- '
- SUB Pol2Rec (r!, theta!, x!, y!) STATIC
- x! = r! * COS(theta!)
- y! = r! * SIN(theta!)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Rec2Pol
-
- Converts a point expressed as a Cartesian coordinate pair (x, y) to the
- equivalent polar notation (magnitude, angle). The Angle! and Magnitude!
- functions within this toolbox perform the calculations for this
- conversion.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Rec2pol **
- ' ** Type: Subprogram **
- ' ** Module: CARTESIA.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts Cartesian coordinates to polar notation.
- '
- ' EXAMPLE OF USE: Rec2Pol x!, y!, r!, theta!
- ' PARAMETERS: x! X coordinate of the point
- ' y! Y coordinate of the point
- ' r! Distance of point from the origin
- ' theta! Angle of point from the X axis
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Angle! (x!, y!)
- ' DECLARE FUNCTION Magnitude! (x!, y!)
- ' DECLARE SUB Rec2Pol (x!, y!, r!, theta!)
- '
- SUB Rec2Pol (x!, y!, r!, theta!) STATIC
- r! = Magnitude!(x!, y!)
- theta! = Angle!(x!, y!)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- CIPHER
-
- The CIPHER program securely ciphers and deciphers any file. You probably
- have some files or data that you'd prefer to keep secret, such as personal
- financial information or proprietary business matters. Several packages on
- the market let you keep your files secure from prying eyes, but they do it
- at some expense. This program does it quickly and simply.
-
- For each byte in the file to be ciphered, the program generates a
- pseudorandom byte in the range 0 through 255. The pseudorandom byte and
- the file byte are combined using the QuickBASIC XOR function, and the byte
- in the file is replaced with this result. To decipher the file, use the
- CIPHER program to process the file a second time, using exactly the same
- key. XOR then returns the file to its original state.
-
- The bytes in the ciphered file will appear to be as random as the sequence
- of pseudorandom bytes generated for this process. The RandInteger%
- function generates the bytes, which makes the number of possible
- pseudorandom sequences astronomical. Without knowing the key string used
- to initialize this sequence, a person could probably not break the cipher.
- This points out an important fact about the security of this technique:
- The ciphered file is only as secure as the key you select. Let's see how
- you can choose a secure key.
-
- First, the "don'ts": Don't use simple, obvious keys such as your name,
- initials, names of family members or pets, addresses, phone numbers, and
- the like. Don't use the same key repeatedly. Don't record the keys in an
- easy-to-find place, such as in a batch file containing CIPHER commands.
- And don't forget to keep track of your key in some safe way. You won't be
- able to get your file back if you forget the key!
-
- There are several ways to generate your own keys in a safe, secure manner.
- Be creative! For example, you might choose your own private "magic number"
- that you can easily remember and use it to define a key. If your number is
- 17, you could use the first 17 characters of line 17, page 17, in your
- favorite novel. Another technique is to create a common phrase that's easy
- to remember yet contains deliberately misspelled words or an odd
- combination of upper- and lowercase characters──3 blined MiSe, for
- example. Don't get too carried away with your creativity, though, and end
- up with something you can't remember. Changing even one character in the
- key will generate an entirely different sequence of pseudorandom bytes.
-
- The CIPHER program has a unique feature built into it to help generate new
- words that you can use as keys. Instead of typing the filename and key
- string on the command line that invokes the CIPHER program, type CIPHER
- /NEWKEY and press the Enter key. The program will generate nine
- pseudorandom words, created by randomly selecting characters from sets of
- consonants and vowels in a way that makes most of them readable.
-
- When you use the /NEWKEY command line option, a unique set of new words is
- generated for every possible clock tick in the life of your computer. In
- the module-level code of CIPHER.BAS is the statement RandShuffle DATE$ +
- TIME$ + STR$(TIMER), which initializes the random number generator when
- you give the /NEWKEY option. The key string for the initialization is
- formed by combining the date, time, and timer information into a string of
- about 27 characters.
-
- Eighteen times each second your computer updates its internal clock. The
- TIMER function returns a different value each time this happens, and the
- date and time are unique for every possible second of each day. As a
- result, the key string that initializes the random number generator will
- always be unique, and it's safe to say you'll never see the same group of
- nine words repeated.
-
- If you have a large number of files that you'd like to cipher, you can
- automate the process. Create a batch file containing CIPHER command lines,
- complete with filenames and keys. Keep this batch file ciphered at all
- times, except when you want to use it to cipher or decipher the group of
- files listed in the commands. This way, the only key you must remember is
- the one for unlocking the batch command file.
-
- To try out the CIPHER program, follow these steps. Create a small,
- readable file using the Document mode of the QuickBASIC editor, and save
- it as TEST.TXT. Verify the file contents by typing TYPE TEST.TXT. Now, to
- cipher the file, run CIPHER with the command line TEST.TXT ABC. When
- CIPHER is finished, the file will be unreadable, and entering TYPE
- TEST.TXT will result in strange characters on your screen. To decipher the
- file, once again run CIPHER with the same command line: TEST.TXT ABC. Be
- sure to enter the key string ("ABC" in this case) exactly the same as you
- did when the file was ciphered. Finally, type out the file to verify that
- it was correctly deciphered.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- CIPHER.BAS Program module
- NewWord$ Func Creates pseudorandom new word
- ProcesX Sub Enciphers string by XORing bytes
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: CIPHER
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CIPHER **
- ' ** Type: Program **
- ' ** Module: CIPHER.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: CIPHER filename.ext key or CIPHER /NEWKEY
- ' .MAK FILE: CIPHER.BAS
- ' RANDOMS.BAS
- ' PARAMETERS: filename Name of file to be ciphered or deciphere
- ' key String of one or more words used as the
- ' cipher key
- ' VARIABLES: cmd$ Working copy of COMMAND$
- ' i% Loop index
- ' firstSpace% Location in command line of first charac
- ' fileName$ Name of file to be processed
- ' key$ String to be used as cipher key
- ' fileLength& Length of file to be processed
- ' a$ Workspace for groups of bytes from the f
- ' count% Number of groups of bytes to be processe
- ' j& Location in file of each group of bytes
-
- ' Constants
- CONST BYTES = 1000&
-
- ' Functions
- DECLARE FUNCTION NewWord$ ()
- DECLARE FUNCTION Rand& ()
- DECLARE FUNCTION RandInteger% (a%, b%)
-
- ' Subprograms
- DECLARE SUB RandShuffle (key$)
- DECLARE SUB ProcesX (a$)
-
- ' Initialization
- CLS
- PRINT "CIPHER "; COMMAND$
- PRINT
-
- ' Grab the command line parameters
- cmd$ = COMMAND$
-
- ' If no command line parameters, then tell user what's needed
- IF cmd$ = "" THEN
- PRINT
- PRINT "Usage: CIPHER /NEWKEY"
- PRINT "(or) CIPHER filename key-string"
- PRINT
- SYSTEM
- END IF
-
- ' If /NEWKEY option, generate a few new words, and then quit
- IF INSTR(cmd$, "/NEWKEY") THEN
-
- ' Clear the screen and describe the output
- CLS
- PRINT "Randomly created words that can be used as cipher keys..."
- PRINT
- RandShuffle DATE$ + TIME$ + STR$(TIMER)
- FOR i% = 1 TO 9
- PRINT NewWord$; " ";
- NEXT i%
- PRINT
- SYSTEM
- END IF
-
- ' Get the filename from the command line
- cmd$ = cmd$ + " "
- firstSpace% = INSTR(cmd$, " ")
- fileName$ = LEFT$(cmd$, firstSpace% - 1)
-
- ' Grab the rest of the command line as the cipher key
- key$ = LTRIM$(MID$(cmd$, firstSpace% + 1))
-
- ' Prepare the pseudorandom numbers using the key for shuffling
- RandShuffle key$
-
- ' Open up the file
- OPEN fileName$ FOR BINARY AS #1
- fileLength& = LOF(1)
-
- ' Process the file in manageable pieces
- a$ = SPACE$(BYTES)
- count% = fileLength& \ BYTES
-
- ' Loop through the file
- FOR i% = 0 TO count%
- j& = i% * BYTES + 1
- IF i% = count% THEN
- a$ = SPACE$(fileLength& - BYTES * count%)
- END IF
- GET #1, j&, a$
- ProcesX a$
- PUT #1, j&, a$
- NEXT i%
-
- ' All done
- SYSTEM
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: NewWord$
-
- Creates a pseudorandom, new "word" by randomly selecting appropriate
- consonants and vowels to form one to three syllables. These words can be
- useful as passwords, cipher keys, or new product names.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: NewWord$ **
- ' ** Type: Function **
- ' ** Module: CIPHER.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a pseudorandom word of a possibly
- ' speakable form.
- '
- ' EXAMPLE OF USE: PRINT NewWord$
- ' PARAMETERS: (none)
- ' VARIABLES: vowel$ String constant listing the set of vowels
- ' consonant$ String constant listing the set of consonant
- ' syllables% Random number of syllables for the new word
- ' i% Loop index for creating each syllable
- ' t$ Temporary work string for forming the new wo
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION NewWord$ ()
- '
- FUNCTION NewWord$ STATIC
- CONST vowel$ = "aeiou"
- CONST consonant$ = "bcdfghjklmnpqrstvwxyz"
- syllables% = Rand& MOD 3 + 1
- FOR i% = 1 TO syllables%
- t$ = t$ + MID$(consonant$, RandInteger%(1, 21), 1)
- IF i% = 1 THEN
- t$ = UCASE$(t$)
- END IF
- t$ = t$ + MID$(vowel$, RandInteger%(1, 5), 1)
- NEXT i%
- IF Rand& MOD 2 THEN
- t$ = t$ + MID$(consonant$, RandInteger%(1, 21), 1)
- END IF
- NewWord$ = t$
- t$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ProcesX
-
- Enciphers a string by XORing the bytes with a sequence of pseudorandom
- bytes. The bytes are generated as pseudorandom integers in the range 0
- through 255 by the RandInteger% function.
-
- If you initialize the random number generator with the same sequence and
- process the ciphered string a second time with this subprogram, the
- original string will result. The CIPHER program allows deciphering in this
- way by simply requiring that the ciphered file be "ciphered" a second time
- with the same key.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ProcesX **
- ' ** Type: Subprogram **
- ' ** Module: CIPHER.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Enciphers a string by XORing with pseudorandom bytes.
- '
- ' EXAMPLE OF USE: ProcesX a$
- ' PARAMETERS: a$ String to be ciphered
- ' VARIABLES: i% Index into the string
- ' byte% Numeric value of each string character
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB ProcesX (a$)
- '
- SUB ProcesX (a$) STATIC
- FOR i% = 1 TO LEN(a$)
- byte% = ASC(MID$(a$, i%, 1)) XOR RandInteger%(0, 255)
- MID$(a$, i%, 1) = CHR$(byte%)
- NEXT i%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- COLORS
-
- The COLORS program provides a handy utility for interactively selecting
- colors from the 262,144 available in the VGA and MCGA graphics modes. To
- run this program, you must have a mouse and VGA or MCGA graphics
- capability.
-
- The program is easy to use. Simply click on any of the three color bars to
- set the intensity of that color. The ellipse on the left side of the
- screen shows the color shade you selected, and the long integer value at
- the top of the screen shows the numeric value to use with the PALETTE
- statement for setting this same color in other programs. When you're ready
- to quit, click on the X at the lower left corner of the screen.
-
- You can run this program from the QuickBASIC environment, but to make it
- an easily accessible utility, it's probably better to compile it and
- create a stand-alone .EXE program module.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- COLORS.BAS Program module
- Shade& Func Color value from given red, green, and
- blue
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: COLORS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: COLORS **
- ' ** Type: Program **
- ' ** Module: COLORS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Provides interactive selection of a color shade.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: VGA or MCGA
- ' MIXED.QLB/.LIB
- ' Mouse
- ' .MAK FILE: COLORS.BAS
- ' BITS.BAS
- ' MOUSSUBS.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: red! Intensity of red, from 0 to 1
- ' green! Intensity of green, from 0 to 1
- ' blue! Intensity of blue, from 0 to 1
- ' mask$ Mouse graphics cursor definition strin
- ' xHot% Mouse cursor hot spot X location
- ' yHot% Mouse cursor hot spot Y location
- ' cursor$ Mouse cursor binary definition string
- ' fill% Color bar height calculation
- ' x% Color bar horizontal left edge
- ' x2% Color bar horizontal right edge
- ' y% Color bar vertical top edge
- ' y2% Color bar vertical bottom edge
- ' leftButton% State of left mouse button
- ' rightButton% State of right mouse button
- ' xMouse% Horizontal mouse location
- ' yMouse% Vertical mouse location
- ' clickFlag% Toggle for left mouse button state
- ' xM% Modified mouse horizontal location
- ' quitFlag% Signal to end program
-
-
- ' Logical constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Constants
- CONST REDPAL = 1
- CONST BLUEPAL = 2
- CONST GREENPAL = 3
- CONST TESTPAL = 4
- CONST WHITEPAL = 5
- CONST BARPAL = 6
- CONST DX = 15
- CONST DY = 150
- CONST RX = 180
- CONST RY = 30
- CONST GX = RX + DX + DX
- CONST GY = RY
- CONST BX = GX + DX + DX
- CONST BY = RY
-
- ' Functions
- DECLARE FUNCTION Shade& (red!, green!, blue!)
-
- ' Subprograms
- DECLARE SUB MouseHide ()
- DECLARE SUB MouseMaskTranslate (mask$, xHot%, yHot%, cursor$)
- DECLARE SUB MouseSetGcursor (cursor$)
- DECLARE SUB MouseShow ()
- DECLARE SUB Cursleft (mask$, xHot%, yHot%)
- DECLARE SUB MouseNow (leftButton%, rightButton%, xMouse%, yMouse%)
-
- ' Set 256 color mode
- SCREEN 13
-
- ' Set first three colors as pure red, green, blue
- PALETTE REDPAL, Shade&(1!, 0!, 0!)
- PALETTE GREENPAL, Shade&(0!, 1!, 0!)
- PALETTE BLUEPAL, Shade&(0!, 0!, 1!)
-
- ' Set a pure white color choice
- PALETTE WHITEPAL, Shade&(1!, 1!, 1!)
-
- ' Set bar background color
- PALETTE BARPAL, Shade&(0!, 0!, 0!)
-
- ' Set background to light gray
- PALETTE 0, Shade&(.4, .4, .4)
-
- ' Start each intensity at midscale
- red! = .5
- green! = .5
- blue! = .5
-
- ' Set starting shade
- PALETTE TESTPAL, Shade&(red!, green!, blue!)
-
- ' Create ellipse of circle to show current shade selected
- CIRCLE (70, 100), 80, TESTPAL, , , 1.4
- PAINT (70, 100), TESTPAL
-
- ' Create the three color bars
- LINE (RX, RY)-(RX + DX, RY + DY), WHITEPAL, B
- LINE (GX, GY)-(GX + DX, GY + DY), WHITEPAL, B
- LINE (BX, BY)-(BX + DX, BY + DY), WHITEPAL, B
-
- ' Mark place to quit by clicking
- LOCATE 25, 1
- PRINT "(X) "; CHR$(27); " Quit";
-
- ' Make the left arrow mouse cursor
- Cursleft mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, cursor$
- MouseSetGcursor cursor$
-
- ' Main loop
- DO
-
- ' Put title and current shade number at top
- LOCATE 1, 1
- PRINT "COLOR CHOOSER"; TAB(22);
- PRINT USING "##########"; Shade&(red!, green!, blue!)
-
- ' Fill in the red color bar
- fill% = red! * (DY - 3) + 1
- x% = RX + 1
- x2% = RX + DX
- y% = RY + 1
- y2% = RY + DY
- LINE (x%, y%)-(x2% - 1, y2% - fill% - 1), BARPAL, BF
- LINE (x%, y2% - fill%)-(x2% - 1, y2% - 1), REDPAL, BF
-
- ' Fill in the green color bar
- fill% = green! * (DY - 3) + 1
- x% = GX + 1
- x2% = GX + DX
- y% = GY + 1
- y2% = GY + DY
- LINE (x%, y%)-(x2% - 1, y2% - fill% - 1), BARPAL, BF
- LINE (x%, y2% - fill%)-(x2% - 1, y2% - 1), GREENPAL, BF
-
- ' Fill in the blue color bar
- fill% = blue! * (DY - 3) + 1
- x% = BX + 1
- x2% = BX + DX
- y% = BY + 1
- y2% = BY + DY
- LINE (x%, y%)-(x2% - 1, y2% - fill% - 1), BARPAL, BF
- LINE (x%, y2% - fill%)-(x2% - 1, y2% - 1), BLUEPAL, BF
-
- ' Change the shade of the ellipse
- PALETTE TESTPAL, Shade&(red!, green!, blue!)
-
- ' Refresh mouse cursor
- MouseShow
-
- ' Wait for fresh mouse left button click
- DO
- MouseNow leftButton%, rightButton%, xMouse%, yMouse%
- IF leftButton% = FALSE THEN
- clickFlag% = FALSE
- END IF
- IF clickFlag% THEN
- leftButton% = 0
- END IF
- LOOP UNTIL leftButton%
-
- ' Hide mouse and set parameters
- MouseHide
- clickFlag% = TRUE
- xM% = xMouse% \ 2
-
- ' Is mouse in the "Quit" area?
- IF xMouse% < 45 AND yMouse% > 190 THEN
- quitFlag% = TRUE
- END IF
-
- ' Is mouse at the right height to be in a bar?
- IF yMouse% > RY - 2 AND yMouse% < RY + DY + 2 THEN
-
- ' Is mouse in the red bar?
- IF xM% > RX AND xM% < RX + DX THEN
- red! = 1! - (yMouse% - RY) / DY
- IF red! < 0 THEN
- red! = 0
- ELSEIF red! > 1 THEN
- red! = 1
- END IF
- END IF
-
- ' Is mouse in the green bar?
- IF xM% > GX AND xM% < GX + DX THEN
- green! = 1! - (yMouse% - RY) / DY
- IF green! < 0 THEN
- green! = 0
- ELSEIF green! > 1 THEN
- green! = 1
- END IF
- END IF
-
- ' Is mouse in the blue bar?
- IF xM% > BX AND xM% < BX + DX THEN
- blue! = 1! - (yMouse% - RY) / DY
- IF blue! < 0 THEN
- blue! = 0
- ELSEIF blue! > 1 THEN
- blue! = 1
- END IF
- END IF
-
- END IF
-
- LOOP UNTIL quitFlag%
-
- SCREEN 0
- WIDTH 80
- CLS
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Shade&
-
- Returns the long integer number for a given shade of color.
-
- This is the only function the COLORS utility provides, but it's useful
- when programming the VGA and MCGA SCREEN modes 11, 12, and 13. You can use
- the long integer value returned in a PALETTE statement for setting a color
- attribute to one of 262,144 color choices.
-
- Three single-precision numbers are passed to this routine, representing
- the desired intensities of the red, green, and blue colors. These numbers
- must be in the range 0.0 through 1.0. Shade&(1!, 0!, 0!), for example,
- returns the long integer value for bright red; Shade&(.5, .5, .5) returns
- a number for medium gray.
-
- The best way to see the results of setting the three colors to various
- intensity levels is by running the COLORS program.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Shade& **
- ' ** Type: Function **
- ' ** Module: COLORS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the long integer color number given red,
- ' green, and blue intensity numbers in the range
- ' 0 through 1.
- '
- ' EXAMPLE OF USE: PALETTE 1, Shade&(red!, green!, blue!)
- ' PARAMETERS: red! Intensity of red, from 0 to 1
- ' green! Intensity of green, from 0 to 1
- ' blue! Intensity of blue, from 0 to 1
- ' VARIABLES: r& Red amount
- ' g& Green amount
- ' b& Blue amount
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Shade& (red!, green!, blue!)
- '
- FUNCTION Shade& (red!, green!, blue!) STATIC
- r& = red! * 63!
- g& = green! * 63!
- b& = blue! * 63!
- Shade& = r& + g& * 256& + b& * 65536
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- COMPLEX
-
- The COMPLEX toolbox provides a collection of subprograms for working with
- complex numbers. The QuickBASIC TYPE definition statement is ideal for
- declaring variables to be of type Complex, as shown. The variables a, b,
- and c each comprise a pair of single-precision numbers representing the
- real and imaginary parts of a complex number. These variables are passed
- to and from the subprograms as easily as if they were simple numeric
- values.
-
- Complex numbers are expressed as the sum of a real and an imaginary
- number. Usually you show a complex number by writing the real number,
- followed immediately by a plus or minus sign, the imaginary number, and a
- small letter "i" or "j," which represents the square root of -1 and
- indicates the imaginary numeric component of the complex number.
-
- In this program, complex numbers are entered and displayed in a similar
- format. You use parentheses to surround each complex number. This sample
- run of COMPLEX shows typical input and output complex-number formats:
-
-
- Enter first complex number ? (4-5i)
- (4-5i)
-
- ComplexExp (15.48743+52.35549i)
- ComplexLog 1.856786-.8960554i)
- ComplexReciprocal 9.756097E-02+.1219512i)
- ComplexSqr 2.280693-1.096158i)
-
- Enter second complex number ? (3+4i)
- (3+4i)
-
- ComplexAdd (7-1i)
- ComplexSub (1-9i)
- ComplexMul (32+1i)
- ComplexDiv (-.32-1.24i)
- ComplexPower (251.4394-9454.315i)
- ComplexRoot (.9952651-.4262131i)
-
-
-
- Press any key to continue
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- COMPLEX.BAS Demo module
- Complex2String Sub String representation of a complex number
- ComplexAdd Sub Adds two complex numbers
- ComplexDiv Sub Divides two complex numbers
- ComplexExp Sub Exponential function of a complex number
- ComplexLog Sub Natural log of a complex number
- ComplexMul Sub Multiplies two complex numbers
- ComplexPower Sub Complex number raised to a complex number
- ComplexReciprocal Sub Reciprocal of a complex number
- ComplexRoot Sub Complex root of a complex number
- ComplexSqr Sub Square root of a complex number
- ComplexSub Sub Subtracts two complex numbers
- String2Complex Sub Converts string to complex variable
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: COMPLEX
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: COMPLEX **
- ' ** Type: Toolbox **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates a set of complex number functions and
- ' subprograms.
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: COMPLEX.BAS
- ' CARTESIA.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: a Variable of type Complex
- ' b Variable of type Complex
- ' c Variable of type Complex
- ' x$ String representation of a complex number
- ' y$ String representation of a complex number
- ' z$ String representation of a complex number
-
- TYPE Complex
- r AS SINGLE
- i AS SINGLE
- END TYPE
-
- ' Subprograms
- DECLARE SUB ComplexSub (a AS Complex, b AS Complex, c AS Complex)
- DECLARE SUB ComplexSqr (a AS Complex, c AS Complex)
- DECLARE SUB ComplexRoot (a AS Complex, b AS Complex, c AS Complex)
- DECLARE SUB ComplexReciprocal (a AS Complex, c AS Complex)
- DECLARE SUB ComplexAdd (a AS Complex, b AS Complex, c AS Complex)
- DECLARE SUB ComplexLog (a AS Complex, c AS Complex)
- DECLARE SUB ComplexPower (a AS Complex, b AS Complex, c AS Complex)
- DECLARE SUB Complex2String (a AS Complex, x$)
- DECLARE SUB String2Complex (x$, a AS Complex)
- DECLARE SUB ComplexDiv (a AS Complex, b AS Complex, c AS Complex)
- DECLARE SUB ComplexExp (a AS Complex, c AS Complex)
- DECLARE SUB ComplexMul (a AS Complex, b AS Complex, c AS Complex)
- DECLARE SUB Rec2pol (x!, y!, r!, theta!)
-
- DIM a AS Complex, b AS Complex, c AS Complex
-
- CLS
- INPUT "Enter first complex number "; x$
- String2Complex x$, a
- Complex2String a, x$
- PRINT x$
- PRINT
-
- ComplexExp a, c
- Complex2String c, z$
- PRINT "ComplexExp", , z$
-
- ComplexLog a, c
- Complex2String c, z$
- PRINT "ComplexLog", , z$
-
- ComplexReciprocal a, c
- Complex2String c, z$
- PRINT "ComplexReciprocal", z$
-
- ComplexSqr a, c
- Complex2String c, z$
- PRINT "ComplexSqr", , z$
-
- PRINT
- INPUT "Enter second complex number "; y$
- String2Complex y$, b
- Complex2String b, y$
- PRINT y$
- PRINT
-
- ComplexAdd a, b, c
- Complex2String c, z$
- PRINT "ComplexAdd", , z$
-
- ComplexSub a, b, c
- Complex2String c, z$
- PRINT "ComplexSub", , z$
-
- ComplexMul a, b, c
- Complex2String c, z$
- PRINT "ComplexMul", , z$
-
- ComplexDiv a, b, c
- Complex2String c, z$
- PRINT "ComplexDiv", , z$
-
- ComplexPower a, b, c
- Complex2String c, z$
- PRINT "ComplexPower", , z$
-
- ComplexRoot a, b, c
- Complex2String c, z$
- PRINT "ComplexRoot", , z$
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Complex2String
-
- Creates a string representation of a complex number suitable for printing
- or displaying the results of complex number calculations. The string
- consists of two numbers enclosed in parentheses and separated by either a
- plus or minus sign, with the second number followed by a lowercase "i" to
- indicate the imaginary component. The length of this string result will
- vary, depending on the numeric values of the real and imaginary parts.
-
- All results displayed by the demonstrations are formatted using this
- subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Complex2String **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Makes a string representation of a complex number.
- '
- ' EXAMPLE OF USE: Complex2String a, x$
- ' PARAMETERS: a Complex number variable (type Complex)
- ' x$ String representation of the complex number
- ' VARIABLES: r$ Working string, real part
- ' i$ Working string, imaginary part
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB Complex2String (a AS Complex, x$)
- '
- SUB Complex2String (a AS Complex, x$) STATIC
-
- ' Form the left part of the string
- IF a.r < 0 THEN
- r$ = "(" + STR$(a.r)
- ELSE
- r$ = "(" + MID$(STR$(a.r), 2)
- END IF
-
- ' Form the right part of the string
- IF a.i < 0 THEN
- i$ = STR$(a.i)
- ELSE
- i$ = "+" + MID$(STR$(a.i), 2)
- END IF
-
- ' The whole is more complex than the sum of the parts
- x$ = r$ + i$ + "i)"
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexAdd
-
- Calculates the sum of two complex numbers. Complex number a is added to
- complex number b, and the result is placed in the variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexAdd **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Adds two complex numbers.
- '
- ' EXAMPLE OF USE: ComplexAdd a, b, c
- ' PARAMETERS: a First complex number for the addition
- ' b Second complex number for the addition
- ' c Result of the complex number addition
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexAdd (a AS Complex, b AS Complex, c AS Comple
- '
- SUB ComplexAdd (a AS Complex, b AS Complex, c AS Complex) STATIC
- c.r = a.r + b.r
- c.i = a.i + b.i
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexDiv
-
- Calculates the result of dividing one complex number by another. The
- result of a/b is placed in the variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexDiv **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Divides two complex numbers.
- '
- ' EXAMPLE OF USE: ComplexDiv a, b, c
- ' PARAMETERS: a First complex number for the division
- ' b Second complex number for the division
- ' c Result of the complex number division a/b
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexDiv (a AS Complex, b AS Complex, c AS Complex
- '
- SUB ComplexDiv (a AS Complex, b AS Complex, c AS Complex) STATIC
- t! = b.r * b.r + b.i * b.i
- c.r = (a.r * b.r + a.i * b.i) / t!
- c.i = (a.i * b.r - a.r * b.i) / t!
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexExp
-
- Calculates the exponential function of a complex number a. The result is
- placed in the variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexExp **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calculates the exponential function of a complex number.
- '
- ' EXAMPLE OF USE: ComplexExp a, c
- ' PARAMETERS: a Complex number argument
- ' c Complex result of the calculations
- ' VARIABLES: t! Temporary working value
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexExp (a AS Complex, c AS Complex)
- '
- SUB ComplexExp (a AS Complex, c AS Complex) STATIC
- t! = EXP(a.r)
- c.r = t! * COS(a.i)
- c.i = t! * SIN(a.i)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexLog
-
- Calculates the complex logarithm of a complex number a. The result is
- placed in the variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexLog **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calculates the log of a complex number.
- '
- ' EXAMPLE OF USE: ComplexLog a, c
- ' PARAMETERS: a Complex number argument
- ' c Complex result of the calculations
- ' VARIABLES: r! Magnitude of complex number a
- ' theta! Angle of complex number a
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexLog (a AS Complex, c AS Complex)
- ' DECLARE SUB Rec2pol (x!, y!, r!, theta!)
- '
- SUB ComplexLog (a AS Complex, c AS Complex) STATIC
- CALL Rec2pol(a.r, a.i, r!, theta!)
- IF r! <> 0! THEN
- c.r = LOG(r!)
- c.i = theta!
- ELSE
- ERROR 5
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexMul
-
- Calculates the product of two complex numbers. Complex variables a and b
- are multiplied, and the result is placed in the variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexMul **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Multiplies two complex numbers.
- '
- ' EXAMPLE OF USE: ComplexMul a, b, c
- ' PARAMETERS: a First complex number for the multiplication
- ' b Second complex number for the multiplicatio
- ' c Result of the complex number multiplication
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexMul (a AS Complex, b AS Complex, c AS Comple
- '
- SUB ComplexMul (a AS Complex, b AS Complex, c AS Complex) STATIC
- c.r = a.r * b.r - a.i * b.i
- c.i = a.r * b.i + a.i * b.r
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexPower
-
- Calculates the result of raising one complex number to the power of
- another. The result of raising a to the power of b is then placed in the
- variable c.
-
- Notice that this subprogram calls several others. If you extract this
- routine for use in another program module, be sure to extract the other
- subprograms as well.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexPower **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calculates a complex number raised to a complex number.
- '
- ' EXAMPLE OF USE: ComplexPower a, b, c
- ' PARAMETERS: a Complex number to be raised to a power
- ' b Complex number to raise a to
- ' c Result of a raised to the power of b
- ' VARIABLES: t1 Structure of type Complex
- ' t2 Structure of type Complex
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexPower (a AS Complex, b AS Complex, c AS Complex
- ' DECLARE SUB ComplexExp (a AS Complex, c AS Complex)
- ' DECLARE SUB ComplexLog (a AS Complex, c AS Complex)
- ' DECLARE SUB ComplexMul (a AS Complex, b AS Complex, c AS Complex)
- '
- SUB ComplexPower (a AS Complex, b AS Complex, c AS Complex) STATIC
- DIM t1 AS Complex, t2 AS Complex
- IF a.r <> 0! OR a.i <> 0! THEN
- CALL ComplexLog(a, t1)
- CALL ComplexMul(t1, b, t2)
- CALL ComplexExp(t2, c)
- ELSE
- ERROR 5
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexReciprocal
-
- Calculates the reciprocal of a complex number by dividing the complex
- number (1+0i) by the complex number a. The result is placed in the
- variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexReciprocal **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calculates the reciprocal of a complex number.
- '
- ' EXAMPLE OF USE: ComplexReciprocal a, c
- ' PARAMETERS: a Complex number to be processed
- ' c Result of calculating 1/a
- ' VARIABLES: t Structure of type Complex
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexReciprocal (a AS Complex, c AS Complex)
- ' DECLARE SUB ComplexDiv (a AS Complex, b AS Complex, c AS Comple
- '
- SUB ComplexReciprocal (a AS Complex, c AS Complex) STATIC
- DIM t AS Complex
- t.r = 1!
- t.i = 0
- ComplexDiv t, a, c
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexRoot
-
- Calculates the complex root of a complex number. The ComplexReciprocal
- and ComplexPower subprograms are called by this subprogram. These
- routines allow the root to be found by raising a to the power of 1/b.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexRoot **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calculates the complex root of a complex number.
- '
- ' EXAMPLE OF USE: ComplexRoot a, b, c
- ' PARAMETERS: a First complex number
- ' b Complex number root
- ' c Result of finding the bth root of a
- ' VARIABLES: t Structure of type Complex
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexRoot (a AS Complex, b AS Complex, c AS Complex
- ' DECLARE SUB ComplexReciprocal (a AS Complex, c AS Complex)
- ' DECLARE SUB ComplexPower (a AS Complex, b AS Complex, c AS Comple
- '
- SUB ComplexRoot (a AS Complex, b AS Complex, c AS Complex) STATIC
- DIM t AS Complex
- IF b.r <> 0! OR b.i <> 0! THEN
- CALL ComplexReciprocal(b, t)
- CALL ComplexPower(a, t, c)
- ELSE
- ERROR 5
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexSqr
-
- Calculates the complex square root of a complex number. The square root of
- a is placed in the variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexSqr **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calculates the square root of a complex number.
- '
- ' EXAMPLE OF USE: ComplexSqr a, c
- ' PARAMETERS: a Complex number argument
- ' c Result of finding the square root of a
- ' VARIABLES: r! Magnitude of complex number a
- ' theta! Angle of complex number a
- ' rs! Square root of r!
- ' h! One half of theta!
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexSqr (a AS Complex, c AS Complex)
- '
- SUB ComplexSqr (a AS Complex, c AS Complex) STATIC
- CALL Rec2pol(a.r, a.i, r!, theta!)
- rs! = SQR(r!)
- h! = theta! / 2!
- c.r = rs! * COS(h!)
- c.i = rs! * SIN(h!)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ComplexSub
-
- Calculates the difference between two complex numbers. The result of
- subtracting b from a is returned in the variable c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ComplexSub **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Subtracts two complex numbers.
- '
- ' EXAMPLE OF USE: ComplexSub a, b, c
- ' PARAMETERS: a First complex number
- ' b Second Complex number
- ' c Result of subtracting b from a
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB ComplexSub (a AS Complex, b AS Complex, c AS Comple
- '
- SUB ComplexSub (a AS Complex, b AS Complex, c AS Complex) STATIC
- c.r = a.r - b.r
- c.i = a.i - b.i
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: String2Complex
-
- Converts a string representation of a complex number to a complex number
- variable of type Complex. This routine is useful for converting user input
- of a complex number to a complex variable.
-
- In general, the string should be in the same format as that produced by
- the Complex2String function. However, there is some flexibility to allow
- for variations in the way a user might type in complex numbers. For
- example, the "i" character indicates the imaginary part of a complex
- number, but a "j" will also be recognized. Also, parentheses around the
- numbers are optional.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: String2Complex **
- ' ** Type: Subprogram **
- ' ** Module: COMPLEX.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts a string representation of a complex
- ' number to a type Complex variable.
- '
- ' EXAMPLE OF USE: String2Complex x$, a
- ' PARAMETERS: x$ String representation of a complex number
- ' a Complex number structure of type Complex
- ' VARIABLES: j% Index to first numerical character
- ' i% Pointer to the "i" or "j" character
- ' k% Pointer to start of imaginary part
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Complex
- ' r AS SINGLE
- ' i AS SINGLE
- ' END TYPE
- '
- ' DECLARE SUB Complex2String (a AS Complex, x$)
- '
- SUB String2Complex (x$, a AS Complex) STATIC
-
- ' Real part starts just after left parenthesis
- j% = INSTR(x$, "(") + 1
-
- ' Step forward to find start of number
- DO UNTIL INSTR("+-0123456789", MID$(x$, j%, 1)) OR j% > LEN(x$)
- j% = j% + 1
- LOOP
-
- ' Imaginary part ends at the "i" or "j"
- i% = INSTR(LCASE$(x$), "i")
- IF INSTR(LCASE$(x$), "j") > i% THEN
- i% = INSTR(LCASE$(x$), "j")
- END IF
-
- ' Step back to find start of imaginary part
- FOR k% = i% TO 1 STEP -1
- IF INSTR("+-", MID$(x$, k%, 1)) THEN
- EXIT FOR
- END IF
- NEXT k%
-
- ' Error if pointers don't make sense
- IF j% = 0 OR j% > LEN(x$) THEN
- PRINT "Error: String2Complex - unrecognizable string format"
- SYSTEM
- END IF
-
- ' Grab the real part
- a.r = VAL(MID$(x$, j%))
-
- ' Grab the imaginary part
- IF k% > j% THEN
- a.i = VAL(MID$(x$, k%))
- ELSEIF k% = j% THEN
- a.r = 0
- a.i = VAL(MID$(x$, j%))
- ELSE
- a.i = 0
- END IF
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- DOLLARS
-
- The DOLLARS toolbox contains three functions for working with monetary
- amounts.
-
- QuickBASIC provides a way for you to put commas between groups of three
- digits in numbers as they're printed or displayed. However, the Comma$
- and DollarString$ functions have the added advantage of allowing you to
- manipulate the string results further before outputting the results.
-
- The Round# function is presented here as a means of rounding dollar
- amounts to the nearest cent, but you can also use it for scientific and
- engineering calculations when you want to round numbers to a given number
- of decimal places.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- DOLLARS.BAS Demo module
- Comma$ Func Double-precision with commas inserted
- DollarString$ Func Dollar representation rounded with commas
- Round# Func Rounding at specified decimal place
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: DOLLARS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DOLLARS **
- ' ** Type: Toolbox **
- ' ** Module: DOLLARS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: n# Number for demonstration of the functions
-
- DECLARE FUNCTION Comma$ (n#)
- DECLARE FUNCTION DollarString$ (amount#, length%)
- DECLARE FUNCTION Round# (n#, place%)
-
- CLS
- n# = 1234567.76543#
- PRINT "Number n#:", , n#
- PRINT "Comma$(n#)", , Comma$(n#)
- PRINT "Comma$(Round#(n#, -2))", Comma$(Round#(n#, -2))
- PRINT
- PRINT "DollarString$(n#, 20)", ":"; DollarString$(n#, 20); ":"
- PRINT , , " 12345678901234567890"
- PRINT
-
- PRINT "Round#(n#, -3)", Round#(n#, -3)
- PRINT "Round#(n#, -2)", Round#(n#, -2)
- PRINT "Round#(n#, -1)", Round#(n#, -1)
- PRINT "Round#(n#, 0)", , Round#(n#, 0)
- PRINT "Round#(n#, 1)", , Round#(n#, 1)
- PRINT "Round#(n#, 2)", , Round#(n#, 2)
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Comma$
-
- Returns a string representation of a given double-precision number, with
- commas separating groups of three digits to the left of the decimal point.
- The returned string is the same as that returned by the QuickBASIC STR$
- function, except for the addition of the commas.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Comma$ **
- ' ** Type: Function **
- ' ** Module: DOLLARS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Creates a string representing a double-precision
- ' number, with commas inserted every three digits.
- '
- ' EXAMPLE OF USE: n$ = Comma$(n#)
- ' PARAMETERS: n# Number to be formatted
- ' VARIABLES: tn$ Temporary string of the number
- ' dp% Position of the decimal point
- ' i% Index into tn$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Comma$ (n#)
- '
- FUNCTION Comma$ (n#) STATIC
- tn$ = STR$(n#)
- dp% = INSTR(tn$, ".")
- IF dp% = 0 THEN
- dp% = LEN(tn$) + 1
- END IF
- IF dp% > 4 THEN
- FOR i% = dp% - 3 TO 3 STEP -3
- tn$ = LEFT$(tn$, i% - 1) + "," + MID$(tn$, i%)
- NEXT i%
- END IF
- Comma$ = LTRIM$(tn$)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: DollarString$
-
- Returns a string representation of a dollar amount, as passed in a
- double-precision variable. The Round# function rounds the number to the
- nearest penny, and the Comma$ function separates each group of three
- digits to the left of the decimal point with commas. The string is then
- padded on the left with spaces until the desired string length is
- achieved, and a dollar sign is placed to the left of the spaces. Thus, you
- can conveniently display the dollar amounts in columns.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DollarString$ **
- ' ** Type: Function **
- ' ** Module: DOLLARS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string representation of a dollar amount,
- ' rounded to the nearest cent, with commas separating
- ' groups of three digits, and with a preceding dollar sign.
- '
- ' EXAMPLE OF USE: d$ = DollarString$(dollars#)
- ' PARAMETERS: dollars# Amount of money
- ' VARIABLES: tmp$ Temporary working string
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Comma$ (n#)
- ' DECLARE FUNCTION DollarString$ (amount#, length%)
- ' DECLARE FUNCTION Round# (n#, place%)
- '
- FUNCTION DollarString$ (amount#, length%) STATIC
- tmp$ = SPACE$(length%) + "$" + Comma$(Round#(amount#, -2))
- DollarString$ = RIGHT$(tmp$, length%)
- tmp$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Round#
-
- Rounds numbers to any decimal position, as specified by the passed power
- of ten rounding value. For example, to round pi to the nearest integer
- value, you would use Round#(3.1416#, 0); to round 2/3 of ten dollars to
- the nearest cent, Round#(6.6666667#, -2); and finally, to round the
- distance to the moon to the nearest thousand miles, Round#(238857#, 3).
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Round# **
- ' ** Type: Function **
- ' ** Module: DOLLARS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Rounds a number at the power of 10 decimal place.
- '
- ' EXAMPLE OF USE: x# = Round#(n#, place%)
- ' EXAMPLES: Round#(12.3456#, -2) = 12.35#
- ' Round#(12.3456#, -1) = 12.3#
- ' Round#(12.3456#, 0) = 12#
- ' Round#(12.3456#, 1) = 10#
- ' PARAMETERS: n# Number to be rounded
- ' place% Power of 10 for rounding the number
- ' VARIABLES: pTen# 10 raised to the indicated power of 10
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Round# (n#, place%)
- '
- FUNCTION Round# (n#, powerOfTen%) STATIC
- pTen# = 10# ^ powerOfTen%
- Round# = INT(n# / pTen# + .5#) * pTen#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- DOSCALLS
-
- These routines use the Interrupt and InterruptX subprograms, provided as
- part of the QuickBASIC package, to access the operating system through
- software interrupts. The information returned by these functions and
- subprograms is extensive and useful.
-
- The DOSCALLS demo module proceeds in this way:
-
- The BufferedKeyInput$ function prompts you to enter up to nine
- characters. The appearance of the prompt and the input action from the
- keyboard seem very similar to the QuickBASIC INPUT statement, but there
- are some fundamental differences.
-
- Next, the DOSVersion! function returns the MS-DOS version number.
-
- The SetDrive subprogram temporarily switches the current drive, and the
- GetDrive$ function displays the results.
-
- The GetMediaDescriptor subprogram returns several useful pieces of
- information about the current disk drive.
-
- The Verify state is normally set using the MS-DOS VERIFY command, but with
- the GetVerifyState% function and the SetVerifyState subprogram, your
- programs can now control this setting directly.
-
- The GetDiskFreeSpace subprogram returns five useful details about the
- structure of the data and free space on any disk drive in your system.
-
- The GetCountry subprogram returns a data structure filled with details
- that enable you to modify your program outputs for use in other countries.
- Also returned is the address of the MS-DOS character translation
- subroutine called CaseMap, which translates certain characters for some
- foreign languages.
-
- The TranslateCountry$ function uses the address returned by the
- GetCountry subprogram to translate a string of characters for the
- currently set country.
-
- The GetDirectory$ function and SetDirectory subprogram let you determine
- or set the current directory-path string.
-
- The WriteToDevice subprogram is useful for outputting strings directly to
- the indicated device, using the MS-DOS output handler rather than
- QuickBASIC's. One advantage of this approach is in being able to use the
- ANSI.SYS escape-code sequences to control cursor movement, screen mode,
- and color attributes.
-
- Finally, the GetFileAttributes and SetFileAttributes subprograms let you
- determine or change the file attribute bits as desired. With these
- routines, it's easy to hide or unhide files and to set or clear the
- archive bit for use by the MS-DOS XCOPY command.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- DOSCALLS.BAS Demo module
- BufferedKeyInput$ Func ASCII string of specified length
- DOSVersion! Func Version number of MS-DOS returned
- GetCountry Sub Current country setting
- GetDirectory$ Func Path to disk directory specified
- GetDiskFreeSpace Sub Disk space format and usage for input
- drive
- GetDrive$ Func Current drive string
- GetFileAttributes Sub Attribute bits for given file
- GetMediaDescriptor Sub Drive information for system
- GetVerifyState% Func Verify setting (state)
- SetDirectory Sub Sets current directory
- SetDrive Sub Sets current disk drive
- SetFileAttributes Sub Sets the attribute bits for a given file
- SetVerifyState Sub Sets or clears verify state (writing to
- file)
- TranslateCountry$ Func Translates string──current country
- setting
- WriteToDevice Sub Outputs a string to a device
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: DOSCALLS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DOSCALLS **
- ' ** Type: Toolbox **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates several interrupt calls to MS-DOS.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: MS-DOS 3.0 or later
- ' MIXED.QLB/.LIB
- '.MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: buffer$ String for buffered input demonstration
- ' x$ Buffered input string
- ' drive$ Current disk drive name
- ' desc Structure of type MediaDescriptorType
- ' state% Current status of the Verify state
- ' oppositeState% Opposite state for Verify
- ' disk Structure of type DiskFreeSpaceType
- ' country Structure of type CountryType
- ' i% Loop index for creating translation characte
- ' a$ Characters to be translated
- ' path$ Current directory
- ' result% Result code from call to SetDirectory
- ' t$ Temporary copy of TIME$
- ' attr Structure of type FileAttributesType
- ' fileName$ Name of file for determining file attributes
-
-
- TYPE RegType
- ax AS INTEGER
- bx AS INTEGER
- cx AS INTEGER
- dx AS INTEGER
- bp AS INTEGER
- si AS INTEGER
- di AS INTEGER
- flags AS INTEGER
- END TYPE
-
- TYPE RegTypeX
- ax AS INTEGER
- bx AS INTEGER
- cx AS INTEGER
- dx AS INTEGER
- bp AS INTEGER
- si AS INTEGER
- di AS INTEGER
- flags AS INTEGER
- ds AS INTEGER
- es AS INTEGER
- END TYPE
-
- TYPE MediaDescriptorType
- sectorsPerAllocationUnit AS INTEGER
- bytesPerSector AS INTEGER
- FATIdentificationByte AS INTEGER
- END TYPE
-
- TYPE DiskFreeSpaceType
- sectorsPerCluster AS INTEGER
- bytesPerSector AS INTEGER
- clustersPerDrive AS LONG
- availableClusters AS LONG
- availableBytes AS LONG
- END TYPE
-
- TYPE CountryType
- dateTimeFormat AS STRING * 11
- currencySymbol AS STRING * 4
- thousandsSeparator AS STRING * 1
- decimalSeparator AS STRING * 1
- dateSeparator AS STRING * 1
- timeSeparator AS STRING * 1
- currencyThenSymbol AS INTEGER
- currencySymbolSpace AS INTEGER
- currencyPlaces AS INTEGER
- hours24 AS INTEGER
- caseMapSegment AS INTEGER
- caseMapOffset AS INTEGER
- dataListSeparator AS STRING * 1
- END TYPE
-
- TYPE FileAttributesType
- readOnly AS INTEGER
- hidden AS INTEGER
- systemFile AS INTEGER
- archive AS INTEGER
- result AS INTEGER
- END TYPE
-
- ' Subprograms
- DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegType)
- DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegTypeX)
- DECLARE SUB SetDrive (drive$)
- DECLARE SUB GetMediaDescriptor (drive$, desc AS MediaDescriptorType)
- DECLARE SUB SetVerifyState (state%)
- DECLARE SUB GetDiskFreeSpace (drive$, disk AS DiskFreeSpaceType)
- DECLARE SUB GetCountry (country AS CountryType)
- DECLARE SUB CaseMap (character%, BYVAL Segment%, BYVAL Offset%)
- DECLARE SUB SetDirectory (path$, result%)
- DECLARE SUB WriteToDevice (handle%, a$, result%)
- DECLARE SUB GetFileAttributes (fileName$, attr AS FileAttributesType)
- DECLARE SUB SetFileAttributes (fileName$, attr AS FileAttributesType)
-
- ' Functions
- DECLARE FUNCTION DOSVersion! ()
- DECLARE FUNCTION BufferedKeyInput$ (n%)
- DECLARE FUNCTION GetDrive$ ()
- DECLARE FUNCTION GetVerifyState% ()
- DECLARE FUNCTION TranslateCountry$ (a$, country AS CountryType)
- DECLARE FUNCTION GetDirectory$ (drive$)
-
- ' Try the Buffered Keyboard Input call
- CLS
- PRINT "BufferedKeyInput$:"
- PRINT "Enter a string of up to nine characters... ";
- x$ = BufferedKeyInput$(9)
- PRINT
- PRINT "Here's the nine-character string result... ";
- PRINT CHR$(34); x$; CHR$(34)
-
- ' Get the MS-DOS version number
- PRINT
- PRINT "DosVersion!:"
- PRINT "DOS Version number is "; DOSVersion!
-
- ' Demonstrate the GetDrive and SetDrive routines
- PRINT
- PRINT "GetDrive$ and SetDrive:"
- drive$ = GetDrive$
- PRINT "The current drive is "; drive$
- PRINT "Setting the current drive to A:"
- SetDrive "A:"
- PRINT "Now the current drive is "; GetDrive$
- PRINT "Setting the current drive back to "; drive$
- SetDrive drive$
- PRINT "Now the current drive is "; GetDrive$
-
- ' Call the MS-DOS "Media Descriptor" function for the current drive
- PRINT
- PRINT "GetMediaDescriptor"
- DIM desc AS MediaDescriptorType
- GetMediaDescriptor drive$, desc
- PRINT "Drive "; drive$
- PRINT "Sectors per allocation unit "; desc.sectorsPerAllocationUnit
- PRINT "Bytes per sector "; desc.bytesPerSector
- PRINT "FAT identification byte &H"; HEX$(desc.FATIdentificationByt
-
- ' Wait for user
- PRINT
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
- CLS
-
- ' Demonstrate the GetVerifyState and SetVerifyState routines
- PRINT
- PRINT "GetVerifyState% and SetVerifyState:"
- state% = GetVerifyState%
- PRINT "Current verify state is"; state%
- oppositeState% = 1 AND NOT state%
- SetVerifyState oppositeState%
- PRINT "Now the verify state is"; GetVerifyState%
- SetVerifyState state%
- PRINT "Now the verify state is"; GetVerifyState%
-
- ' Determine free space on the current drive
- PRINT
- PRINT "GetDiskFreeSpace:"
- DIM disk AS DiskFreeSpaceType
- GetDiskFreeSpace drive$, disk
- PRINT "Sectors per cluster "; disk.sectorsPerCluster
- PRINT "Bytes per sector "; disk.bytesPerSector
- PRINT "Total clusters on drive "; disk.clustersPerDrive
- PRINT "Available clusters "; disk.availableClusters
- PRINT "Available bytes "; disk.availableBytes
-
- ' Wait for user
- PRINT
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
- CLS
-
- ' Get country-dependent information
- PRINT
- PRINT "GetCountry:"
- DIM country AS CountryType
- GetCountry country
- PRINT "Date and time format "; country.dateTimeFormat
- PRINT "Currency symbol "; country.currencySymbol
- PRINT "Thousands separator "; country.thousandsSeparator
- PRINT "Decimal separator "; country.decimalSeparator
- PRINT "Date separator "; country.dateSeparator
- PRINT "Time separator "; country.timeSeparator
- PRINT "Currency before symbol "; country.currencyThenSymbol
- PRINT "Currency symbol space "; country.currencySymbolSpace
- PRINT "Currency decimal places"; country.currencyPlaces
- PRINT "24-hour time "; country.hours24
- PRINT "Case map segment "; country.caseMapSegment
- PRINT "Case map offset "; country.caseMapOffset
- PRINT "Data list separator "; country.dataListSeparator
-
- ' Let's translate lowercase characters for the current country
- PRINT
- PRINT "TranslateCountry$:"
- FOR i% = 128 TO 175
- a$ = a$ + CHR$(i%)
- NEXT i%
- PRINT "Character codes 128 to 175, before and after translation... "
- PRINT a$
- PRINT TranslateCountry$(a$, country)
-
- ' Wait for user
- PRINT
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
- CLS
-
- ' Demonstrate the SetDirectory and GetDirectory routines
- PRINT
- PRINT "GetDirectory$ and SetDirectory:"
- path$ = GetDirectory$(drive$)
- PRINT "Current directory is "; path$
- SetDirectory GetDrive$ + "\", result%
- PRINT "Now the directory is "; GetDirectory$(drive$)
- SetDirectory path$, result%
- PRINT "Now the directory is "; GetDirectory$(drive$)
-
- ' Write to a file or device
- PRINT
- PRINT "WriteToDevice:"
- PRINT "Writing a 'bell' character to the CRT"
- WriteToDevice 1, CHR$(7), result%
- t$ = TIME$
- DO
- LOOP UNTIL t$ <> TIME$
- PRINT "Writing a 'bell' character to the printer"
- WriteToDevice 4, CHR$(7), result%
-
- ' Wait for user
- PRINT
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
- CLS
-
- ' Demonstrate the GetFileAttributes and SetFileAttributes routines
- PRINT
- PRINT "GetFileAttributes and SetFileAttributes:"
- DIM attr AS FileAttributesType
- fileName$ = "C:\IBMDOS.COM"
- GetFileAttributes fileName$, attr
- PRINT "File attributes for "; fileName$
- PRINT "Result of call "; attr.result
- PRINT "Read only "; attr.readOnly
- PRINT "Hidden "; attr.hidden
- PRINT "System "; attr.systemFile
- PRINT "Archive "; attr.archive
- PRINT
- attr.hidden = 0
- SetFileAttributes fileName$, attr
- GetFileAttributes fileName$, attr
- PRINT "File attributes for "; fileName$
- PRINT "Result of call "; attr.result
- PRINT "Read only "; attr.readOnly
- PRINT "Hidden "; attr.hidden
- PRINT "System "; attr.systemFile
- PRINT "Archive "; attr.archive
- PRINT
- attr.hidden = 1
- SetFileAttributes fileName$, attr
- GetFileAttributes fileName$, attr
- PRINT "File attributes for "; fileName$
- PRINT "Result of call "; attr.result
- PRINT "Read only "; attr.readOnly
- PRINT "Hidden "; attr.hidden
- PRINT "System "; attr.systemFile
- PRINT "Archive "; attr.archive
- PRINT
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: BufferedKeyInput$
-
- Calls the MS-DOS Buffered Keyboard Input routine, which is similar in
- concept to QuickBASIC's LINE INPUT statement but contains some useful
- differences.
-
- When you call the BufferedKeyInput$ function, you pass an integer that
- tells the MS-DOS routine the maximum number of characters to be input. If
- extra characters are typed, the computer beeps, and the keystrokes are
- ignored. The Backspace and Left arrow keys allow editing of the input, and
- the screen is constantly updated to display the input buffer at the
- current cursor location.
-
- The returned string is always n% characters in length, even if the user
- entered fewer than n% characters. If necessary, the string is padded on
- the right with spaces to bring the length up to n%.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BufferedKeyInput$ **
- ' ** Type: Function **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calls the "Buffered Keyboard Input" MS-DOS function
- ' and returns the entered string of characters.
- '
- ' EXAMPLE OF USE: x$ = BufferedKeyInput$(n%)
- ' PARAMETERS: buffer$ Buffer for keyboard input
- ' VARIABLES: regX Structure of type RegTypeX
- ' bufSize% Length of buffer$
- ' b$ Working copy of buffer$
- ' count% Count of characters entered
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE FUNCTION BufferedKeyInput$ (n%)
- '
- FUNCTION BufferedKeyInput$ (n%) STATIC
- DIM regX AS RegTypeX
- b$ = CHR$(n% + 1) + SPACE$(n% + 1)
- regX.ax = &HA00
- regX.ds = VARSEG(b$)
- regX.dx = SADD(b$)
- InterruptX &H21, regX, regX
- count% = ASC(MID$(b$, 2, 1))
- BufferedKeyInput$ = MID$(b$, 3, count%) + SPACE$(n% - count%)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: DOSVersion!
-
- Returns the version number of MS-DOS. Sometimes it's necessary to know the
- current version of MS-DOS before proceeding with certain MS-DOS functions.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DOSVersion! **
- ' ** Type: Function **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the version number of MS-DOS.
- '
- ' EXAMPLE OF USE: PRINT "MS-DOS Version number is "; DOSVersion!
- ' PARAMETERS: (none)
- ' VARIABLES: reg Structure of type RegType
- ' major% Integer part of the MS-DOS version number
- ' minor% Fractional part of the MS-DOS version numbe
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE FUNCTION DOSVersion! ()
- '
- FUNCTION DOSVersion! STATIC
- DIM reg AS RegType
- reg.ax = &H3000
- Interrupt &H21, reg, reg
- major% = reg.ax MOD 256
- minor% = reg.ax \ 256
- DOSVersion! = major% + minor% / 100!
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: GetCountry
-
- Returns information from MS-DOS about the current country settings. This
- information can be invaluable for programs slated to be marketed in more
- than one country. A program's data output can be modified to conform to
- the standards of each country. For example, the date 3-4-88 can refer to
- March 4th or April 3rd, depending on which part of the world you are in.
-
- The date and time format string indicates the order of the six numeric
- values that make up a given date and time.
-
- Several variables are returned to indicate the desirable way to format
- monetary values. These determine whether the currency symbol is before or
- after the monetary value, whether a space separates the two, and the
- number of decimal places to use.
-
- The currency symbol is a four-character string such as "Lira". For
- dollars, the string contains three spaces followed by a $.
-
- The thousands separator is a one-character string, usually a decimal point
- or a comma.
-
- The decimal separator is also a one-character string, usually a decimal
- point or a comma.
-
- The date separator is a one-character string such as "-" or "/".
-
- The time separator is a one-character string such as ":".
-
- The hours designation indicates whether a 24-hour format or an A.M. and
- P.M. 12-hour format is more commonly used. The CaseMap address is the
- segment and offset address of the MS-DOS character translation function.
- Refer to the TranslateCountry$ function to see how this address is used.
- (The CaseMap subprogram is discussed in Part III of this book.)
-
- The data list separator is a one-character string such as ",".
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetCountry **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns country-dependent information as defined
- ' by MS-DOS.
- '
- ' EXAMPLE OF USE: GetCountry country
- ' PARAMETERS: country Structure of type CountryType
- ' VARIABLES: regX Structure of type RegTypeX
- ' c$ Buffer for data returned from interrupt
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' TYPE CountryType
- ' DateTimeFormat AS STRING * 11
- ' CurrencySymbol AS STRING * 4
- ' ThousandsSeparator AS STRING * 1
- ' DecimalSeparator AS STRING * 1
- ' DateSeparator AS STRING * 1
- ' TimeSeparator AS STRING * 1
- ' CurrencyThenSymbol AS INTEGER
- ' CurrencySymbolSpace AS INTEGER
- ' CurrencyPlaces AS INTEGER
- ' Hours24 AS INTEGER
- ' caseMapSegment AS INTEGER
- ' caseMapOffset AS INTEGER
- ' DataListSeparator AS STRING * 1
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB GetCountry (country AS CountryType)
- '
- SUB GetCountry (country AS CountryType)
- DIM regX AS RegTypeX
- regX.ax = &H3800
- c$ = SPACE$(32)
- regX.ds = VARSEG(c$)
- regX.dx = SADD(c$)
- InterruptX &H21, regX, regX
- SELECT CASE CVI(LEFT$(c$, 2))
- CASE 0
- country.dateTimeFormat = "h:m:s m/d/y"
- CASE 1
- country.dateTimeFormat = "h:m:s d/m/y"
- CASE 2
- country.dateTimeFormat = "y/m/d h:m:s"
- CASE ELSE
- country.dateTimeFormat = "h:m:s m/d/y"
- END SELECT
- country.currencySymbol = MID$(c$, 3, 4)
- country.thousandsSeparator = MID$(c$, 8, 1)
- country.decimalSeparator = MID$(c$, 10, 1)
- country.dateSeparator = MID$(c$, 12, 1)
- country.timeSeparator = MID$(c$, 14, 1)
- country.currencyThenSymbol = ASC(MID$(c$, 16)) AND 1
- country.currencySymbolSpace = (ASC(MID$(c$, 16)) AND 2) \ 2
- country.currencyPlaces = ASC(MID$(c$, 17))
- country.hours24 = ASC(MID$(c$, 18))
- country.caseMapSegment = CVI(MID$(c$, 21, 2))
- country.caseMapOffset = CVI(MID$(c$, 19, 2))
- country.dataListSeparator = MID$(c$, 23, 1)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: GetDirectory$
-
- Returns the complete path for any drive on your system. The called MS-DOS
- function doesn't return the drive designation or the first slash,
- representing the root directory, but the GetDirectory$ function adds these
- parts to the returned string for you.
-
- For the current directory of the current, default drive, pass a null
- string. For a specific drive, pass a string containing the letter of the
- drive in the first character position. For example, GetDirectory$("A:")
- might return A:\QB4\SOURCE.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetDirectory$ **
- ' ** Type: Function **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the name of the current directory for any drive.
- '
- ' EXAMPLE OF USE: path$ = GetDirectory$(drive$)
- ' PARAMETERS: drive$ Drive of concern, or null string for defaul
- ' drive
- ' VARIABLES: regX Structure of type RegTypeX
- ' d$ Working copy of drive$
- ' p$ Buffer space for returned path
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE FUNCTION GetDirectory$ (drive$)
- '
- FUNCTION GetDirectory$ (drive$) STATIC
- DIM regX AS RegTypeX
- IF drive$ = "" THEN
- d$ = GetDrive$
- ELSE
- d$ = UCASE$(drive$)
- END IF
- drive% = ASC(d$) - 64
- regX.dx = drive%
- regX.ax = &H4700
- p$ = SPACE$(64)
- regX.ds = VARSEG(p$)
- regX.si = SADD(p$)
- InterruptX &H21, regX, regX
- p$ = LEFT$(p$, INSTR(p$, CHR$(0)) - 1)
- GetDirectory$ = LEFT$(d$, 1) + ":\" + p$
- IF regX.flags AND 1 THEN
- GetDirectory$ = ""
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: GetDiskFreeSpace
-
- Returns information about the current usage and format of a given disk
- drive's contents. The data structure of type DiskFreeSpaceType lists the
- various information returned by this subprogram. Some information, such as
- the sectors per cluster, bytes per sector, and total clusters information,
- is constant in nature, so the subprogram always returns the same value for
- a given drive. The available clusters and available bytes are the variable
- information that this subprogram returns.
-
- Probably the most important information this subprogram returns is the
- total bytes available. Call this subprogram before creating a large file
- on a disk to prevent the program from being interrupted by a "disk full"
- message. This lets you prompt the user to insert a different disk or take
- other action before any data is lost.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetDiskFreeSpace **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Get information about a drive's organization, including
- ' total number of bytes available.
- '
- ' EXAMPLE OF USE: GetDiskFreeSpace drive$, disk
- ' PARAMETERS: drive$ Disk drive designation
- ' disk Structure of type DiskFreeSpaceType
- ' VARIABLES: reg Structure of type RegType
- ' drive% Numeric drive designation
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' TYPE DiskFreeSpaceType
- ' sectorsPerCluster AS INTEGER
- ' bytesPerSector AS INTEGER
- ' clustersPerDrive AS LONG
- ' availableClusters AS LONG
- ' availableBytes AS LONG
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB GetDiskFreeSpace (drive$, disk AS DiskFreeSpaceType)
- '
- SUB GetDiskFreeSpace (drive$, disk AS DiskFreeSpaceType)
- DIM reg AS RegType
- IF drive$ <> "" THEN
- drive% = ASC(UCASE$(drive$)) - 64
- ELSE
- drive% = 0
- END IF
- IF drive% >= 0 THEN
- reg.dx = drive%
- ELSE
- reg.dx = 0
- END IF
- reg.ax = &H3600
- Interrupt &H21, reg, reg
- disk.sectorsPerCluster = reg.ax
- disk.bytesPerSector = reg.cx
- IF reg.dx >= 0 THEN
- disk.clustersPerDrive = reg.dx
- ELSE
- disk.clustersPerDrive = reg.dx + 65536
- END IF
- IF reg.bx >= 0 THEN
- disk.availableClusters = reg.bx
- ELSE
- disk.availableClusters = reg.bx + 65536
- END IF
- disk.availableBytes = disk.availableClusters * reg.ax * reg.cx
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: GetDrive$
-
- Returns a two-character string designation for the current disk drive. The
- first character is always an uppercase letter, and the second character is
- always a colon.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetDrive$ **
- ' ** Type: Function **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the current disk drive name, such as "A:".
- '
- ' EXAMPLE OF USE: drive$ = GetDrive$
- ' PARAMETERS: (none)
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegType
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE FUNCTION GetDrive$ ()
- '
- FUNCTION GetDrive$ STATIC
- DIM reg AS RegType
- reg.ax = &H1900
- Interrupt &H21, reg, reg
- GetDrive$ = CHR$((reg.ax AND &HFF) + 65) + ":"
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: GetFileAttributes
-
- Returns current attribute bits for a given file. Each file has several
- attribute bits that serve useful purposes in MS-DOS. For example, whenever
- a change is made to a file, the "archive" bit is set. The MS-DOS XCOPY
- utility can check the setting of this bit and copy only those files that
- have been modified since the last XCOPY command was given for the same set
- of files. XCOPY clears this bit when a file is copied.
-
- The "read only" attribute bit protects a file by preventing you from
- changing or deleting its contents. You can read the file, list it, or
- access it in any normal way, but the operating system will generate an
- error if you try to edit or delete it.
-
- The "hidden" attribute bit makes a file invisible to the user. A good
- example of this bit's action is shown by the module-level code that
- demonstrates this subprogram. The hidden file IBMDOS.COM has its "hidden"
- bit cleared and then reset. If you leave this bit cleared, the IBMDOS.COM
- file will show up in your root directory whenever you give the DIR
- command.
-
- DOSCALLS
-
- The "system" attribute bit marks files such as IBMBIO.COM and IBMDOS.COM
- as special system files. These two files are in the root directory of all
- your bootable disks and are necessary for MS-DOS to be able to
- successfully boot from a given disk.
-
- The variable attr.result returns a 0 if the attempt to read the file
- attribute bits was successful.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetFileAttributes **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the file attribute settings for a file.
- '
- ' EXAMPLE OF USE: GetFileAttributes fileName$, attr
- ' PARAMETERS: fileName$ Name of file
- ' attr Structure of type FileAttributesType
- ' VARIABLES: regX Structure of type RegTypeX
- ' f$ Null terminated copy of fileName$
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' TYPE FileAttributesType
- ' readOnly AS INTEGER
- ' hidden AS INTEGER
- ' systemFile AS INTEGER
- ' archive AS INTEGER
- ' result AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB GetFileAttributes (fileName$, attr AS FileAttributesType)
- '
- SUB GetFileAttributes (fileName$, attr AS FileAttributesType) STATIC
- DIM regX AS RegTypeX
- regX.ax = &H4300
- f$ = fileName$ + CHR$(0)
- regX.ds = VARSEG(f$)
- regX.dx = SADD(f$)
- InterruptX &H21, regX, regX
- IF regX.flags AND 1 THEN
- attr.result = regX.ax
- ELSE
- attr.result = 0
- END IF
- attr.readOnly = regX.cx AND 1
- attr.hidden = (regX.cx \ 2) AND 1
- attr.systemFile = (regX.cx \ 4) AND 1
- attr.archive = (regX.cx \ 32) AND 1
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: GetMediaDescriptor
-
- Returns media information about any disk drive currently defined by
- MS-DOS. For any given drive, you can determine the number of sectors per
- allocation unit, the number of bytes per sector, and the FAT
- identification byte MS-DOS uses to determine how to treat the drive. This
- information is returned by the MS-DOS function 21H.
-
- The GetDiskFreeSpace subprogram returns related information.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetMediaDescriptor **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calls the MS-DOS "Get Media Descriptor" function for
- ' the indicated drive. Results are returned in a
- ' structure of type MediaDescriptorType.
- '
- ' EXAMPLE OF USE: GetMediaDescriptor drive$, desc
- ' PARAMETERS: drive$ Drive designation, such as "A:"
- ' desc Structure of type MediaDescriptorType
- ' VARIABLES: regX Structure of type RegTypeX
- ' drive% Numeric drive designation
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' TYPE MediaDescriptorType
- ' sectorsPerAllocationUnit AS INTEGER
- ' bytesPerSector AS INTEGER
- ' FATIdentificationByte AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB GetMediaDescriptor (drive$, desc AS MediaDescriptorType)
- '
- SUB GetMediaDescriptor (drive$, desc AS MediaDescriptorType) STATIC
- DIM regX AS RegTypeX
- IF drive$ <> "" THEN
- drive% = ASC(UCASE$(drive$)) - 64
- ELSE
- drive% = 0
- END IF
- IF drive% >= 0 THEN
- regX.dx = drive%
- ELSE
- regX.dx = 0
- END IF
- regX.ax = &H1C00
- InterruptX &H21, regX, regX
- desc.sectorsPerAllocationUnit = regX.ax AND &HFF
- desc.bytesPerSector = regX.cx
- DEF SEG = regX.ds
- desc.FATIdentificationByte = PEEK(regX.bx)
- DEF SEG
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: GetVerifyState%
-
- Returns the current setting of the MS-DOS Verify flag. If Verify is on,
- this function returns a 1. If Verify is off, a 0 is returned.
-
- See the SetVerifyState subprogram to see how to set the Verify on or off
- as desired.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetVerifyState% **
- ' ** Type: Function **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the current state of the MS-DOS "Verify After
- ' Write" flag.
- '
- ' EXAMPLE OF USE: state% = GetVerifyState%
- ' PARAMETERS: (none)
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE FUNCTION GetVerifyState% ()
- '
- FUNCTION GetVerifyState% STATIC
- DIM reg AS RegType
- reg.ax = &H5400
- Interrupt &H21, reg, reg
- GetVerifyState% = reg.ax AND &HFF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SetDirectory
-
- Sets the current directory for the default drive in the same way as the
- MS-DOS CHDIR command.
-
- For example, to cause a program to change to the directory C:\TXT, use
- this program statement:
-
-
- SetDirectory "C:\TXT", result%
-
- The returned value of result% indicates whether the attempt to change the
- directory was successful. If result% is 0, the directory change was
- successful.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SetDirectory **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets the current directory.
- '
- ' EXAMPLE OF USE: SetDirectory path$, result%
- ' PARAMETERS: path$ The path to the directory
- ' result% Returned error code, zero if successful
- ' VARIABLES: regX Structure of type RegTypeX
- ' p$ Null terminated copy of path$
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB SetDirectory (path$, result%)
- '
- SUB SetDirectory (path$, result%) STATIC
- DIM regX AS RegTypeX
- regX.ax = &H3B00
- p$ = path$ + CHR$(0)
- regX.ds = VARSEG(p$)
- regX.dx = SADD(p$)
- InterruptX &H21, regX, regX
- IF regX.flags AND 1 THEN
- result% = regX.ax
- ELSE
- result% = 0
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SetDrive
-
- Lets a QuickBASIC program change the current disk drive. Another way of
- doing the same thing would be to use the SHELL statement:
-
-
- SHELL "CD " + d$
-
- However, this subprogram is much more efficient and much faster.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SetDrive **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calls MS-DOS to set the current drive.
- '
- ' EXAMPLE OF USE: SetDrive d$
- ' PARAMETERS: d$ Drive designation, such as "A:"
- ' VARIABLES: reg Structure of type RegType
- ' drive% Numeric value of drive
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB SetDrive (drive$)
- '
- SUB SetDrive (drive$) STATIC
- DIM reg AS RegType
- IF drive$ <> "" THEN
- drive% = ASC(UCASE$(drive$)) - 65
- ELSE
- drive% = 0
- END IF
- IF drive% >= 0 THEN
- reg.dx = drive%
- ELSE
- reg.dx = 0
- END IF
- reg.ax = &HE00
- Interrupt &H21, reg, reg
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SetFileAttributes
-
- Sets the file attribute bits for a file as desired. For example, to make a
- file invisible to the user, set the "hidden" attribute bit. To protect a
- file from accidentally being modified or deleted, set the "read only"
- attribute bit.
-
- The GetFileAttributes subprogram describes these file attribute bits in
- more detail.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SetFileAttributes **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets attribute bits for a file.
- '
- ' EXAMPLE OF USE: SetFileAttributes fileName$, attr
- ' PARAMETERS: fileName$ Name of file
- ' attr Structure of type FileAttributesType
- ' VARIABLES: regX Structure of type RegTypeX
- ' f$ Null terminated copy of fileName$
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' TYPE FileAttributesType
- ' readOnly AS INTEGER
- ' hidden AS INTEGER
- ' systemFile AS INTEGER
- ' archive AS INTEGER
- ' result AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB SetFileAttributes (fileName$, attr AS FileAttributesType)
- '
- SUB SetFileAttributes (fileName$, attr AS FileAttributesType)
- DIM regX AS RegTypeX
- regX.ax = &H4301
- IF attr.readOnly THEN
- regX.cx = 1
- ELSE
- regX.cx = 0
- END IF
- IF attr.hidden THEN
- regX.cx = regX.cx + 2
- END IF
- IF attr.systemFile THEN
- regX.cx = regX.cx + 4
- END IF
- IF attr.archive THEN
- regX.cx = regX.cx + 32
- END IF
- f$ = fileName$ + CHR$(0)
- regX.ds = VARSEG(f$)
- regX.dx = SADD(f$)
- InterruptX &H21, regX, regX
- IF regX.flags AND 1 THEN
- attr.result = regX.ax
- ELSE
- attr.result = 0
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SetVerifyState
-
- Sets or clears the write verify flag MS-DOS uses during disk file writing,
- duplicating the actions of the MS-DOS commands VERIFY ON and VERIFY OFF.
- If a parameter (state%) of 0 is passed to the routine, the subprogram sets
- the Verify state to off. If non-zero, it sets it to on.
-
- To determine the current setting of the Verify flag, use the
- GetVerifyState% function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SetVerifyState **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets or clears the "Verify After Write" MS-DOS flag.
- '
- ' EXAMPLE OF USE: SetVerifyState state%
- ' PARAMETERS: state% If 0, resets Verify; If non-zero,
- ' then sets Verify on
- ' VARIABLES: reg Structure of type RegType
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB Interrupt (intnum%, inreg AS RegType, outreg AS RegTyp
- ' DECLARE SUB SetVerifyState (state%)
- '
- SUB SetVerifyState (state%) STATIC
- DIM reg AS RegType
- IF state% THEN
- reg.ax = &H2E01
- ELSE
- reg.ax = &H2E00
- END IF
- Interrupt &H21, reg, reg
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: TranslateCountry$
-
- Returns the translated version of the string passed to it, according to
- the current MS-DOS country setting. Only characters with byte values in
- the range 128 through 255 are candidates for translation.
-
- Before calling this function, you must call the GetCountry subprogram to
- fill in the structure of type GetCountryType with the address of the
- translation routine in the operating system. This housekeeping is all
- taken care of automatically if you only remember to call GetCountry
- before calling TranslateCountry$.
-
- The TranslateCountry$ function calls an assembly-language subprogram named
- CaseMap to translate each character of the passed string. CaseMap
- demonstrates the powerful DECLARE statement of QuickBASIC. ( CaseMap is
- discussed in Part III of this book.) Notice that the segment% and offset%
- variables representing the address of the MS-DOS translation routine are
- passed by value rather than by address, the default.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: TranslateCountry$ **
- ' ** Type: Function **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string of characters translated according to
- ' the current country setting of MS-DOS.
- '
- ' EXAMPLE OF USE: b$ = TranslateCountry$(a$, country)
- ' PARAMETERS: a$ String to be translated
- ' country Structure of type CountryType
- ' VARIABLES: i% Index to each character of a$
- ' c% Byte value of each character in a$
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE CountryType
- ' DateTimeFormat AS STRING * 11
- ' CurrencySymbol AS STRING * 4
- ' ThousandsSeparator AS STRING * 1
- ' DecimalSeparator AS STRING * 1
- ' DateSeparator AS STRING * 1
- ' TimeSeparator AS STRING * 1
- ' CurrencyThenSymbol AS INTEGER
- ' CurrencySymbolSpace AS INTEGER
- ' CurrencyPlaces AS INTEGER
- ' Hours24 AS INTEGER
- ' caseMapSegment AS INTEGER
- ' caseMapOffset AS INTEGER
- ' DataListSeparator AS STRING * 1
- ' END TYPE
- '
- ' DECLARE SUB CaseMap (character%, BYVAL Segment%, BYVAL Offset
- ' DECLARE FUNCTION TranslateCountry$ (a$, country AS CountryTyp
- '
- FUNCTION TranslateCountry$ (a$, country AS CountryType) STATIC
- FOR i% = 1 TO LEN(a$)
- c% = ASC(MID$(a$, i%))
- CaseMap c%, country.caseMapSegment, country.caseMapOffset
- MID$(a$, i%, 1) = CHR$(c%)
- NEXT i%
- TranslateCountry$ = a$
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: WriteToDevice
-
- Outputs a string of bytes or characters to any device or file. QuickBASIC
- provides comprehensive input and output capabilities and should be used
- whenever possible. This routine is for those rare instances when accessing
- the MS-DOS output routines is of benefit. For example, the STDOUT toolbox
- is a good example of the use of the MS-DOS level code for output.
- QuickBASIC PRINT statements bypass the extended screen and keyboard
- control device named ANSI.SYS. Using this WriteToDevice subprogram (or the
- routines in the STDOUT toolbox) lets you use the ANSI.SYS driver's
- capabilities.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: WriteToDevice **
- ' ** Type: Subprogram **
- ' ** Module: DOSCALLS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Writes bytes to a file or device.
- '
- ' EXAMPLE OF USE: WriteToDevice handle%, a$, result%
- ' PARAMETERS: handle% File or device handle
- ' a$ String to be output
- ' result% Error code returned from MS-DOS
- ' VARIABLES: regX Structure of type RegTypeX
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB WriteToDevice (handle%, a$, result%)
- '
- SUB WriteToDevice (handle%, a$, result%) STATIC
- DIM regX AS RegTypeX
- regX.ax = &H4000
- regX.cx = LEN(a$)
- regX.bx = handle%
- regX.ds = VARSEG(a$)
- regX.dx = SADD(a$)
- InterruptX &H21, regX, regX
- IF regX.flags AND 1 THEN
- result% = regX.ax
- ELSEIF regX.ax <> LEN(a$) THEN
- result% = -1
- ELSE
- result% = 0
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- EDIT
-
- The EDIT toolbox is a collection of subprograms for line and screen input
- of strings. The EditLine subprogram allows full input editing on a single
- line, and the EditBox subprogram allows user input and editing inside a
- rectangular area of the screen. The DrawBox, FormatTwo, and
- InsertCharacter subprograms enhance the capabilities of the EditBox
- routine and provide capabilities that can be useful in themselves.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- EDIT.BAS Demo module
- DrawBox Sub Creates a double-lined box on the display
- EditBox Sub Allows editing in a boxed area of the
- screen
- EditLine Sub Allows editing of string at cursor
- position
- FormatTwo Sub Splits string into two strings
- InsertCharacter Sub Inserts a character
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: EDIT
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: EDIT **
- ' ** Type: Toolbox **
- ' ** Module: EDIT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: EDIT.BAS
- ' KEYS.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: a$ String to be edited by the user
-
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Key code numbers
- CONST BACKSPACE = 8
- CONST CTRLLEFTARROW = 29440
- CONST CTRLRIGHTARROW = 29696
- CONST CTRLY = 25
- CONST CTRLQ = 17
- CONST DELETE = 21248
- CONST DOWNARROW = 20480
- CONST ENDKEY = 20224
- CONST ENTER = 13
- CONST ESCAPE = 27
- CONST HOME = 18176
- CONST INSERTKEY = 20992
- CONST LEFTARROW = 19200
- CONST RIGHTARROW = 19712
- CONST TABKEY = 9
- CONST UPARROW = 18432
-
- ' Functions
- DECLARE FUNCTION KeyCode% ()
-
- ' Subprograms
- DECLARE SUB EditLine (a$, exitCode%)
- DECLARE SUB DrawBox (row1%, col1%, row2%, col2%)
- DECLARE SUB EditBox (a$, row1%, col1%, row2%, col2%)
- DECLARE SUB FormatTwo (a$, b$, col%)
- DECLARE SUB InsertCharacter (x$(), kee$, cp%, rp%, wide%, high%)
-
- ' Demonstrate the EditLine subprogram
- a$ = " Edit this line, and then press Up arrow, Down arrow, or Enter "
- CLS
- COLOR 14, 1
- EditLine a$, exitCode%
- COLOR 7, 0
- PRINT
- PRINT
- PRINT "Result of edit ..."
- COLOR 14, 0
- PRINT a$
- COLOR 7, 0
- PRINT
- SELECT CASE exitCode%
- CASE 0
- PRINT "Enter";
- CASE -1
- PRINT "Down arrow";
- CASE 1
- PRINT "Up arrow";
- CASE ELSE
- END SELECT
- PRINT " key pressed."
-
- ' Demonstrate the EditBox subprogram
- a$ = "Now, edit text inside this box. Press "
- a$ = a$ + "Esc to end the editing..."
- COLOR 12, 1
- DrawBox 8, 17, 19, 57
- COLOR 11, 1
- EditBox a$, 8, 17, 19, 57
- LOCATE 21, 1
- COLOR 7, 0
- PRINT "Result..."
- COLOR 14, 0
- PRINT a$
- COLOR 7, 0
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: DrawBox
-
- Draws a rectangular, double-lined box on the screen. No attempt is made to
- save the screen contents under the box area, and no control of the
- character colors is provided. The DrawBox subprogram simply provides a
- fast, flexible way to get a rectangular area of the screen cleared and
- outlined using the current foreground and background color settings. Use
- the COLOR statement before calling this subprogram if you want to change
- the foreground and background colors.
-
- The WINDOWS.BAS module provides a more comprehensive method of creating
- and removing windows for information and menuing tasks.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DrawBox **
- ' ** Type: Subprogram **
- ' ** Module: EDIT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Draws a double-lined box.
- '
- ' EXAMPLE OF USE: DrawBox row1%, col1%, row2%, col2%
- ' PARAMETERS: row1% Screen text row at upper left corner of the b
- ' col1% Screen text column at upper left corner of th
- ' row2% Screen text row at lower right corner of the
- ' col2% Screen text column at lower right corner of t
- ' box
- ' VARIABLES: wide% Inside width of box
- ' row3% Loop row number for creating sides of box
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB DrawBox (row1%, col1%, row2%, col2%)
- '
- SUB DrawBox (row1%, col1%, row2%, col2%) STATIC
-
- ' Determine inside width of box
- wide% = col2% - col1% - 1
-
- ' Across the top
- LOCATE row1%, col1%, 0
- PRINT CHR$(201);
- PRINT STRING$(wide%, 205);
- PRINT CHR$(187);
-
- ' Down the sides
- FOR row3% = row1% + 1 TO row2% - 1
- LOCATE row3%, col1%, 0
- PRINT CHR$(186);
- PRINT SPACE$(wide%);
- PRINT CHR$(186);
- NEXT row3%
-
- ' Across the bottom
- LOCATE row2%, col1%, 0
- PRINT CHR$(200);
- PRINT STRING$(wide%, 205);
- PRINT CHR$(188);
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: EditBox
-
- Lets a user input and edit string characters in a rectangular area of the
- screen. This routine doesn't draw a box around the area on the display,
- but you can easily create one by calling the DrawBox subprogram before
- calling EditBox.
-
- This subprogram is a simple text editor. Features include automatic
- wordwrap and reformatting, line insert and delete, and support of many of
- the same editing keys used in the QuickBASIC editing environment. The keys
- acted upon are Left arrow, Right arrow, Up arrow, Down arrow, Home, End,
- Insert, Backspace, Delete, Ctrl-Y, Ctrl-Q-Y, Ctrl-Right arrow, Ctrl-Left
- arrow, Enter, and Escape.
-
- You can force a reformat of the entire rectangular area by moving the
- cursor to the upper left corner of the rectangular area and then pressing
- the Backspace key. The cursor won't move anywhere, but all text in the
- area will be reformatted.
-
- To escape from the editing mode, press the Escape key. The string result
- of the edit is returned in a$ to the calling program. Note that linefeeds
- and all double spaces are removed from a$ and that a$ is trimmed of spaces
- from each end before being returned.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: EditBox **
- ' ** Type: Subprogram **
- ' ** Module: EDIT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Allows the user to edit text inside a rectangular area.
- '
- ' EXAMPLE OF USE: EditBox a$, row1%, col1%, row2%, col2%
- ' PARAMETERS: a$ String to be edited
- ' row1% Screen text row at upper left corner of the are
- ' col1% Screen text column at upper left corner of the
- ' row2% Screen text row at lower right corner of the ar
- ' col2% Screen text column at lower right corner of the
- ' VARIABLES: r1% Upper inside row of rectangular area
- ' r2% Lower inside row of rectangular area
- ' c1% Left inside column of rectangular area
- ' c2% Right inside column of rectangular area
- ' wide% Width of area
- ' high% Height of area
- ' rp% Index to current working row
- ' cp% Index to current working column
- ' insert% Flag for insert/replace mode
- ' quit% Flag for quitting the subprogram
- ' across% Saved current cursor column
- ' down% Saved current cursor row
- ' x$() Workspace string array
- ' i% Looping index
- ' b$ Works with a$ to format a$ into x$()
- ' keyNumber% Integer code for any key press
- ' c$ Temporary string workspace
- ' ds% Index to double-space groupings
- ' sp% Index to character where split of string is to oc
- ' ctrlQflag% Indicates Ctrl-Q has been pressed
- ' kee$ Character entered from keyboard
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION KeyCode% ()
- ' DECLARE SUB EditBox ($, row1%, col1%, row2%, col2%)
- ' DECLARE SUB FormatTwo (a$, b$, col%)
- ' DECLARE SUB InsertCharacter (x$(), kee$, cp%, rp%,
- ' wide%, high%)
- '
- SUB EditBox (a$, row1%, col1%, row2%, col2%) STATIC
-
- ' Set up some working variables
- r1% = row1% + 1
- r2% = row2% - 1
- c1% = col1% + 2
- c2% = col2% - 2
- wide% = c2% - c1% + 1
- high% = r2% - r1% + 1
- rp% = 1
- cp% = 1
- insert% = TRUE
- quit% = FALSE
-
- ' Record the current cursor location
- across% = POS(0)
- down% = CSRLIN
-
- ' Dimension a workspace array
- REDIM x$(1 TO high%)
-
- ' Format a$ into array space
- FOR i% = 1 TO high%
- FormatTwo a$, b$, wide%
- x$(i%) = a$
- a$ = b$
- NEXT i%
-
- ' Display the strings
- FOR i% = 1 TO high%
- LOCATE r1% + i% - 1, c1%, 0
- PRINT x$(i%);
- NEXT i%
-
- ' Process each keystroke
- DO
-
- ' Update the current line
- LOCATE r1% + rp% - 1, c1%, 0
- PRINT x$(rp%);
-
- ' Place the cursor
- IF insert% THEN
- LOCATE r1% + rp% - 1, c1% + cp% - 1, 1, 6, 7
- ELSE
- LOCATE r1% + rp% - 1, c1% + cp% - 1, 1, 1, 7
- END IF
-
- ' Grab next keystroke
- keyNumber% = KeyCode%
-
- ' Process the key
- SELECT CASE keyNumber%
-
- CASE INSERTKEY
- IF insert% THEN
- insert% = FALSE
- ELSE
- insert% = TRUE
- END IF
-
- CASE BACKSPACE
-
- ' Rub out character to the left
- IF cp% > 1 THEN
- x$(rp%) = x$(rp%) + " "
- b$ = LEFT$(x$(rp%), cp% - 2)
- c$ = MID$(x$(rp%), cp%)
- x$(rp%) = b$ + c$
- cp% = cp% - 1
-
- ' Upper left corner, so reformat the whole box
- ELSEIF rp% = 1 THEN
-
- ' Pull all the strings together
- a$ = ""
- FOR i% = 1 TO high%
- a$ = a$ + LTRIM$(RTRIM$(x$(i%))) + " "
- NEXT i%
-
- ' Remove double spaces
- ds% = INSTR(a$, " ")
- DO WHILE ds%
- a$ = LEFT$(a$, ds% - 1) + MID$(a$, ds% + 1)
- ds% = INSTR(a$, " ")
- LOOP
-
- ' Format into the array and display lines
- FOR i% = 1 TO high%
- FormatTwo a$, b$, wide%
- x$(i%) = a$
- a$ = b$
- LOCATE r1% + i% - 1, c1%, 0
- PRINT x$(i%);
- NEXT i%
-
- ' Concatenate to the preceding line
- ELSE
-
- ' Use the InsertCharacter sub to insert a space
- rp% = rp% - 1
- cp% = wide% + 1
- InsertCharacter x$(), " ", rp%, cp%, wide%, high%
-
- ' Remove the extra spaces introduced
- IF cp% > 2 THEN
- b$ = LEFT$(x$(rp%), cp% - 3)
- c$ = MID$(x$(rp%), cp%)
- ELSE
- b$ = ""
- c$ = MID$(x$(rp%), cp% + 1)
- END IF
-
- ' Pull the line pieces together
- x$(rp%) = LEFT$(b$ + c$ + SPACE$(3), wide%)
-
- ' Adjust the cursor position
- cp% = cp% - 1
-
- ' Display the lines
- FOR i% = 1 TO high%
- LOCATE r1% + i% - 1, c1%, 0
- PRINT x$(i%);
- NEXT i%
- END IF
-
- CASE DELETE
- x$(rp%) = x$(rp%) + " "
- b$ = LEFT$(x$(rp%), cp% - 1)
- c$ = MID$(x$(rp%), cp% + 1)
- x$(rp%) = b$ + c$
-
- CASE UPARROW
- IF rp% > 1 THEN
- rp% = rp% - 1
- END IF
-
- CASE DOWNARROW
- IF rp% < high% THEN
- rp% = rp% + 1
- END IF
-
- CASE LEFTARROW
- IF cp% > 1 THEN
- cp% = cp% - 1
- END IF
-
- CASE RIGHTARROW
- IF cp% < wide% THEN
- cp% = cp% + 1
- END IF
-
- CASE ENTER
- IF rp% < high% AND x$(high%) = SPACE$(wide%) THEN
-
- ' Shuffle lines down
- FOR i% = high% TO rp% + 1 STEP -1
- x$(i%) = x$(i% - 1)
- NEXT i%
-
- ' Split current line at cursor
- sp% = wide% - cp% + 1
- IF sp% THEN
- MID$(x$(rp%), cp%, sp%) = SPACE$(sp%)
- END IF
-
- ' Move to next line
- rp% = rp% + 1
- x$(rp%) = MID$(x$(rp%), cp%) + SPACE$(cp% - 1)
- cp% = 1
-
- ' Display the modified lines
- FOR i% = rp% - 1 TO high%
- LOCATE r1% + i% - 1, c1%, 0
- PRINT x$(i%);
- NEXT i%
-
- ELSE
-
- ' Nowhere to push things down
- BEEP
-
- END IF
-
- CASE HOME
- cp% = 1
-
- CASE ENDKEY
- cp% = wide% + 1
-
- ' Move back to just after last character
- IF x$(rp%) <> SPACE$(wide%) THEN
- DO UNTIL MID$(x$(rp%), cp% - 1, 1) <> " "
- cp% = cp% - 1
- LOOP
- ELSE
- cp% = 1
- END IF
-
- CASE CTRLRIGHTARROW
-
- ' Find next space
- DO UNTIL MID$(x$(rp%), cp%, 1) = " " OR cp% = wide%
- cp% = cp% + 1
- LOOP
-
- ' Find first non-space character
- DO UNTIL MID$(x$(rp%), cp%, 1) <> " " OR cp% = wide%
- cp% = cp% + 1
- LOOP
-
- CASE CTRLLEFTARROW
-
- ' Find first space to the left
- DO UNTIL MID$(x$(rp%), cp%, 1) = " " OR cp% = 1
- cp% = cp% - 1
- LOOP
-
- ' Find first non-space character to the left
- DO UNTIL MID$(x$(rp%), cp%, 1) <> " " OR cp% = 1
- cp% = cp% - 1
- LOOP
-
- ' Find next space to the left
- DO UNTIL MID$(x$(rp%), cp%, 1) = " " OR cp% = 1
- cp% = cp% - 1
- LOOP
-
- ' Adjust cursor position to first non-space character
- IF cp% > 1 THEN
- cp% = cp% + 1
- END IF
-
- CASE CTRLY
- IF rp% < high% THEN
- ' Shuffle lines up, spacing out the last
- FOR i% = rp% TO high%
- IF i% < high% THEN
- x$(i%) = x$(i% + 1)
- ELSE
- x$(i%) = SPACE$(wide%)
- END IF
- LOCATE r1% + i% - 1, c1%, 0
- PRINT x$(i%);
- NEXT i%
- END IF
-
- ' Move cursor to far left
- cp% = 1
-
- CASE CTRLQ
- ctrlQflag% = TRUE
-
- CASE ESCAPE
- quit% = TRUE
-
- CASE IS > 255
- SOUND 999, 1
-
- CASE IS < 32
- SOUND 999, 1
-
- CASE ELSE
- kee$ = CHR$(keyNumber%)
-
- ' Insert mode
- IF insert% THEN
- InsertCharacter x$(), kee$, rp%, cp%, wide%, high%
- FOR i% = 1 TO high%
- LOCATE r1% + i% - 1, c1%, 0
- PRINT x$(i%);
- NEXT i%
-
- ' Must be overstrike mode
- ELSE
- MID$(x$(rp%), cp%, 1) = kee$
- IF cp% < wide% + 1 THEN
- cp% = cp% + 1
- ELSE
- IF rp% < high% THEN
- LOCATE r1% + rp% - 1, c1%, 0
- PRINT x$(rp%);
- rp% = rp% + 1
- cp% = 1
- END IF
- END IF
- END IF
-
- ' Correct for bottom right corner problem
- IF rp% > high% THEN
- cp% = wide%
- rp% = high%
- END IF
-
- ' Check for Ctrl-Q-Y combination (del to end of line)
- IF kee$ = "y" AND ctrlQflag% THEN
- cp% = cp% - 1
- IF cp% = 0 THEN
- cp% = wide%
- rp% = rp% - 1
- END IF
- sp% = wide% - cp% + 1
- MID$(x$(rp%), cp%, sp%) = SPACE$(sp%)
- END IF
-
- ' Clear out the possible Ctrl-Q signal
- ctrlQflag% = FALSE
-
- END SELECT
-
- LOOP UNTIL quit%
-
- ' Concatenate the array strings to form the result
- a$ = ""
- FOR i% = 1 TO high%
- a$ = a$ + " " + LTRIM$(RTRIM$(x$(i%)))
- NEXT i%
-
- ' Remove double spaces
- ds% = INSTR(a$, " ")
- DO WHILE ds%
- a$ = LEFT$(a$, ds% - 1) + MID$(a$, ds% + 1)
- ds% = INSTR(a$, " ")
- LOOP
-
- ' Trim both ends of spaces
- a$ = LTRIM$(RTRIM$(a$))
-
- ' Restore original cursor position
- LOCATE down%, across%, 1
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: EditLine
-
- Allows the user to edit a single line of text. The string is displayed at
- the current cursor location using the current foreground and background
- colors. Many of the same editing keys from the QuickBASIC editing
- environment are supported in the expected manner. For example, pressing
- Ctrl-Right arrow moves the cursor to the start of the next word, and
- pressing Ctrl-Q-Y deletes to the end of the line. Insert and overstrike
- modes are both supported, and you can delete characters by pressing the
- Delete or Backspace key.
-
- To exit the editing, press the Enter, Up arrow, or Down arrow key. The
- exitCode% value is set to 0, 1, or -1 respectively, allowing your calling
- program to determine which key terminated the editing.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: EditLine **
- ' ** Type: Subprogram **
- ' ** Module: EDIT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Allows the user to edit a string at the current cursor position
- ' on the screen. Keys acted upon are Ctrl-Y, Ctrl-Q-Y, Right arrow,
- ' Left arrow, Ctrl-Left arrow, Ctrl-Right arrow, Home, End,
- ' Insert, Escape, Backspace, and Delete.
- ' Pressing Enter, Up arrow, or Down arrow terminates
- ' the subprogram and returns exitCode% of 0, +1, or -1.
- '
- ' EXAMPLE OF USE: EditLine a$, exitCode%
- ' PARAMETERS: a$ String to be edited
- ' exitCode% Returned code indicating the terminating
- ' key press
- ' VARIABLES: row% Saved current cursor row
- ' col% Saved current cursor column
- ' length% Length of a$
- ' ptr% Location of cursor during the editing
- ' insert% Insert mode toggle
- ' quit% Flag for quitting the editing
- ' original$ Saved copy of starting a$
- ' keyNumber% Integer code for any key press
- ' ctrlQflag% Indicates Ctrl-Q key press
- ' kee$ Character of key just pressed
- ' sp% Length of space string
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION KeyCode% ()
- ' DECLARE SUB EditLine (a$, exitCode%)
- '
- SUB EditLine (a$, exitCode%) STATIC
-
- ' Set up some variables
- row% = CSRLIN
- col% = POS(0)
- length% = LEN(a$)
- ptr% = 0
- insert% = TRUE
- quit% = FALSE
- original$ = a$
-
- ' Main processing loop
- DO
-
- ' Display the line
- LOCATE row%, col%, 0
- PRINT a$;
-
- ' Show appropriate cursor type
- IF insert% THEN
- LOCATE row%, col% + ptr%, 1, 6, 7
- ELSE
- LOCATE row%, col% + ptr%, 1, 1, 7
- END IF
-
- ' Get next keystroke
- keyNumber% = KeyCode%
-
- ' Process the key
- SELECT CASE keyNumber%
-
- CASE INSERTKEY
- IF insert% THEN
- insert% = FALSE
- ELSE
- insert% = TRUE
- END IF
-
- CASE BACKSPACE
- IF ptr% THEN
- a$ = a$ + " "
- a$ = LEFT$(a$, ptr% - 1) + MID$(a$, ptr% + 1)
- ptr% = ptr% - 1
- END IF
-
- CASE DELETE
- a$ = a$ + " "
- a$ = LEFT$(a$, ptr%) + MID$(a$, ptr% + 2)
-
- CASE UPARROW
- exitCode% = 1
- quit% = TRUE
-
- CASE DOWNARROW
- exitCode% = -1
- quit% = TRUE
-
- CASE LEFTARROW
- IF ptr% THEN
- ptr% = ptr% - 1
- END IF
-
- CASE RIGHTARROW
- IF ptr% < length% - 1 THEN
- ptr% = ptr% + 1
- END IF
-
- CASE ENTER
- exitCode% = 0
- quit% = TRUE
-
- CASE HOME
- ptr% = 0
-
- CASE ENDKEY
- ptr% = length% - 1
-
- CASE CTRLRIGHTARROW
- DO UNTIL MID$(a$, ptr% + 1, 1) = " " OR ptr% = length% - 1
- ptr% = ptr% + 1
- LOOP
- DO UNTIL MID$(a$, ptr% + 1, 1) <> " " OR ptr% = length% - 1
- ptr% = ptr% + 1
- LOOP
-
- CASE CTRLLEFTARROW
- DO UNTIL MID$(a$, ptr% + 1, 1) = " " OR ptr% = 0
- ptr% = ptr% - 1
- LOOP
- DO UNTIL MID$(a$, ptr% + 1, 1) <> " " OR ptr% = 0
- ptr% = ptr% - 1
- LOOP
- DO UNTIL MID$(a$, ptr% + 1, 1) = " " OR ptr% = 0
- ptr% = ptr% - 1
- LOOP
- IF ptr% THEN
- ptr% = ptr% + 1
- END IF
-
- CASE CTRLY
- a$ = SPACE$(length%)
- ptr% = 0
-
- CASE CTRLQ
- ctrlQflag% = TRUE
-
- CASE ESCAPE
- a$ = original$
- ptr% = 0
- insert% = TRUE
-
- CASE IS > 255
- SOUND 999, 1
-
- CASE IS < 32
- SOUND 999, 1
-
- CASE ELSE
-
- ' Convert key code to character string
- kee$ = CHR$(keyNumber%)
-
- ' Insert or overstrike
- IF insert% THEN
- a$ = LEFT$(a$, ptr%) + kee$ + MID$(a$, ptr% + 1)
- a$ = LEFT$(a$, length%)
- ELSE
- IF ptr% < length% THEN
- MID$(a$, ptr% + 1, 1) = kee$
- END IF
- END IF
-
- ' Are we up against the wall?
- IF ptr% < length% THEN
- ptr% = ptr% + 1
- ELSE
- SOUND 999, 1
- END IF
-
- ' Special check for Ctrl-Q-Y (del to end of line)
- IF kee$ = "y" AND ctrlQflag% THEN
- IF ptr% <= length% THEN
- sp% = length% - ptr% + 1
- MID$(a$, ptr%, sp%) = SPACE$(sp%)
- ptr% = ptr% - 1
- END IF
- END IF
-
- ' Clear out the Ctrl-Q signal
- ctrlQflag% = FALSE
-
- END SELECT
-
- LOOP UNTIL quit%
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FormatTwo
-
- Formats text lines to a given maximum length. The value of col% is used to
- find a point in a$ where a$ can be split into two strings between words.
- The length of the returned a$ will be less than or equal to col%, and the
- rest of the original a$ will be returned in b$.
-
- Notice that repeated calls to this subprogram can format an entire
- paragraph of text. An example of this is shown in the subprogram EditBox.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FormatTwo **
- ' ** Type: Subprogram **
- ' ** Module: EDIT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Splits a string into two strings between words,
- ' and with spaces padded to the first string to bring it to
- ' length, col%.
- '
- ' EXAMPLE OF USE: FormatTwo a$, b$, col%
- ' PARAMETERS: a$ String to be split
- ' b$ Returns the tail of the string
- ' col% Maximum length of a$ after being split
- ' VARIABLES: ptr% Pointer to split point in a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB FormatTwo (a$, b$, col%)
- '
- SUB FormatTwo (a$, b$, col%) STATIC
-
- ' Be sure string is long enough
- a$ = a$ + SPACE$(col%)
-
- ' Look for rightmost space
- ptr% = col% + 1
- DO WHILE MID$(a$, ptr%, 1) <> " " AND ptr% > 1
- ptr% = ptr% - 1
- LOOP
-
- ' Do the split
- IF ptr% = 1 THEN
- b$ = MID$(a$, col% + 1)
- a$ = LEFT$(a$, col%)
- ELSE
- b$ = MID$(a$, ptr% + 1)
- a$ = LEFT$(a$, ptr% - 1)
- END IF
-
- ' Pad the first string with spaces to length col%
- a$ = LEFT$(a$ + SPACE$(col%), col%)
-
- ' Trim extra spaces from end of second string
- b$ = RTRIM$(b$)
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: InsertCharacter
-
- Inserts a character into the array of text being maintained by the
- EditBox subprogram. While in Insert mode, the EditBox subprogram calls
- InsertCharacter. The character insertion is simple enough, but this
- subprogram also handles the chore of performing automatic wordwrap and
- formatting.
-
- This task of character insertion could have been performed in the
- EditBox subprogram, but breaking the code out into a separate subprogram
- makes it much easier to isolate this task from the others. One great
- advantage of QuickBASIC is the ability to break complex programming tasks
- into smaller, more manageable tasks.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: InsertCharacter **
- ' ** Type: Subprogram **
- ' ** Module: EDIT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Handles the task of inserting a character
- ' for the EditBox subprogram.
- '
- ' EXAMPLE OF USE: InsertCharacter x$(), kee$, rp%, cp%, wide%, high%
- ' PARAMETERS: x$() Array in EditBox where character is to be
- ' inserted
- ' kee$ Character to be inserted
- ' rp% Row location of insert
- ' cp% Column location of insert
- ' wide% Width of rectangular area being edited
- ' high% Height of rectangular area being edited
- ' VARIABLES: dum$ Marker character
- ' b$ String from array at insertion point
- ' c$ Right part of string at insertion point
- ' i% Looping index
- ' ds% Position in string of double spaces
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB InsertCharacter (x$(), kee$, cp%, rp%,
- ' wide%, high%)
- '
- SUB InsertCharacter (x$(), kee$, rp%, cp%, wide%, high%) STATIC
-
- ' First, insert a dummy character as a marker
- dum$ = CHR$(255)
- b$ = LEFT$(x$(rp%), cp% - 1)
- c$ = MID$(x$(rp%), cp%)
- b$ = b$ + dum$ + c$
-
- ' If end of string is a space, then drop it
- IF RIGHT$(b$, 1) = " " THEN
- x$(rp%) = LEFT$(b$, wide%)
-
- ' Otherwise, need to adjust the lines
- ELSE
-
- ' If not in the last line, then tack them all together
- IF rp% < high% THEN
- FOR i% = rp% + 1 TO high%
- b$ = b$ + " " + x$(i%)
- NEXT i%
- END IF
-
- ' Trim both ends
- b$ = LTRIM$(RTRIM$(b$))
-
- ' Remove all double spaces
- ds% = INSTR(b$, " ")
- DO WHILE ds%
- b$ = LEFT$(b$, ds% - 1) + MID$(b$, ds% + 1)
- ds% = INSTR(b$, " ")
- LOOP
-
- ' Reformat the lines
- FOR i% = rp% TO high%
- FormatTwo b$, c$, wide%
- x$(i%) = b$
- b$ = c$
- NEXT i%
-
- END IF
-
- ' Find out where that dummy character is now
- FOR rp% = 1 TO high%
- cp% = INSTR(x$(rp%), dum$)
- IF cp% THEN
- EXIT FOR
- END IF
- NEXT rp%
-
- ' Replace the dummy character with the keystroke character
- IF cp% THEN
- MID$(x$(rp%), cp%, 1) = kee$
- END IF
-
- ' Increment the cursor location
- IF cp% < wide% + 1 THEN
- cp% = cp% + 1
- ELSE
- IF rp% < high% THEN
- cp% = 1
- rp% = rp% + 1
- END IF
- END IF
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- ERROR
-
- The ERROR toolbox contains a single subprogram that displays an error
- message in a box. If you have a color monitor, you can make the display
- quite eye-catching. In this example, the message is yellow on a red
- background.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- ERROR.BAS Demo module
- ErrorMessage Sub Error message display
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: ERROR
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ERROR **
- ' ** Type: Toolbox **
- ' ** Module: ERROR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
-
- ' Subprogram
- DECLARE SUB ErrorMessage (message$)
-
- ' Demonstrate the subprogram
-
- ErrorMessage "This is a sample message for ErrorMessage"
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ErrorMessage
-
- Provides a convenient, noticeable way to display error messages.
-
- QuickBASIC has a built-in mechanism for terminating a program when a
- serious error occurs. For example, if you try to divide by 0, the program
- immediately halts and displays the message Division by zero.
-
- In other situations, you might want to terminate a program because of a
- serious error that QuickBASIC would otherwise let pass. One approach in
- such a situation would be to use QuickBASIC's ERROR n% statement. This
- works fine, but unless one of the built-in error messages happens to fit
- the given situation, you're stuck with the default message Unprintable
- error, which sounds ghastly.
-
- A second approach to terminating a program in a controlled way would be to
- print your own descriptive error message and then follow with the SYSTEM
- statement. In many cases this technique is sufficient, but it's preferable
- to present a more polished, eye-catching display.
-
- This subprogram lets you systematically display your own error messages in
- a unique error-message window, just before terminating and returning to
- MS-DOS. The display──in this example, a red background and bright yellow
- message──immediately lets you know that a serious error has been detected.
-
- The table of color-defining constants in this subprogram can be useful in
- any program where you use the COLOR statement. A statement such as COLOR
- YELLOW, RED is much more descriptive than the equivalent COLOR 23, 4. It
- also makes programming easier because you don't have to remember or look
- up the numbers for the various colors.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ErrorMessage **
- ' ** Type: Subprogram **
- ' ** Module: ERROR.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Displays an error message and then exits to the system.
- '
- ' EXAMPLE OF USE: ErrorMessage "This is a sample message for ErrorMessage
- ' PARAMETERS: message$ String to be displayed in the error bo
- ' VARIABLES: lm% Length of message$ during processing
- ' col% Screen character column for left edge
- ' of error box
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB ErrorMessage (message$)
- '
- SUB ErrorMessage (message$) STATIC
-
- ' Define color constants
- CONST BLACK = 0
- CONST BLUE = 1
- CONST GREEN = 2
- CONST CYAN = 3
- CONST RED = 4
- CONST MAGENTA = 5
- CONST BROWN = 6
- CONST WHITE = 7
- CONST BRIGHT = 8
- CONST BLINK = 16
- CONST YELLOW = BROWN + BRIGHT
-
- ' Trim off spaces on each end of message
- message$ = LTRIM$(RTRIM$(message$))
-
- ' Make message length an odd number
- IF LEN(message$) MOD 2 = 0 THEN
- message$ = message$ + " "
- END IF
-
- ' Minimum length of message is 9 characters
- DO WHILE LEN(message$) < 9
- message$ = " " + message$ + " "
- LOOP
-
- ' Maximum length of message is 75
- message$ = LEFT$(message$, 75)
-
- ' Initialization of display
- SCREEN 0
- WIDTH 80
- CLS
-
- ' Calculate screen locations
- lm% = LEN(message$)
- col% = 38 - lm% \ 2
-
- ' Create the error box
- COLOR RED + BRIGHT, RED
- LOCATE 9, col%
- PRINT CHR$(201); STRING$(lm% + 2, 205); CHR$(187)
- LOCATE 10, col%
- PRINT CHR$(186); SPACE$(lm% + 2); CHR$(186)
- LOCATE 11, col%
- PRINT CHR$(186); SPACE$(lm% + 2); CHR$(186)
- LOCATE 12, col%
- PRINT CHR$(200); STRING$(lm% + 2, 205); CHR$(188)
-
- ' The title
- COLOR CYAN + BRIGHT, RED
- LOCATE 10, 36
- PRINT "* ERROR *";
-
- ' The message$
- COLOR YELLOW, RED
- LOCATE 11, col% + 2
- PRINT message$;
-
- ' System will prompt for "any key"
- COLOR WHITE, BLACK
- LOCATE 22, 1
- SYSTEM
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- FIGETPUT
-
- The FIGETPUT toolbox demonstrates the FileGet$ function and FilePut
- subprogram, routines that allow efficient binary-mode access to files up
- to 32767 bytes in length. Because each of these routines uses binary-file
- mode, an entire file can be read by one GET statement or written by one
- PUT statement. Any type of file containing no more than 32767 bytes can be
- read into or written from a QuickBASIC string variable by these routines.
- When reading an ASCII file, the FileGet$ function returns all lines of
- the file in one string. A carriage return/line feed pair of characters
- marks the separation of each line in the file.
-
- These routines can be useful for file-processing utility programs, such as
- byte-for-byte file comparisons, text searches, and file ciphering.
-
- To demonstrate the routines, the module-level code reads a copy of itself
- into a single string, converts all characters to uppercase, counts the
- occurrences of each letter of the alphabet, and saves the resulting string
- in a file named FIGETPUT.TST. For a meaningful character count save
- FIGETPUT.BAS in ASCII format.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- FIGETPUT.BAS Demo module
- FileGet$ Func Returns a string with contents of file
- FilePut Sub Writes contents of string into binary
- file
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: FIGETPUT
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FIGETPUT **
- ' ** Type: Toolbox **
- ' ** Module: FIGETPUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reads itself (FIGETPUT.BAS) into a string,
- ' converts characters to uppercase, counts occurrences of
- ' the characters "A" through "Z," and saves the
- ' result in a file named FIGETPUT.TST.
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: filename
- ' VARIABLES: count%() Tally array for the 26 alpha characters
- ' fileName$ Name of file to be processed
- ' a$ Contents of the file
- ' i% Looping index
- ' c% ASCII value of each file byte
-
- ' Functions
- DECLARE FUNCTION FileGet$ (fileName$)
-
- ' Subprograms
- DECLARE SUB FilePut (fileName$, a$)
-
- ' Dimension array of counts for each ASCII code "A" to "Z"
- DIM count%(65 TO 90)
-
- ' Read in the file (must be no greater than 32767 bytes long)
- a$ = FileGet$("FIGETPUT.BAS")
-
- ' Convert to uppercase
- a$ = UCASE$(a$)
-
- ' Count the letters
- FOR i% = 1 TO LEN(a$)
- c% = ASC(MID$(a$, i%, 1))
- IF c% >= 65 AND c% <= 90 THEN
- count%(c%) = count%(c%) + 1
- END IF
- NEXT i%
-
- ' Output the results
- CLS
- PRINT "Alphabetic character count for FIGETPUT.BAS"
- PRINT
- FOR i% = 65 TO 90
- PRINT CHR$(i%); " -"; count%(i%),
- NEXT i%
-
- ' Write out the new file
- FilePut "FIGETPUT.TST", a$
-
- ' All done
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: FileGet$
-
- Uses the binary file mode to read the contents of any MS-DOS file into a
- string variable. The file length must be fewer than 32768 bytes to fit in
- one string. If you try to read a larger file, an error message is
- displayed, and the program halts.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FileGet$ **
- ' ** Type: Function **
- ' ** Module: FIGETPUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string containing the contents of a file.
- ' Maximum file length is 32767 bytes.
- '
- ' EXAMPLE OF USE: a$ = FileGet$(fileName$)
- ' PARAMETERS: fileName$ Name of file to be accessed
- ' VARIABLES: fileNumber Next available free file number
- ' length& Length of file
- ' a$ String for binary read of file
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION FileGet$ (fileName$)
- '
- FUNCTION FileGet$ (fileName$) STATIC
- fileNumber = FREEFILE
- OPEN fileName$ FOR BINARY AS #fileNumber
- length& = LOF(fileNumber)
- IF length& <= 32767 THEN
- a$ = SPACE$(length&)
- GET #fileNumber, , a$
- FileGet$ = a$
- a$ = ""
- ELSE
- PRINT "FileGet$()... file too large"
- SYSTEM
- END IF
- CLOSE #fileNumber
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FilePut
-
- Writes the contents of any string variable to a file using binary file
- mode. The biggest file that you can create in this way is 32767 bytes
- because that's the longest string you can build.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FilePut **
- ' ** Type: Subprogram **
- ' ** Module: FIGETPUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Writes contents of a$ into a binary file named fileName$.
- '
- ' EXAMPLE OF USE: FilePut fileName$, a$
- ' PARAMETERS: fileName$ Name of file to be written
- ' a$ Bytes to be placed in the file
- ' VARIABLES: fileNumber Next available free file number
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB FilePut (fileName$, a$)
- '
- SUB FilePut (fileName$, a$) STATIC
-
- ' Find available file number
- fileNumber = FREEFILE
-
- ' Truncate any previous contents
- OPEN fileName$ FOR OUTPUT AS #fileNumber
- CLOSE #fileNumber
-
- ' Write string to file
- OPEN fileName$ FOR BINARY AS #fileNumber
- PUT #fileNumber, , a$
-
- ' All done
- CLOSE #fileNumber
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- FILEINFO
-
- The FILEINFO toolbox contains subprograms that obtain directory
- information about files. Basically, this program mimics the MS-DOS DIR
- command or the QuickBASIC FILES command.
-
- As set up, this program finds normal file entries. You can change the
- FILEATTRIBUTE constant to access other types of files. Refer to the CONST
- statements that define the various file attribute bits.
-
- The starting path$ for the search is set to the current directory, but you
- can change the path$ assignment to search any desired drive or directory.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- FILEINFO.BAS Demo module
- FindFirstFile Sub Finds first file that matches parameter
- FindNextFile Sub Locates next file that matches parameter
- GetFileData Sub Extracts file directory information
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: FILEINFO
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FILEINFO **
- ' ** Type: Toolbox **
- ' ** Module: FILEINFO.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Collection of subprograms and functions for accessing
- ' directory information about files.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: MIXED.QLB/.LIB
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: path$ Path to files for gathering directory
- ' information; wildcard characters accepted
- ' dta$ Disk transfer area buffer string
- ' result% Code returned as result of directory search
- ' file Structure of type FileDataType
- ' n% File count
-
- ' File search attribute bits
- CONST ISNORMAL = 0
- CONST ISREADONLY = 1
- CONST ISHIDDEN = 2
- CONST ISSYSTEM = 4
- CONST ISVOLUMELABEL = 8
- CONST ISSUBDIRECTORY = 16
- CONST ISARCHIVED = 32
-
- ' Here we'll search for normal files and subdirectories
- CONST FILEATTRIBUTE = ISNORMAL + ISSUBDIRECTORY
-
- TYPE RegTypeX
- ax AS INTEGER
- bx AS INTEGER
- cx AS INTEGER
- dx AS INTEGER
- bp AS INTEGER
- si AS INTEGER
- di AS INTEGER
- flags AS INTEGER
- ds AS INTEGER
- es AS INTEGER
- END TYPE
-
- TYPE FileDataType
- finame AS STRING * 12
- year AS INTEGER
- month AS INTEGER
- day AS INTEGER
- hour AS INTEGER
- minute AS INTEGER
- second AS INTEGER
- attribute AS INTEGER
- size AS LONG
- END TYPE
-
- ' Subprograms
- DECLARE SUB INTERRUPTX (intnum%, inreg AS RegTypeX, outreg AS RegTypeX)
- DECLARE SUB FindFirstFile (path$, dta$, result%)
- DECLARE SUB FindNextFile (dta$, result%)
- DECLARE SUB GetFileData (dta$, file AS FileDataType)
-
- ' Data structures
- DIM file AS FileDataType
-
- ' For demonstration purposes, list current directory
- CLS
- path$ = "*.*"
-
- ' Always start by finding the first match
- FindFirstFile path$, dta$, result%
-
- ' Check that the path$ got us off to a good start
- IF result% THEN
- PRINT "Error: FindFirstFile - found no match for path$"
- SYSTEM
- END IF
-
- ' List all the files in this directory
- DO
- IF n% MOD 19 = 0 THEN
- CLS
- PRINT TAB(4); "File"; TAB(18); "Date"; TAB(29); "Time";
- PRINT TAB(39); "Size"; TAB(48); "Attributes"
- PRINT
- END IF
- GetFileData dta$, file
- PRINT file.finame;
- PRINT USING " ##/##/####"; file.month, file.day, file.year;
- PRINT USING " ##:##:##"; file.hour, file.minute, file.second;
- PRINT USING " ########"; file.size;
- PRINT USING " &"; RIGHT$("0" + HEX$(file.attribute), 2)
- PRINT " &H";
- PRINT USING "&"; RIGHT$("0" + HEX$(file.attribute), 2)
- n% = n% + 1
- FindNextFile dta$, result%
- IF n% MOD 19 = 0 THEN
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP WHILE INKEY$ = ""
- END IF
- LOOP UNTIL result%
- PRINT
- PRINT n%; "files found"
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FindFirstFile
-
- Finds the first directory entry that matches a given path$. This
- subprogram is called once before FindNextFile is called numerous times to
- find the rest of the entries.
-
- The result of this file search is returned in the dta$ variable. Call the
- GetFileData subprogram to extract the information from the string.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FindFirstFile **
- ' ** Type: Subprogram **
- ' ** Module: FILEINFO.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Finds first file that matches the path$.
- '
- ' EXAMPLE OF USE: FindFirstFile path$, dta$, result%
- ' PARAMETERS: path$ Complete path, including wildcard character
- ' desired, for the directory search
- ' dta$ Disk transfer area buffer space
- ' result% Returned result code for the search
- ' VARIABLES: reg Structure of type RegTypeX
- ' thePath$ Null terminated version of path$
- ' sgmt% Current DTA address segment
- ' ofst% Current DTA address offset
- ' MODULE LEVEL
- ' DECLARATIONS: File search attribute bits
- ' CONST ISNORMAL = 0
- ' CONST ISREADONLY = 1
- ' CONST ISHIDDEN = 2
- ' CONST ISSYSTEM = 4
- ' CONST ISVOLUMELABEL = 8
- ' CONST ISSUBDIRECTORY = 16
- ' CONST ISARCHIVED = 32
- '
- ' CONST FILEATTRIBUTE = ISNORMAL + ISSUBDIRECTORY
- '
- ' TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB INTERRUPTX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB FindFirstFile (path$, dta$, result%)
- '
- SUB FindFirstFile (path$, dta$, result%) STATIC
-
- ' Initialization
- DIM reg AS RegTypeX
-
- ' The path must be a null terminated string
- thePath$ = path$ + CHR$(0)
-
- ' Get current DTA address
- reg.ax = &H2F00
- INTERRUPTX &H21, reg, reg
- sgmt% = reg.es
- ofst% = reg.bx
-
- ' Set dta address
- dta$ = SPACE$(43)
- reg.ax = &H1A00
- reg.ds = VARSEG(dta$)
- reg.dx = SADD(dta$)
- INTERRUPTX &H21, reg, reg
-
- ' Find first file match
- reg.ax = &H4E00
- reg.cx = FILEATTRIBUTE
- reg.ds = VARSEG(thePath$)
- reg.dx = SADD(thePath$)
- INTERRUPTX &H21, reg, reg
-
- ' The carry flag tells if a file was found or not
- result% = reg.flags AND 1
-
- ' Reset the original DTA
- reg.ax = &H1A00
- reg.ds = sgmt%
- reg.dx = ofst%
- INTERRUPTX &H21, reg, reg
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FindNextFile
-
- Continues the search for file directory entries after the FindFirstFile
- subprogram was called once. This subprogram is usually called repeatedly
- until all files that match the original path$ are found. The value of
- result% is 0 until the last file is found.
-
- The dta$ variable carries the important information about the search from
- call to call of this subprogram. Be careful not to alter its contents
- between calls to this routine. To extract details about each file's
- directory entry, pass dta$ to the subprogram GetFileData.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FindNextFile **
- ' ** Type: Subprogram **
- ' ** Module: FILEINFO.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Locates next file. FindFirstFile must be called
- ' before this subprogram is called.
- '
- ' EXAMPLE OF USE: FindNextFile dta$, result%
- ' PARAMETERS: dta$ Previously filled-in Disk Transfer Area
- ' buffer string
- ' result% Result code for the search
- ' VARIABLES: reg Structure of type RegTypeX
- ' thePath$ Null terminated version of path$
- ' sgmt% Current DTA address segment
- ' ofst% Current DTA address offset
- ' MODULE LEVEL
- ' DECLARATIONS: CONST ISNORMAL = 0
- ' CONST ISREADONLY = 1
- ' CONST ISHIDDEN = 2
- ' CONST ISSYSTEM = 4
- ' CONST ISVOLUMELABEL = 8
- ' CONST ISSUBDIRECTORY = 16
- ' CONST ISARCHIVED = 32
- '
- ' CONST FILEATTRIBUTE = ISNORMAL + ISSUBDIRECTORY
- '
- ' TYPE RegTypeX
- ' ax AS INTEGER
- ' bx AS INTEGER
- ' cx AS INTEGER
- ' dx AS INTEGER
- ' bp AS INTEGER
- ' si AS INTEGER
- ' di AS INTEGER
- ' flags AS INTEGER
- ' ds AS INTEGER
- ' es AS INTEGER
- ' END TYPE
- '
- ' DECLARE SUB INTERRUPTX (intnum%, inreg AS RegTypeX, outreg AS RegType
- ' DECLARE SUB FindNextFile (dta$, result%)
- '
- SUB FindNextFile (dta$, result%) STATIC
-
- ' Initialization
- DIM reg AS RegTypeX
-
- ' Be sure dta$ was built (FindFirstFile should have been called)
- IF LEN(dta$) <> 43 THEN
- result% = 2
- EXIT SUB
- END IF
-
- ' Get current DTA address
- reg.ax = &H2F00
- INTERRUPTX &H21, reg, reg
- sgmt% = reg.es
- ofst% = reg.bx
-
- ' Set dta address
- reg.ax = &H1A00
- reg.ds = VARSEG(dta$)
- reg.dx = SADD(dta$)
- INTERRUPTX &H21, reg, reg
-
- ' Find next file match
- reg.ax = &H4F00
- reg.cx = FILEATTRIBUTE
- reg.ds = VARSEG(thePath$)
- reg.dx = SADD(thePath$)
- INTERRUPTX &H21, reg, reg
-
- ' The carry flag tells whether a file was found or not
- result% = reg.flags AND 1
-
- ' Reset the original DTA
- reg.ax = &H1A00
- reg.ds = sgmt%
- reg.dx = ofst%
- INTERRUPTX &H21, reg, reg
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: GetFileData
-
- Extracts the information about a file's directory entry from the variable
- dta$ passed back from calls to FindFirstFile and FindNextFile. The
- information is returned in the data structure of type FileDataType and
- includes the date and time of the last file update, the filename, the file
- size, and the file attribute byte.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GetFileData **
- ' ** Type: Subprogram **
- ' ** Module: FILEINFO.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Extracts the file directory information from a Disk
- ' Transfer Area (dta$) that has been filled in by a
- ' call to either FindFirstFile or FindNextFile.
- '
- ' EXAMPLE OF USE: GetFileData dta$, file
- ' PARAMETERS: dta$ Disk Transfer Area buffer string passed bac
- ' either FindFirstFile or FindNextFile
- ' VARIABLES: tim& Time stamp of the file
- ' dat& Date stamp of the file
- ' f$ Filename during extraction
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE FileDataType
- ' finame AS STRING * 12
- ' year AS INTEGER
- ' month AS INTEGER
- ' day AS INTEGER
- ' hour AS INTEGER
- ' minute AS INTEGER
- ' second AS INTEGER
- ' attribute AS INTEGER
- ' size AS LONG
- ' END TYPE
- '
- ' DECLARE SUB GetFileData (dta$, file AS FileDataType)
- '
- SUB GetFileData (dta$, file AS FileDataType) STATIC
-
- file.attribute = ASC(MID$(dta$, 22, 1))
- tim& = CVI(MID$(dta$, 23, 2))
- IF tim& < 0 THEN
- tim& = tim& + 65536
- END IF
- file.second = tim& AND &H1F
- file.minute = (tim& \ 32) AND &H3F
- file.hour = (tim& \ 2048) AND &H1F
- dat& = CVI(MID$(dta$, 25, 2))
- file.day = dat& AND &H1F
- file.month = (dat& \ 32) AND &HF
- file.year = ((dat& \ 512) AND &H1F) + 1980
- file.size = CVL(MID$(dta$, 27, 4))
- f$ = MID$(dta$, 31) + CHR$(0)
- file.finame = LEFT$(f$, INSTR(f$, CHR$(0)) - 1)
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- FRACTION
-
- The FRACTION toolbox is a set of subprograms and functions for working
- with fractions. The fractions are handled as data structures, defined by
- the TYPE statement in the module-level code. This effectively allows
- fractions, comprising a pair of long integer numerator and denominator
- numbers, to be referenced as a new type of variable.
-
- The demo module displays examples of the LeastComMul& and
- GreatestComDiv& functions and then prompts you to enter fraction problems
- involving the addition, subtraction, multiplication, or division of two
- fractions. Enter the problems using the format displayed on screen. The
- results, reduced to lowest terms, will be displayed.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- FRACTION.BAS Demo module
- Fraction2String$ Func Converts type Fraction variable to a
- string
- FractionAdd Sub Adds two fractions and reduces
- FractionDiv Sub Divides two fractions and reduces
- FractionMul Sub Multiplies two fractions and reduces
- FractionReduce Sub Reduces fraction to lowest terms
- FractionSub Sub Subtracts two fractions and reduces
- GreatestComDiv& Func Returns greatest common divisor
- LeastComMul& Func Returns least common multiple
- SplitFractions Sub Parses fraction problem string
- String2Fraction Sub Converts a string to Fraction variable
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: FRACTION
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FRACTION **
- ' ** Type: Toolbox **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates a collection of functions and subprograms
- ' for working with fractions.
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: a Structure of type Fraction
- ' b Structure of type Fraction
- ' c Structure of type Fraction
- ' f$ Input string for fraction problems
- ' fa$ First fraction in string format
- ' fb$ Second fraction in string format
- ' operator$ Function indicator
- ' fc$ Resultant fraction in string output form
-
- ' Data structure definitions
- TYPE Fraction
- Num AS LONG
- Den AS LONG
- END TYPE
-
- ' Subprograms
- DECLARE SUB FractionReduce (a AS Fraction)
- DECLARE SUB String2Fraction (f$, a AS Fraction)
- DECLARE SUB FractionAdd (a AS Fraction, b AS Fraction, c AS Fraction)
- DECLARE SUB FractionDiv (a AS Fraction, b AS Fraction, c AS Fraction)
- DECLARE SUB FractionMul (a AS Fraction, b AS Fraction, c AS Fraction)
- DECLARE SUB FractionSub (a AS Fraction, b AS Fraction, c AS Fraction)
- DECLARE SUB SplitFractions (f$, fa$, operator$, fb$)
-
- ' Functions
- DECLARE FUNCTION Fraction2String$ (a AS Fraction)
- DECLARE FUNCTION GreatestComDiv& (n1&, n2&)
- DECLARE FUNCTION LeastComMul& (n1&, n2&)
-
- ' Data structures
- DIM a AS Fraction
- DIM b AS Fraction
- DIM c AS Fraction
-
- ' Demonstrate the LeastComMul& function
- CLS
- PRINT "LeastComMul&(21&, 49&) =", LeastComMul&(21&, 49&)
- PRINT
-
- ' Demonstrate the GreatestComDiv& function
- PRINT "GreatestComDiv&(21&, 49&) =", GreatestComDiv&(21&, 49&)
- PRINT
-
- ' Demonstrate the fraction routines
- DO
- PRINT
- PRINT "Enter a fraction problem, or simply press Enter"
- PRINT "Example: 2/3 + 4/5"
- PRINT
- LINE INPUT f$
- IF INSTR(f$, "/") = 0 THEN
- EXIT DO
- END IF
- SplitFractions f$, fa$, operator$, fb$
- String2Fraction fa$, a
- String2Fraction fb$, b
- SELECT CASE operator$
- CASE "+"
- FractionAdd a, b, c
- CASE "-"
- FractionSub a, b, c
- CASE "*"
- FractionMul a, b, c
- CASE "/"
- FractionDiv a, b, c
- CASE ELSE
- BEEP
- END SELECT
- fc$ = Fraction2String$(c)
- PRINT "Result (reduced to lowest terms) is "; fc$
- LOOP
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Fraction2String$
-
- Returns a string representation of a fraction. The numerator and
- denominator values are converted to strings by the QuickBASIC STR$
- function, and a slash (/) is concatenated between them to form the
- resultant string.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Fraction2String$ **
- ' ** Type: Function **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts a type Fraction variable to a string.
- '
- ' EXAMPLE OF USE: fa$ = Fraction2String$(a)
- ' PARAMETERS: a Structure of type Fraction
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Fraction
- ' Num AS LONG
- ' Den AS LONG
- ' END TYPE
- '
- ' DECLARE FUNCTION Fraction2String$ (a AS Fraction)
- '
- FUNCTION Fraction2String$ (a AS Fraction) STATIC
- Fraction2String$ = STR$(a.Num) + "/" + STR$(a.Den)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FractionAdd
-
- Adds fraction a to fraction b, reduces the result to lowest terms, and
- returns the result in fraction c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FractionAdd **
- ' ** Type: Subprogram **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Adds two fractions and reduces the result to lowest terms.
- '
- ' EXAMPLE OF USE: FractionAdd a, b, c
- ' PARAMETERS: a First fraction to add
- ' b Second fraction to add
- ' c Resulting fraction
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Fraction
- ' Num AS LONG
- ' Den AS LONG
- ' END TYPE
- '
- ' DECLARE SUB FractionReduce (a AS Fraction)
- ' DECLARE SUB FractionAdd (a AS Fraction, b AS Fraction, c AS Fractio
- ' DECLARE FUNCTION GreatestComDiv& (n1&, n2&)
- '
- SUB FractionAdd (a AS Fraction, b AS Fraction, c AS Fraction)
- c.Num = a.Num * b.Den + a.Den * b.Num
- c.Den = a.Den * b.Den
- FractionReduce c
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FractionDiv
-
- Divides fraction b into fraction a, reduces the result to lowest terms,
- and returns the result in fraction c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FractionDiv **
- ' ** Type: Subprogram **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Divides two fractions and reduces the result to
- ' lowest terms.
- '
- ' EXAMPLE OF USE: FractionDiv a, b, c
- ' PARAMETERS: a First fraction
- ' b Fraction to divide into first
- ' c Resulting fraction
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Fraction
- ' Num AS LONG
- ' Den AS LONG
- ' END TYPE
- ' DECLARE SUB FractionReduce (a AS Fraction)
- ' DECLARE SUB FractionDiv (a AS Fraction, b AS Fraction, c AS Fractio
- ' DECLARE FUNCTION GreatestComDiv& (n1&, n2&)
- '
- SUB FractionDiv (a AS Fraction, b AS Fraction, c AS Fraction)
- c.Num = a.Num * b.Den
- c.Den = a.Den * b.Num
- FractionReduce c
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FractionMul
-
- Multiplies fraction a times fraction b, reduces the result to lowest
- terms, and returns the result in fraction c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FractionMul **
- ' ** Type: Subprogram **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Multiplies two fractions and reduces the result to
- ' lowest terms.
- '
- ' EXAMPLE OF USE: FractionMul a, b, c
- ' PARAMETERS: a First fraction to multiply
- ' b Second fraction to multiply
- ' c Resulting fraction
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Fraction
- ' Num AS LONG
- ' Den AS LONG
- ' END TYPE
- '
- ' DECLARE SUB FractionReduce (a AS Fraction)
- ' DECLARE SUB FractionMul (a AS Fraction, b AS Fraction, c AS Fractio
- ' DECLARE FUNCTION GreatestComDiv& (n1&, n2&)
- '
- SUB FractionMul (a AS Fraction, b AS Fraction, c AS Fraction)
- c.Num = a.Num * b.Num
- c.Den = a.Den * b.Den
- FractionReduce c
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FractionReduce
-
- Reduces a fraction to its lowest terms by dividing the numerator and
- denominator by their greatest common divisor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FractionReduce **
- ' ** Type: Subprogram **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reduces a fraction to its lowest terms.
- '
- ' EXAMPLE OF USE: FractionReduce a
- ' PARAMETERS: a Fraction to reduce
- ' VARIABLES: d& Greatest common divisor of the numerator an
- ' denominator
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Fraction
- ' Num AS LONG
- ' Den AS LONG
- ' END TYPE
- '
- ' DECLARE SUB FractionReduce (a AS Fraction)
- ' DECLARE FUNCTION GreatestComDiv& (n1&, n2&)
- '
- SUB FractionReduce (a AS Fraction)
- d& = GreatestComDiv&(a.Num, a.Den)
- a.Num = a.Num / d&
- a.Den = a.Den / d&
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FractionSub
-
- Subtracts fraction b from fraction a, reduces the result to lowest terms,
- and returns the result in fraction c.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FractionSub **
- ' ** Type: Subprogram **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Subtracts two fractions and reduces the result to
- ' lowest terms.
- '
- ' EXAMPLE OF USE: FractionSub a, b, c
- ' PARAMETERS: a First fraction
- ' b Fraction to subtract from the first
- ' c Resulting fraction
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE Fraction
- ' Num AS LONG
- ' Den AS LONG
- ' END TYPE
- '
- ' DECLARE SUB FractionReduce (a AS Fraction)
- ' DECLARE SUB FractionSub (a AS Fraction, b AS Fraction, c AS Fractio
- ' DECLARE FUNCTION GreatestComDiv& (n1&, n2&)
- '
- SUB FractionSub (a AS Fraction, b AS Fraction, c AS Fraction)
- c.Num = a.Num * b.Den - a.Den * b.Num
- c.Den = a.Den * b.Den
- FractionReduce c
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: GreatestComDiv&
-
- Returns the greatest common divisor of two long integers.
-
- The greatest common divisor of the numerator and denominator of a fraction
- is efficient for reducing the fraction to its lowest terms, as
- demonstrated by the FractionReduce subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GreatestComDiv& **
- ' ** Type: Function **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the greatest common divisor of two long integers.
- '
- ' EXAMPLE OF USE: gcd& = GreatestComDiv& (n1&, n2&)
- ' PARAMETERS: n1& First long integer
- ' n2& Second long integer
- ' VARIABLES: ta& Working copy of n1&
- ' tb& Working copy of n2&
- ' tc& Working variable
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION GreatestComDiv& (n1&, n2&)
- '
- FUNCTION GreatestComDiv& (n1&, n2&)
- ta& = n1&
- tb& = n2&
- DO
- tc& = ta& MOD tb&
- ta& = tb&
- tb& = tc&
- LOOP WHILE tc&
- GreatestComDiv& = ta&
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: LeastComMul&
-
- Returns the least common multiple of two long integers.
-
- Although this function is not used by any other routine in the
- FRACTION.BAS module, it is included because of its close ties to the
- GreatestComDiv& function. In fact, by using the GreatestComDiv& function
- in the calculations, the LeastComMul& function is shortened to one program
- line, as shown.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: LeastComMul& **
- ' ** Type: Function **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the least common multiple of two long integers.
- '
- ' EXAMPLE OF USE: lcm& = LeastComMul& (n1&, n2&)
- ' PARAMETERS: n1& First long integer
- ' n2& Second long integer
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION LeastComMul& (n1&, n2&)
- '
- FUNCTION LeastComMul& (n1&, n2&)
- LeastComMul& = ABS(n1& * n2& / GreatestComDiv&(n1&, n2&))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SplitFractions
-
- Splits the input fraction problem string into two fraction strings and one
- operator string.
-
- This subprogram has a special purpose in the FRACTION.BAS program. After
- you enter a fraction problem, this subprogram splits your input into three
- strings: a string representation of the first fraction, a one-character
- symbol representing the desired mathematical operation, and a string
- representation of the second fraction.
-
- The results of this subprogram are passed to the String2Fraction
- subprogram before the indicated calculations are performed.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SplitFractions **
- ' ** Type: Subprogram **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Splits an input fraction problem string into
- ' three strings representing each of the two
- ' fractions and a one-character string of the
- ' operation given.
- '
- ' EXAMPLE OF USE: SplitFractions f$, fa$, operator$, fb$
- ' PARAMETERS: f$ Input string from the FRACTIONS demonstratio
- ' program
- ' fa$ First fraction, extracted from f$
- ' operator$ Mathematical operation symbol, from f$
- ' fb$ Second fraction, extracted from f$
- ' VARIABLES: i% Looping index
- ' ndx% Index to mathematical operation symbol
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB SplitFractions (f$, fa$, operator$, fb$)
- '
- SUB SplitFractions (f$, fa$, operator$, fb$)
- fa$ = ""
- fb$ = ""
- operator$ = ""
- FOR i% = 1 TO 4
- ndx% = INSTR(f$, MID$("+-*/", i%, 1))
- IF ndx% THEN
- IF i% = 4 THEN
- ndx% = INSTR(ndx% + 1, f$, "/")
- END IF
- fa$ = LEFT$(f$, ndx% - 1)
- fb$ = MID$(f$, ndx% + 1)
- operator$ = MID$(f$, ndx%, 1)
- EXIT FOR
- END IF
- NEXT i%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: String2Fraction
-
- Converts a string representation of a fraction to a data structure of type
- Fraction. This routine is useful for converting user input of fractional
- values to type Fraction variables.
-
- This subprogram extracts numerator and denominator values from a string
- representation of a fraction and fills in a data structure of type
- Fraction with the results.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: String2Fraction **
- ' ** Type: Subprogram **
- ' ** Module: FRACTION.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts a string to a type Fraction variable.
- '
- ' EXAMPLE OF USE: String2Fraction f$, a
- ' PARAMETERS: f$ String representation of a fraction
- ' a Structure of type Fraction
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB String2Fraction (f$, a AS Fraction)
- '
- SUB String2Fraction (f$, a AS Fraction)
- a.Num = VAL(f$)
- a.Den = VAL(MID$(f$, INSTR(f$, "/") + 1))
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- GAMES
-
- The GAMES toolbox is a collection of subprograms and functions that
- provide some common tasks for programming games with QuickBASIC.
- QuickBASIC is an ideal language for developing many graphics- and
- text-oriented games, partly because of the interactive nature of the
- development process, and partly because of the excellent set of graphics
- functions and subprograms provided by the language.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- GAMES.BAS Demo module
- Card$ Func Returns name of card given a number from
- 1 through 52
- Collision% Func Returns TRUE or FALSE collision condition
- Dice% Func Returns total showing for throwing N dice
- FillArray Sub Fills an integer array with a sequence of
- numbers defined by the bounds
- Shuffle$ Func Randomizes character bytes in a string
- ShuffleArray Sub Randomizes integers in an array
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: GAMES
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GAMES **
- ' ** Type: Toolbox **
- ' ** Module: GAMES.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: a$ String containing the 26 letters of the
- ' alphabet
- ' x% Lower bound for array a%()
- ' y% Upper bound for array a%()
- ' a%() Array of numbers to be shuffled
- ' i% Looping index
- ' size% Dimension of bouncing ball array
- ' object%() Array for GET and PUT of bouncing ball
- ' backGround%() Array for GET and PUT of background
- ' dx% X velocity of bouncing ball
- ' dy% Y velocity of bouncing ball
- ' px% X coordinate of bouncing ball
- ' py% Y coordinate of bouncing ball
- ' testNumber% One of four bounce direction tests
- ' test% Result of the Collision% test
-
- ' Constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Functions
- DECLARE FUNCTION Shuffle$ (a$)
- DECLARE FUNCTION Dice% (numberOfDice%)
- DECLARE FUNCTION Card$ (cardNumber%)
- DECLARE FUNCTION Collision% (object%(), backGround%())
-
- ' Subprograms
- DECLARE SUB FillArray (a%())
- DECLARE SUB ShuffleArray (a%())
-
- ' Demonstration of the Shuffle$ function
- CLS
- RANDOMIZE TIMER
- a$ = "abcdefghijklmnopqrstuvwxyz"
- PRINT "a$ = "; a$
- PRINT "Shuffle$(a$) = "; Shuffle$(a$)
- PRINT
-
- ' Demonstration of the FillArray subprogram
- x% = -7
- y% = 12
- DIM a%(x% TO y%)
- PRINT "FillArray a%() where DIM a%( -7 TO 12) ..."
- FillArray a%()
- FOR i% = x% TO y%
- PRINT a%(i%);
- NEXT i%
- PRINT
-
- ' Demonstration of the ShuffleArray subprogram
- PRINT
- PRINT "ShuffleArray a%() ..."
- ShuffleArray a%()
- FOR i% = x% TO y%
- PRINT a%(i%);
- NEXT i%
- PRINT
-
- ' Demonstration of the Dice% function
- PRINT
- PRINT "Dice%(2)..."
- FOR i% = 1 TO 20
- PRINT Dice%(2);
- NEXT i%
- PRINT
-
- ' Deal a hand of seven cards
- PRINT
- PRINT "Seven random cards, without replacement..."
- REDIM a%(1 TO 54)
- FillArray a%()
- ShuffleArray a%()
- FOR i% = 1 TO 7
- PRINT Card$(a%(i%))
- NEXT i%
- PRINT
-
- ' Wait for user to press a key
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP WHILE INKEY$ = ""
-
- ' Demonstration of the Collision% function
- size% = 6
- DIM object%(size%), backGround%(size%)
-
- ' Set medium resolution graphics mode
- SCREEN 1
-
- ' Create the bouncing ball
- CIRCLE (2, 2), 2, 3
- PAINT (2, 2), 3
- GET (0, 0)-(4, 4), object%
-
- ' Make solid border around screen
- LINE (14, 18)-(305, 187), 1, B
- PAINT (0, 0), 1
-
- PRINT " Collision% function... Press any key to quit "
-
- ' Make three obstacles
- CIRCLE (115, 78), 33, 2, , , .6
- PAINT (115, 78), 2
- CIRCLE (205, 78), 33, 2, , , .6
- PAINT (205, 78), 2
- LINE (90, 145)-(230, 155), 2, BF
-
- ' Initialize position and velocity of the object
- dx% = 1
- dy% = 1
- px% = 160
- py% = 44
- PUT (px%, py%), object%
-
- ' Move the object around the screen, avoiding collisions,
- ' until any key is pressed
- DO
- testNumber% = 0
- DO
- PUT (px%, py%), object%
- px% = px% + dx%
- py% = py% + dy%
- GET (px%, py%)-(px% + 4, py% + 4), backGround%
- PUT (px%, py%), object%
- test% = Collision%(object%(), backGround%())
- IF test% THEN
- testNumber% = testNumber% + 1
- PUT (px%, py%), object%
- px% = px% - dx%
- py% = py% - dy%
- SELECT CASE testNumber%
- CASE 1
- dx% = -dx%
- CASE 2
- dx% = -dx%
- dy% = -dy%
- CASE 3
- dy% = -dy%
- CASE ELSE
- END SELECT
- PUT (px%, py%), object%
- END IF
- LOOP UNTIL test% = 0
- LOOP UNTIL INKEY$ <> ""
-
- ' Clean up a little
- SCREEN 0
- WIDTH 80
- CLS
- SYSTEM
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Card$
-
- Returns the name of a card from a standard, 52-card deck, given a number
- from 1 through 52.
-
- The passed number is first checked to determine the suit. Numbers from 1
- through 13 indicate a Spade, 14 through 26 a Club, and so on. The face
- name or the number of the card is then determined using the MOD function.
-
- If the number is less than 1 or greater than 52, this function returns
- Joker, making it convenient to deal a 54-card deck if desired.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Card$ **
- ' ** Type: Function **
- ' ** Module: GAMES.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the name of a playing card given a number
- ' from 1 to 52. Any other number returns "Joker."
- '
- ' EXAMPLE OF USE: PRINT Card$(n%)
- ' PARAMETERS: n% Number from 1 to 52 representing a card (an
- ' other number returns a Joker)
- ' VARIABLES: suit$ Name of one of the four card suits
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Card$ (cardNumber%)
- '
- FUNCTION Card$ (cardNumber%)
-
- SELECT CASE (cardNumber% - 1) \ 13 ' Which suit?
- CASE 0
- suit$ = " of Spades"
- CASE 1
- suit$ = " of Clubs"
- CASE 2
- suit$ = " of Hearts"
- CASE 3
- suit$ = " of Diamonds"
- CASE ELSE
- Card$ = "Joker"
- EXIT FUNCTION
- END SELECT
-
- SELECT CASE (cardNumber% - 1) MOD 13 ' Which card?
- CASE 0
- Card$ = "Ace" + suit$
- CASE 1 TO 9
- Card$ = MID$(STR$(cardNumber% MOD 13), 2) + suit$
- CASE 10
- Card$ = "Jack" + suit$
- CASE 11
- Card$ = "Queen" + suit$
- CASE 12
- Card$ = "King" + suit$
- END SELECT
-
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Collision%
-
- Returns -1 or 0 (TRUE or FALSE), indicating whether a collision or near
- collision has occurred between two graphics objects stored in integer
- arrays.
-
- The graphics images are copied into the arrays by using the QuickBASIC GET
- statement. If you're not familiar with using the GET and PUT statements to
- create graphics animation, refer to your QuickBASIC documentation. These
- two statements provide a powerful method for quickly moving or duplicating
- graphics objects on your screen.
-
- To use the Collision function, you must pass two integer arrays of the
- same dimension. Normally, the background is copied into one array (using
- the GET statement) just before the object stored in the second is PUT on
- the screen at that same location. These two arrays are passed to the
- Collision% function, and the returned result determines whether the object
- overlaps (or very nearly overlaps) any pixel already on the screen.
-
- The check for near collision of pixels proceeds as follows. The first
- three integers in each array are skipped, as these integers contain
- object-dimensioning information and don't represent any pixel. The
- remaining integers from each array are compared to the corresponding
- integers from the other. Pixels having color attribute 0 represent the
- background and are stored in the integer array as one or more 0 bits. If
- an integer is 0, then all the pixels it represents are of the background
- color. If an integer is non-zero, then one or more of the pixels stored in
- it have a non-zero color attribute. To make the collision check fast and
- efficient, this function simply checks for non-zero bits in any
- corresponding integers from the two arrays. The pixels might not actually
- be overlapping, but they'll be very close neighbors. If a near collision
- is detected, the remaining integers are not checked, and the function
- returns a value of TRUE. If all the integers are checked and no collisions
- are detected, the function returns FALSE.
-
- The demonstration module shows one way to use the collision function to
- allow objects to bounce off each other. The bouncing ball moves around
- quickly in the "square face," bouncing off the mouth, eyes, and screen
- edges. Try experimenting by changing the size of the mouth or eyes or by
- drawing additional objects on the screen. The ball should bounce off any
- non-zero pixel objects.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Collision% **
- ' ** Type: Function **
- ' ** Module: GAMES.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns TRUE if any non-zero pixels occur in the
- ' same byte of video memory, as saved in the object%()
- ' and backGround%() arrays. The arrays must be the
- ' same size.
- '
- ' EXAMPLE OF USE: test% = Collision%(object%(), backGround%())
- ' PARAMETERS: object%() First array, filled in with the GET
- ' statement
- ' backGround%() Second array, filled in with the GET
- ' statement
- ' VARIABLES: lo% Lower bound of first array
- ' up% Upper bound of first array
- ' lb% Lower bound of second array
- ' ub% Upper bound of second array
- ' i% Index to integers in each array
- ' MODULE LEVEL
- ' DECLARATIONS: CONST FALSE = 0
- ' CONST TRUE = NOT FALSE
- ' DECLARE FUNCTION Collision% (object%(), backGround%())
- '
- FUNCTION Collision% (object%(), backGround%()) STATIC
- lo% = LBOUND(object%)
- uo% = UBOUND(object%)
- lb% = LBOUND(backGround%)
- ub% = UBOUND(backGround%)
- IF lo% <> lb% OR uo% <> ub% THEN
- PRINT "Error: Collision - The object and background"
- PRINT "graphics arrays have different dimensions."
- SYSTEM
- END IF
- FOR i% = lo% + 2 TO uo%
- IF object%(i%) THEN
- IF backGround%(i%) THEN
- Collision% = TRUE
- EXIT FUNCTION
- END IF
- END IF
- NEXT i%
- Collision% = FALSE
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Dice%
-
- Returns a total for all dots that are showing when n% pseudorandom dice
- are thrown.
-
- The QuickBASIC RND function creates the pseudorandom sequence of
- unpredictable numbers to simulate the dice. Unless you want the same
- scores to show up every time a program is run, you should randomize the
- QuickBASIC random number generator by using the RANDOMIZE statement.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Dice% **
- ' ** Type: Function **
- ' ** Module: GAMES.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the total of the dots showing when any
- ' desired number of dice are rolled.
- '
- ' EXAMPLE OF USE: total% = Dice%(n%)
- ' PARAMETERS: n% Number of dice
- ' VARIABLES: toss% Loop index for throwing the n% dice
- ' total% Total of the dots showing
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Dice% (numberOfDice%)
- '
- FUNCTION Dice% (numberOfDice%)
- IF numberOfDice% < 1 THEN
- PRINT "Error: Dice%() - Can't throw fewer than one die"
- SYSTEM
- END IF
- FOR toss% = 1 TO numberOfDice%
- total% = total% + INT(RND * 6) + 1
- NEXT toss%
- Dice% = total%
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
- GAMES
-
-
- Subprogram: FillArray
-
- Fills an integer array with a sequence of numbers defined by the bounds.
- For example, consider these two statements:
-
-
- DIM year%(1900 TO 1999)
- FillArray year%
-
- The array will be filled with year numbers from 1900 through 1999.
-
- As a second example, consider an array dimensioned from 1 through 52.
- After filling this array with the numbers 1 through 52, the array contents
- can be shuffled efficiently with the ShuffleArray subprogram. The result
- is a freshly shuffled deck of 52 cards. Pulling these random "cards"
- sequentially from the array prevents duplication of a card.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FillArray **
- ' ** Type: Subprogram **
- ' ** Module: GAMES.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Initializes an integer array by putting i% into
- ' each i%th element.
- '
- ' EXAMPLE OF USE: FillArray a%()
- ' PARAMETERS: a%() Array to be filled with a sequence of numbe
- ' VARIABLES: i% Looping index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB FillArray (a%())
- '
- SUB FillArray (a%()) STATIC
- FOR i% = LBOUND(a%) TO UBOUND(a%)
- a%(i%) = i%
- NEXT i%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Shuffle$
-
- Shuffles the contents of a string by randomly swapping bytes throughout
- the string.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Shuffle$ **
- ' ** Type: Function **
- ' ** Module: GAMES.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Randomizes the order of the character bytes in a$.
- '
- ' EXAMPLE OF USE: b$ = Shuffle$(a$)
- ' PARAMETERS: a$ String to be shuffled
- ' VARIABLES: x$ Working string space
- ' lenx% Number of bytes in the string
- ' i% Pointer to each byte
- ' j% Pointer to randomly selected byte
- ' t$ Temporary byte-swapping string
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Shuffle$ (a$)
- '
- FUNCTION Shuffle$ (a$) STATIC
- x$ = a$
- lenx% = LEN(x$)
- FOR i% = 1 TO lenx%
- j% = INT(RND * lenx% + 1)
- t$ = MID$(x$, i%, 1)
- MID$(x$, i%, 1) = MID$(x$, j%, 1)
- MID$(x$, j%, 1) = t$
- NEXT i%
- Shuffle$ = x$
- x$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ShuffleArray
-
- Shuffles the contents of an integer array. The array dimensions are
- automatically determined, and each integer entry is swapped with a
- randomly selected second entry.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ShuffleArray **
- ' ** Type: Subprogram **
- ' ** Module: GAMES.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Randomizes the order of the integers in a%()
- ' by swapping contents in a pseudorandom order.
- '
- ' EXAMPLE OF USE: ShuffleArray a%()
- ' PARAMETERS: a%() Array to be shuffled
- ' VARIABLES: lb% Lower bound of the array
- ' ub% Upper bound of the array
- ' range% Number of array entries
- ' i% Looping index
- '
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB ShuffleArray (a%())
- '
- SUB ShuffleArray (a%()) STATIC
- lb% = LBOUND(a%)
- ub% = UBOUND(a%)
- range% = ub% - lb% + 1
- FOR i% = lb% TO ub%
- SWAP a%(i%), a%(INT(RND * range% + lb%))
- NEXT i%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- HEX2BIN
-
- The HEX2BIN program reads in a file containing hexadecimal notation and
- creates a file containing the bytes that are indicated. Characters that
- are not in the set of hexadecimal characters are ignored, and each byte is
- assumed to be indicated by a pair of hexadecimal characters.
-
- This program converts the hexadecimal format files created by the
- BIN2HEX program into the object code files they represent. For example,
- you can create the MOUSE.OBJ file from the MOUSE.HEX file if you don't
- have the Microsoft Macro Assembler. (If you do have the Macro Assembler,
- you should create MOUSE.OBJ directly from the MOUSE.ASM listing.)
-
- The command line for performing this conversion (assuming you've compiled
- HEX2BIN to an executable program to be run from the MS-DOS prompt) is:
-
-
- HEX2BIN MOUSE.HEX MOUSE.OBJ
-
- Refer to the BIN2HEX program for information about creating this and the
- other .HEX files.
-
-
- Program Module: HEX2BIN
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: HEX2BIN **
- ' ** Type: Program **
- ' ** Module: HEX2BIN.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reads in a hexadecimal format file and writes out a binary
- ' file created from the hexadecimal byte numbers.
- '
- ' USAGE: HEX2BIN inFileName.ext outFileName.ext
- ' .MAK FILE: HEX2BIN.BAS
- ' PARSE.BAS
- ' STRINGS.BAS
- ' PARAMETERS: inFileName.ext Name of hexadecimal format file to b
- ' outFileName.ext Name of file to be created
- ' VARIABLES: cmd$ Working copy of the command line
- ' inFile$ Name of input file
- ' outFile$ Name of output file
- ' h$ Pair of hexadecimal characters representing
- ' each byte
- ' i% Index into list of hexadecimal character pa
- ' byte$ Buffer for binary file access
-
- DECLARE SUB ParseWord (a$, sep$, word$)
- DECLARE FUNCTION FilterIn$ (a$, set$)
-
- ' Get the input and output filenames from the command line
- cmd$ = COMMAND$
- ParseWord cmd$, " ,", inFile$
- ParseWord cmd$, " ,", outFile$
-
- ' Verify both filenames were given
- IF outFile$ = "" THEN
- PRINT
- PRINT "Usage: HEX2BIN inFileName.ext outFileName.ext"
- SYSTEM
- END IF
-
- ' Open the input file
- OPEN inFile$ FOR INPUT AS #1
-
- ' Truncate the output file if it already exists
- OPEN outFile$ FOR OUTPUT AS #2
- CLOSE #2
-
- ' Now open it for binary output
- OPEN outFile$ FOR BINARY AS #2 LEN = 1
-
- ' Process each line of the hexadecimal file
- DO
- LINE INPUT #1, h$
- h$ = FilterIn$(UCASE$(h$), "0123456789ABCDEF")
- FOR i% = 1 TO LEN(h$) STEP 2
- byte$ = CHR$(VAL("&H" + MID$(h$, i%, 2)))
- PUT #2, , byte$
- NEXT i%
- LOOP WHILE NOT EOF(1)
-
- ' Clean up and quit
- CLOSE
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- JUSTIFY
-
- The JUSTIFY toolbox contains the subprogram, Justify, which pads a string
- with spaces between words in a pseudorandom manner until the string is a
- desired number of characters. This sounds simple, but the process is
- surprisingly complicated. For example, the inserted spaces must fall
- randomly between words, but it's desirable to keep the density of spaces
- as even as possible. You wouldn't want five spaces between the first two
- words and two spaces between the next two words.
-
- The demo module prints a paragraph justified to three different widths. As
- shown in the demo, the FormatTwo subprogram works hand in hand with the
- Justify subprogram to format a long string into several smaller strings.
- By padding the resulting shorter strings with a fixed number of spaces on
- the left, you're able to format paragraphs of text between arbitrary
- margins. Refer to .MAK FILE in the comment lines of the listing to see the
- other modules you must load for this program to run correctly.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- JUSTIFY.BAS Demo module
- Justify Sub Adjusts strings to specified widths
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: JUSTIFY
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: JUSTIFY **
- ' ** Type: Toolbox **
- ' ** Module: JUSTIFY.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates the Justify subprogram.
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: JUSTIFY.BAS
- ' EDIT.BAS
- ' PARSE.BAS
- ' KEYS.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: a$ String to be justified
- ' col% Number of columns for each example of Justify
- ' x$ Working copy of a$
- ' y$ Working string space
-
- DECLARE SUB Justify (a$, n%)
- DECLARE SUB ParseLine (x$, sep$, a$())
- DECLARE SUB FormatTwo (a$, b$, col%)
-
- CLS
- a$ = ""
- a$ = a$ + "This paragraph is used to demonstrate the Justify "
- a$ = a$ + "subprogram. First, the entire paragraph is "
- a$ = a$ + "placed in a single string variable. This string "
- a$ = a$ + "is then split between words into shorter strings, "
- a$ = a$ + "and these shorter strings are then justified in "
- a$ = a$ + "order to align both the left and right edges of "
- a$ = a$ + "the text."
-
- FOR col% = 50 TO 70 STEP 10
- x$ = a$
- DO
- FormatTwo x$, y$, col%
- IF y$ <> "" THEN
- Justify x$, col%
- END IF
- PRINT x$
- x$ = y$
- LOOP WHILE y$ <> ""
- PRINT
- NEXT col%
-
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Justify
-
- Inserts spaces between words until the given string is the desired length.
- Spaces are not added before the first word or after the last word,
- resulting in a string that is left- and right-justified to the length
- indicated.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Justify **
- ' ** Type: Subprogram **
- ' ** Module: JUSTIFY.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Spaces words with extra spaces until line
- ' is n% characters long.
- '
- ' EXAMPLE OF USE: Justify a$, n%
- ' PARAMETERS: a$ String to be justified
- ' n% Desired string length
- ' VARIABLES: ary$() Array to store individual words from the st
- ' cnt% Count of non-space characters
- ' i% Looping index
- ' j% Count of words
- ' each% Minimum space count to insert between words
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Justify (a$, n%)
- ' DECLARE SUB ParseLine (x$, sep$, a$())
- ' DECLARE SUB FormatTwo (a$, b$, col%)
- '
- SUB Justify (a$, n%) STATIC
-
- ' If string is shorter than n%, don't bother
- IF LEN(a$) < n% THEN
- EXIT SUB
- END IF
-
- ' Array for list of words from original string
- REDIM ary$(1 TO n%)
-
- ' Split line up into individual words
- ParseLine a$, " ", ary$()
-
- ' Count the words and total of non-space characters
- cnt% = 0
- FOR i% = n% TO 1 STEP -1
- cnt% = cnt% + LEN(ary$(i%))
- IF ary$(i%) = "" THEN
- j% = i% - 1
- END IF
- NEXT i%
-
- ' If only one or zero words, there's not much we can do
- IF j% < 2 THEN
- a$ = LEFT$(ary$(1) + SPACE$(n%), n%)
- EXIT SUB
- END IF
-
- ' We want an extra space at the ends of sentences, questions, etc.
- FOR i% = 1 TO j% - 1
- IF INSTR(".!?", RIGHT$(ary$(i%), 1)) THEN
- ary$(i%) = ary$(i%) + " "
- cnt% = cnt% + 1
- END IF
- NEXT i%
-
- ' How many spaces minimum to add to each word?
- each% = (n% - cnt%) \ (j% - 1)
-
- ' Tack on the minimum spaces to each word
- FOR i% = 1 TO j% - 1
- ary$(i%) = ary$(i%) + SPACE$(each%)
- cnt% = cnt% + each%
- NEXT i%
-
- ' Which is quicker, adding remaining spaces, or
- ' adding spaces to all and removing a few of them?
- IF (n% - cnt%) < j% \ 2 THEN
-
- ' We'll add a few spaces at random
- DO UNTIL cnt% = n%
- DO
- i% = INT(RND * (j% - 1) + 2)
- LOOP UNTIL LEFT$(ary$(i%), 1) <> " "
- ary$(i%) = " " + ary$(i%)
- cnt% = cnt% + 1
- LOOP
-
- ELSE
-
- ' We'll add a space to each, and then remove some at random
- FOR i% = 2 TO j%
- ary$(i%) = " " + ary$(i%)
- cnt% = cnt% + 1
- NEXT i%
-
- ' Now we'll take a few away at random
- DO UNTIL cnt% = n%
- DO
- i% = INT(RND * (j% - 1) + 2)
- LOOP UNTIL LEFT$(ary$(i%), 1) = " "
- ary$(i%) = MID$(ary$(i%), 2)
- cnt% = cnt% - 1
- LOOP
-
- END IF
-
- ' Glue it all back together
- a$ = ary$(1)
- FOR i% = 2 TO j%
- a$ = a$ + ary$(i%)
- NEXT i%
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- KEYS
-
- The KEYS toolbox performs two enhanced keyboard input functions. It prints
- the unique integer number returned by the KeyCode% or InKeyCode%
- function for any key pressed. Run the program and press a few keys to see
- the numbers. To try the InKeyCode% function for one second at a time,
- press the Escape key followed immediately by other keys.
-
- The QuickBASIC INKEY$ function returns a string of zero, one, or two
- characters, depending on whether a key was pressed and whether the key has
- an extended key code. The two functions presented here always return a
- unique integer for any key pressed, even if the key normally returns an
- extended key code. For example, pressing the letter "a" returns 97, F1
- returns 15104, Alt-F1 returns 26624, and the Home key returns 18176. Run
- the program to determine other returned values.
-
- The EDIT.BAS module uses these functions and presents a table of CONST
- statements that define several common editing keys. Note that most
- standard alphanumeric keys return the expected ASCII code number.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- KEYS.BAS Demo module
- InKeyCode% Func Returns unique integer for any key pressed
- KeyCode% Func Waits and returns integer value for key
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: KEYS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: KEYS **
- ' ** Type: Toolbox **
- ' ** Module: KEYS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates keyboard access functions.
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: kee% Unique integer returned by KeyCode% and
- ' InKeyCode%
-
-
- DECLARE FUNCTION KeyCode% ()
- DECLARE FUNCTION InKeyCode% ()
-
- CLS
- PRINT "Press any key to see the unique number returned by KeyCode%."
- PRINT "Press Esc to see InKeyCode% results for 1 second."
- PRINT "Press Esc twice in a row to quit."
- PRINT
-
- DO
- kee% = KeyCode%
- PRINT kee%
- IF kee% = 27 THEN
- t0 = TIMER
- DO
- kee% = InKeyCode%
- PRINT kee%;
- IF kee% THEN
- PRINT
- END IF
- IF kee% = 27 THEN
- quitFlag% = -1
- t0 = t0 - 1
- END IF
- LOOP UNTIL TIMER - t0 > 1
- PRINT
- END IF
- LOOP UNTIL quitFlag%
-
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: InKeyCode%
-
- Immediately returns a unique integer for any key pressed or 0 if no key
- was pressed.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: InKeyCode% **
- ' ** Type: Function **
- ' ** Module: KEYS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a unique integer for any key pressed or
- ' a zero if no key was pressed.
- '
- ' EXAMPLE OF USE: k% = InKeyCode%
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION KeyCode% ()
- '
- FUNCTION InKeyCode% STATIC
- InKeyCode% = CVI(INKEY$ + STRING$(2, 0))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: KeyCode%
-
- Waits until a key is pressed, and then returns the unique key-code integer
- for each key on the keyboard.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: KeyCode% **
- ' ** Type: Function **
- ' ** Module: KEYS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a unique integer for any key pressed.
- '
- ' EXAMPLE OF USE: k% = KeyCode%
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION KeyCode% ()
- '
- FUNCTION KeyCode% STATIC
- DO
- k$ = INKEY$
- LOOP UNTIL k$ <> ""
- KeyCode% = CVI(k$ + CHR$(0))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- LOOK
-
- The LOOK program is a utility for viewing text-file contents. The program
- displays ASCII text-file contents and provides limited keyboard control to
- allow scrolling or paging through files.
-
- This program presents the FileRead subprogram for reading ASCII files
- into an array of strings and also demonstrates the VIEW PRINT statement
- for limiting printing and scrolling of text to only those display lines
- desired.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- LOOK.BAS Program module
- FileRead Sub Reads lines of ASCII files into an array
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: LOOK
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: LOOK **
- ' ** Type: Program **
- ' ** Module: LOOK.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: LOOK filename.ext
- ' .MAK FILE: LOOK.BAS
- ' KEYS.BAS
- ' PARAMETERS: filename.ext Name of file to view
- ' VARIABLES: a$() Array of lines from the file
- ' fileName$ Name of file, from the command line
- ' lineCount% Count of lines read from the file
- ' linePtr% First file line currently on the display
- ' i% Loop index for printing 24 lines
- ' quitFlag% Indicates Escape key press
- ' updateFlag% Indicates if update of screen is necessa
-
- ' Constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Key code numbers
- CONST UPARROW = 18432
- CONST DOWNARROW = 20480
- CONST PGUP = 18688
- CONST PGDN = 20736
- CONST HOME = 18176
- CONST ENDKEY = 20224
- CONST ESCAPE = 27
-
- ' Functions
- DECLARE FUNCTION KeyCode% ()
-
- ' Subprograms
- DECLARE SUB FileRead (fileName$, lineCount%, a$())
-
- ' Dimension string array
- ' NOTE:
- ' Must be dimensioned big enough to read in all lines from the file
- DIM a$(1 TO 2000)
-
- ' Get the command line parameters
- fileName$ = COMMAND$
-
- ' Read in the file
- ON ERROR GOTO FileError
- FileRead fileName$, lineCount%, a$()
- ON ERROR GOTO 0
-
- ' Prepare the screen
- SCREEN 0, 0, 0, 0
- CLS
-
- ' Set line pointer
- linePtr% = 1
-
- ' Main loop
- DO
-
- ' Print information bar at top
- VIEW PRINT 1 TO 1
- COLOR 0, 3
- LOCATE 1, 1
- PRINT " Line:"; LEFT$(STR$(linePtr%) + SPACE$(7), 8);
- PRINT "File: "; LEFT$(fileName$ + SPACE$(19), 19);
- PRINT "Quit: ESC"; SPACE$(3);
- PRINT "Move: "; CHR$(24); " "; CHR$(25); " PGUP PGDN HOME END ";
-
- ' Update the 24 lines of text
- VIEW PRINT 2 TO 25
- COLOR 7, 1
- FOR i% = 0 TO 23
- LOCATE i% + 2, 1
- PRINT LEFT$(a$(i% + linePtr%) + SPACE$(80), 80);
- NEXT i%
-
- ' Wait for a meaningful key to be pressed
- SELECT CASE KeyCode%
- CASE UPARROW
- IF linePtr% > 1 THEN
- linePtr% = linePtr% - 1
- END IF
- CASE DOWNARROW
- IF linePtr% < lineCount% THEN
- linePtr% = linePtr% + 1
- END IF
- CASE PGUP
- IF linePtr% > 1 THEN
- linePtr% = linePtr% - 24
- IF linePtr% < 1 THEN
- linePtr% = 1
- END IF
- END IF
- CASE PGDN
- IF linePtr% < lineCount% - 24 THEN
- linePtr% = linePtr% + 24
- IF linePtr% > lineCount% THEN
- linePtr% = lineCount%
- END IF
- END IF
- CASE HOME
- IF linePtr% > 1 THEN
- linePtr% = 1
- END IF
- CASE ENDKEY
- IF linePtr% < lineCount% - 24 THEN
- linePtr% = lineCount% - 24
- END IF
- CASE ESCAPE
- quitFlag% = TRUE
- CASE ELSE
- updateFlag% = FALSE
- END SELECT
-
- LOOP UNTIL quitFlag%
-
- ' Set color back to normal
- COLOR 7, 0
- END
-
- FileError:
- PRINT
- PRINT "Usage: LOOK filename.ext"
- SYSTEM
- RESUME NEXT
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FileRead
-
- Reads all lines of a text (ASCII) file into a string array and returns the
- array of lines from the file and the count of the read lines.
-
- The string array must be large enough to hold all the lines from the file.
- The file to read must be readable using the LINE INPUT statement.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FileRead **
- ' ** Type: Subprogram **
- ' ** Module: LOOK.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reads lines of an ASCII file into a$(). The
- ' lineCount% is set to the number of lines read
- ' in. If a$() wasn't dimensioned large enough,
- ' then lineCount% will be set to -1.
- '
- ' EXAMPLE OF USE: FileRead fileName$, lineCount%, a$()
- ' PARAMETERS: fileName$ Name of file to be read into the array
- ' lineCount% Returned count of lines read from the fi
- ' a$() String array of file contents
- ' VARIABLES: FileNumber% Next available free file number
- ' i% Index for string array
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB FileRead (fileName$, lineCount%, a$())
- '
- SUB FileRead (fileName$, lineCount%, a$()) STATIC
- FileNumber% = FREEFILE
- OPEN fileName$ FOR INPUT AS FileNumber%
- FOR i% = LBOUND(a$) TO UBOUND(a$)
- LINE INPUT #FileNumber%, a$(i%)
- lineCount% = i%
- IF EOF(FileNumber%) THEN
- EXIT FOR
- END IF
- NEXT i%
- IF NOT EOF(FileNumber%) THEN
- lineCount% = -1
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- MONTH
-
- The MONTH program demonstrates how to use the CALENDAR.BAS toolbox to
- perform calendar-related calculations.
-
- When MONTH is run, a display of three one-month calendars is created. The
- current system date determines the second month displayed; the previous
- and next month are also shown.
-
- Included with the display are instructions on how to increment or
- decrement the years or months. Press the lowercase y key to display the
- same three months of the previous year. Press a shifted (uppercase) Y to
- increment the year. In the same way, press M to increment or m to
- decrement the range of months displayed.
-
-
- Program Module: MONTH
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MONTH **
- ' ** Type: Program **
- ' ** Module: MONTH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Creates and displays a three-month calendar.
- ' USAGE: No command line parameters
- ' .MAK FILE: MONTH.BAS
- ' CALENDAR.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: year% Year of concern
- ' month% Month of concern
- ' quitFlag% Indicates that program is to terminate
- ' day% Day near middle of the month
- ' d2$ Date for second calendar month
- ' j2& Julian day number for second calendar month
- ' d1$ Date for first calendar month
- ' j1& Julian day number for first calendar month
- ' d3$ Date for third calendar month
- ' j3& Julian day number for third calendar month
- ' k$ Key press character
-
- ' Constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Functions
- DECLARE FUNCTION Date2Julian& (dat$)
- DECLARE FUNCTION MDY2Date$ (month%, day%, year%)
- DECLARE FUNCTION Date2Year% (dat$)
- DECLARE FUNCTION Date2Month% (dat$)
- DECLARE FUNCTION Julian2Date$ (julian&)
-
- ' Subprograms
- DECLARE SUB OneMonthCalendar (dat$, row%, col%)
-
- ' Get today's month and year
- year% = Date2Year%(DATE$)
- month% = Date2Month%(DATE$)
-
- ' Make calendars until the Esc key is pressed
- DO UNTIL quitFlag%
-
- ' Get Julian day number for about the middle of the month
- day% = 15
- d2$ = MDY2Date$(month%, day%, year%)
- j2& = Date2Julian&(d2$)
-
- ' Get last month's date
- j1& = j2& - 30
- d1$ = Julian2Date$(j1&)
-
- ' Get next month's date
- j3& = j2& + 30
- d3$ = Julian2Date$(j3&)
-
- ' Display the heading
- CLS
- LOCATE 1, 57
- PRINT "THREE-MONTH CALENDAR"
- LOCATE 2, 57
- PRINT "QuickBASIC 4.0"
-
- ' Create the three calendar sheets
- OneMonthCalendar d1$, 1, 1
- OneMonthCalendar d2$, 8, 25
- OneMonthCalendar d3$, 15, 49
-
- ' Display the instructions
- LOCATE 17, 1
- PRINT "Press <Y> to increment the year"
- LOCATE 18, 1
- PRINT "Press <y> to decrement the year"
- LOCATE 19, 1
- PRINT "Press <M> to increment the months"
- LOCATE 20, 1
- PRINT "Press <m> to decrement the months"
- LOCATE 22, 1
- PRINT "Press the Esc key to quit"
-
- ' Wait for a keystroke
- DO
- k$ = INKEY$
- LOOP UNTIL k$ <> ""
-
- ' Check for appropriate keystroke
- SELECT CASE k$
- CASE "y"
- year% = year% - 1
- CASE "Y"
- year% = year% + 1
- CASE "m"
- month% = month% - 3
- CASE "M"
- month% = month% + 3
- CASE CHR$(27)
- quitFlag% = TRUE
- CASE ELSE
- END SELECT
-
- ' Adjust month for proper range
- IF month% < 1 THEN
- month% = month% + 12
- year% = year% - 1
- ELSEIF month% > 12 THEN
- month% = month% - 12
- year% = year% + 1
- END IF
-
- LOOP
-
- ' All done
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- MOUSGCRS
-
- The MOUSGCRS program is a utility for designing graphics-mode mouse
- cursors.
-
- This program lets you create new graphics-mode cursors for programs that
- use the Microsoft Mouse. The program's output is a QuickBASIC subprogram
- file that other programs can load and use. To run MOUSGCRS, your computer
- must have CGA graphics capability and a mouse.
-
- This module can also be used as a toolbox for choosing any of the
- predefined cursors. For an example of a program using this module as a
- toolbox, see the OBJECT.BAS utility program.
-
- The MOUSE.ASM subprogram must be assembled and loaded with the QuickBASIC
- environment for this program to run correctly. See the MOUSE.ASM
- subprogram in Part III of this book for more information on loading this
- routine.
-
- Two masks are displayed while this program is running. The memory-resident
- mouse driver uses the screen mask to define areas of the cursor where the
- background pixels are to be left alone (0s) or blanked out (1s) before the
- cursor mask is displayed. Often, the screen-mask pixels define an area of
- the same shape but slightly larger than the cursor mask, creating an
- outline around the cursor when it's located on a pure white background.
-
- To edit a cursor, click with either the left or right mouse button on any
- of the small squares that make up the two masks. The left button sets
- pixel locations on, and the right button sets them off. To change the hot
- spot to a new location, press both mouse buttons simultaneously.
-
- When you're ready to try out your cursor creation, click on the "Try new
- cursor" box. A solid white area at the right side of the screen lets you
- view your new cursor against a white background.
-
- Click on the "Try standard cursors" box to select one of the predefined
- cursors. Each time you click on this box, the cursor changes to the next
- available predefined cursor type, allowing you to preview them all.
-
- When you click on the "Create cursor subroutine" box, the currently
- defined cursor masks are written to a QuickBASIC subprogram source file
- named GCURSOR.BAS. This file can be loaded by or merged with any program
- in which you want to use the new cursor. To create more than one cursor,
- be sure to rename the GCURSOR.BAS file after creating each cursor
- subprogram.
-
-
- Program Module: MOUSGCRS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MOUSGCRS **
- ' ** Type: Program **
- ' ** Module: MOUSGCRS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Program for the interactive design of graphics-
- ' mode mouse cursor subroutines.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' MIXED.QLB/.LIB
- ' Mouse
- ' .MAK FILE: MOUSGCRS.BAS
- ' BITS.BAS
- ' MOUSSUBS.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: curs$() Array of binary cursor string data
- ' defaultMask$ Pattern mask for the default cursor
- ' xdef% Default hot spot X value
- ' ydef% Default hot spot Y value
- ' mask$ Pattern mask for a cursor
- ' xHot% Hot spot X value
- ' yHot% Hot spot Y value
- ' maskChr% Index into the pattern mask
- ' maskPtr% Index to the background or foreground mas
- ' pattern
- ' y% Cursor bit pointer, vertical
- ' x% Cursor bit pointer, horizontal
- ' xbox% X location on screen for cursor bit box
- ' ybox% Y location on screen for cursor bit box
- ' xh% Screen X location for hot spot
- ' yh% Screen Y location for hot spot
- ' click$ DRAW string for creating the click boxes
- ' quitFlag% Indication that user wants to quit
- ' t$ Copy of TIME$
- ' toggle% Once per second toggle for hot spot visib
- ' pxl% Pixel value at the hot spot
- ' leftButton% Current state of the left mouse button
- ' rightButton% Current state of the right mouse button
- ' resetBox% Indicates cursor is in the "Try standard
- ' cursors" box
- ' tryBox% Indicates cursor is in the "Try new curso
- ' box
- ' subBox% Indicates cursor is in the "Create cursor
- ' subroutine" box
- ' quitBox% Indicates cursor is in the "Quit" box
- ' xold% X location of just-modified pixel box
- ' yold% Y location of just-modified pixel box
- ' ix% X bit pointer for pixel change
- ' iy% Y bit pointer for pixel change
- ' q$ Double-quote character
-
- ' Define constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Subprograms
- DECLARE SUB Cursdflt (mask$, xHot%, yHot%)
- DECLARE SUB Curschek (mask$, xHot%, yHot%)
- DECLARE SUB Curshand (mask$, xHot%, yHot%)
- DECLARE SUB Curshour (mask$, xHot%, yHot%)
- DECLARE SUB Cursjet (mask$, xHot%, yHot%)
- DECLARE SUB Cursleft (mask$, xHot%, yHot%)
- DECLARE SUB Cursplus (mask$, xHot%, yHot%)
- DECLARE SUB Cursup (mask$, xHot%, yHot%)
- DECLARE SUB Cursx (mask$, xHot%, yHot%)
- DECLARE SUB MouseShow ()
- DECLARE SUB MouseNow (lbutton%, rbutton%, xMouse%, yMouse%)
- DECLARE SUB MouseHide ()
- DECLARE SUB MouseMaskTranslate (mask$, xHot%, yHot%, cursor$)
- DECLARE SUB MouseSetGcursor (cursor$)
-
- ' Arrays
- DIM curs$(0 TO 8)
-
- ' Initialization
- SCREEN 2
- CLS
-
- ' Create set of cursors
- Cursdflt defaultMask$, xdef%, ydef%
- MouseMaskTranslate defaultMask$, xdef%, ydef%, curs$(0)
-
- Curschek mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(1)
-
- Curshand mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(2)
-
- Curshour mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(3)
-
- Cursjet mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(4)
-
- Cursleft mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(5)
-
- Cursplus mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(6)
-
- Cursup mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(7)
-
- Cursx mask$, xHot%, yHot%
- MouseMaskTranslate mask$, xHot%, yHot%, curs$(8)
-
- ' Set the default cursor
- MouseSetGcursor curs$(0)
-
- ' Make the default cursor the starting point for editing
- mask$ = defaultMask$
- xHot% = xdef%
- yHot% = ydef%
-
- ' Place titles above pixel boxes
- LOCATE 2, 22, 0
- PRINT "Screen mask";
- LOCATE 2, 50, 0
- PRINT "Cursor mask";
-
- ' Outline the pixel boxes, filling the "ones" using the Mask$
- maskChr% = 0
- FOR maskPtr% = 0 TO 1
- FOR y% = 1 TO 16
- FOR x% = 1 TO 16
- xbox% = x% * 12 + maskPtr% * 222 + 107
- ybox% = y% * 9 + 10
- maskChr% = maskChr% + 1
- LINE (xbox%, ybox%)-(xbox% + 12, ybox% + 9), 1, B
- IF MID$(mask$, maskChr%, 1) = "1" THEN
- LINE (xbox% + 3, ybox% + 2)-(xbox% + 9, ybox% + 7), 1,
- END IF
- IF maskPtr% = 0 THEN
- IF x% = xHot% + 1 AND y% = yHot% + 1 THEN
- xh% = xbox%
- yh% = ybox%
- END IF
- END IF
- NEXT x%
- NEXT y%
- NEXT maskPtr%
-
- ' Instruction text at bottom of display
- LOCATE 23, 1
- PRINT TAB(16); "Left button Right button Both buttons"
- PRINT TAB(16); "to set pixel to clear pixel for hot spot";
-
- ' Print menu items
- LOCATE 3, 2, 0
- PRINT "Try";
- LOCATE 4, 2, 0
- PRINT "standard";
- LOCATE 5, 2, 0
- PRINT "cursors";
- LOCATE 9, 2, 0
- PRINT "Try new";
- LOCATE 10, 2, 0
- PRINT "cursor";
- LOCATE 14, 2, 0
- PRINT "Create"
- LOCATE 15, 2, 0
- PRINT "cursor";
- LOCATE 16, 2, 0
- PRINT "subroutine";
- LOCATE 16, 74, 0
- PRINT "Quit";
-
- ' Make click box draw string
- click$ = "R20D10L20U10BF5BR1F3E6"
-
- ' Draw the click boxes
- DRAW "BM20,45" + click$
- DRAW "BM20,85" + click$
- DRAW "BM20,132" + click$
- DRAW "BM592,132" + click$
-
- ' Make a white cursor testing area
- LOCATE 5, 71
- PRINT "Cursor";
- LOCATE 6, 71
- PRINT "viewing";
- LOCATE 7, 71
- PRINT "area";
- LINE (560, 60)-(610, 100), 1, BF
-
- ' Turn on the mouse
- MouseShow
-
- ' Main processing loop control
- DO
- GOSUB MainLoop
- LOOP UNTIL quitFlag%
-
- ' Exit the loop and end program because Quitflag% has been set
- CLS
- SYSTEM
-
-
- ' Main processing loop
- MainLoop:
-
- ' Toggle the hot spot once per second
- IF t$ <> TIME$ THEN
- t$ = TIME$
- IF toggle% = 1 THEN
- toggle% = 0
- ELSE
- toggle% = 1
- END IF
- pxl% = POINT(xh% + 3, yh% + 2) XOR toggle%
- LINE (xh% + 5, yh% + 3)-(xh% + 7, yh% + 6), pxl%, BF
- pxl% = POINT(xh% + 3 + 222, yh% + 2) XOR toggle%
- LINE (xh% + 5 + 222, yh% + 3)-(xh% + 7 + 222, yh% + 6), pxl%, BF
- END IF
-
- ' What is the mouse location and button state right now?
- MouseNow leftButton%, rightButton%, x%, y%
-
- ' Are both buttons being pressed right now?
- IF leftButton% AND rightButton% THEN
- GOSUB WhichBox
- IF xbox% THEN
- GOSUB SetHotSpot
- END IF
- END IF
-
- ' Are we traversing the "Try standard cursors" click box?
- IF x% > 20 AND x% < 40 AND y% > 45 AND y% < 55 THEN
- IF resetBox% = 0 THEN
- MouseHide
- resetBox% = 1
- LINE (17, 43)-(43, 57), 1, B
- MouseShow
- END IF
- ELSE
- IF resetBox% = 1 THEN
- MouseHide
- resetBox% = 0
- LINE (17, 43)-(43, 57), 0, B
- MouseShow
- END IF
- END IF
-
- ' Are we traversing the "Try new cursor" click box?
- IF x% > 20 AND x% < 40 AND y% > 85 AND y% < 95 THEN
- IF tryBox% = 0 THEN
- MouseHide
- tryBox% = 1
- LINE (17, 83)-(43, 97), 1, B
- MouseShow
- END IF
- ELSE
- IF tryBox% = 1 THEN
- MouseHide
- tryBox% = 0
- LINE (17, 83)-(43, 97), 0, B
- MouseShow
- END IF
- END IF
-
- ' Are we traversing the "Create cursor subroutine" click box?
- IF x% > 20 AND x% < 40 AND y% > 132 AND y% < 142 THEN
- IF subBox% = 0 THEN
- MouseHide
- subBox% = 1
- LINE (17, 130)-(43, 144), 1, B
- MouseShow
- END IF
- ELSE
- IF subBox% = 1 THEN
- MouseHide
- subBox% = 0
- LINE (17, 130)-(43, 144), 0, B
- MouseShow
- END IF
- END IF
-
- ' Are we traversing the "Quit" click box?
- IF x% > 592 AND x% < 612 AND y% > 132 AND y% < 142 THEN
- IF quitBox% = 0 THEN
- MouseHide
- quitBox% = 1
- LINE (589, 130)-(615, 144), 1, B
- MouseShow
- END IF
- ELSE
- IF quitBox% = 1 THEN
- MouseHide
- quitBox% = 0
- LINE (589, 130)-(615, 144), 0, B
- MouseShow
- END IF
- END IF
-
- ' If just one button or the other is pressed, then check further
- IF leftButton% XOR rightButton% THEN
- GOSUB ButtonWasPressed
- ELSE
- xold% = 0
- yold% = 0
- END IF
-
- ' End of main loop
- RETURN
-
- ' Is the mouse currently pointing at a pixel box?
- WhichBox:
- IF x% > 320 THEN
- maskPtr% = 1
- x% = x% - 222
- ELSE
- maskPtr% = 0
- END IF
- ix% = (x% - 107) \ 12
- iy% = (y% - 10) \ 9
- xbox% = 0
- ybox% = 0
- IF ix% >= 1 AND ix% <= 16 THEN
- IF iy% >= 1 AND iy% <= 16 THEN
- xbox% = ix% * 12 + maskPtr% * 222 + 107
- ybox% = iy% * 9 + 10
- END IF
- END IF
- RETURN
-
- ' Move the hot spot to the current pixel box
- SetHotSpot:
- IF (xbox% <> xh% AND xbox% - 222 <> xh%) OR ybox% <> yh% THEN
- MouseHide
- pxl% = POINT(xh% + 3, yh% + 2)
- LINE (xh% + 5, yh% + 3)-(xh% + 7, yh% + 6), pxl%, BF
- pxl% = POINT(xh% + 3 + 222, yh% + 2)
- LINE (xh% + 5 + 222, yh% + 3)-(xh% + 7 + 222, yh% + 6), pxl%, BF
- MouseShow
- IF xbox% > 320 THEN
- xh% = xbox% - 222
- ELSE
- xh% = xbox%
- END IF
- yh% = ybox%
- END IF
- RETURN
-
- ' Process the button press depending on mouse location
- ButtonWasPressed:
- IF quitBox% THEN
- GOSUB DoQuitBox
- ELSEIF resetBox% THEN
- GOSUB DoResetCursor
- ELSEIF tryBox% THEN
- GOSUB DoSetNewCursor
- ELSEIF subBox% THEN
- GOSUB DoSetNewCursor
- GOSUB DoCreateSub
- ELSE
- GOSUB DoPixelControl
- END IF
- RETURN
-
- ' Button was pressed while mouse was in the "Quit" box
- DoQuitBox:
- MouseHide
- quitFlag% = TRUE
- RETURN
-
- ' Button was pressed while mouse was in the "Try new cursor" box
- DoSetNewCursor:
- MouseHide
- maskChr% = 0
- FOR maskPtr% = 0 TO 1
- FOR y% = 1 TO 16
- FOR x% = 1 TO 16
- xbox% = x% * 12 + maskPtr% * 222 + 107
- ybox% = y% * 9 + 10
- maskChr% = maskChr% + 1
- IF POINT(xbox% + 3, ybox% + 2) THEN
- MID$(mask$, maskChr%, 1) = "1"
- ELSE
- MID$(mask$, maskChr%, 1) = "0"
- END IF
- IF xbox% = xh% AND ybox% = yh% THEN
- xHot% = x% - 1
- yHot% = y% - 1
- END IF
- NEXT x%
- NEXT y%
- NEXT maskPtr%
- MouseMaskTranslate mask$, xHot%, yHot%, cursor$
- MouseSetGcursor cursor$
- MouseShow
- RETURN
-
- ' Button was pressed while mouse was in the "Try standard cursors" box
- DoResetCursor:
- MouseHide
- cursorIndex% = (cursorIndex% + 1) MOD 9
- MouseSetGcursor curs$(cursorIndex%)
- MouseShow
- DO
- MouseNow leftButton%, rightButton%, xMouse%, yMouse%
- LOOP UNTIL leftButton% = 0 AND rightButton% = 0
- RETURN
-
- ' Button was pressed while mouse was in the "Create cursor subroutine" bo
- DoCreateSub:
- q$ = CHR$(34)
- OPEN "GCURSOR.BAS" FOR OUTPUT AS #1
- PRINT #1, " ' ************************************************"
- PRINT #1, " ' ** Name: Gcursor **"
- PRINT #1, " ' ** Type: Subprogram **"
- PRINT #1, " ' ** Module: GCURSOR.BAS **"
- PRINT #1, " ' ** Language: Microsoft QuickBASIC 4.00 **"
- PRINT #1, " ' ************************************************"
- PRINT #1, " '"
- PRINT #1, " SUB Gcursor (mask$, xHot%, yHot%) STATIC"
- PRINT #1, ""
- PRINT #1, " mask$ = "; q$; q$
- FOR i% = 0 TO 31
- PRINT #1, " mask$ = mask$ + ";
- PRINT #1, q$; MID$(mask$, 16 * i% + 1, 16); q$
- IF i% = 15 THEN
- PRINT #1, ""
- END IF
- NEXT i%
- PRINT #1, ""
- PRINT #1, " xHot% ="; STR$(xHot%)
- PRINT #1, " yHot% ="; STR$(yHot%)
- PRINT #1, ""
- PRINT #1, " END SUB"
- RETURN
-
- ' Set or clear pixel box if mouse is on one
- DoPixelControl:
- GOSUB WhichBox
- IF xbox% THEN
- IF xold% <> xbox% OR yold% <> ybox% THEN
- xold% = xbox%
- yold% = ybox%
- MouseHide
- IF leftButton% THEN
- LINE (xbox% + 3, ybox% + 2)-(xbox% + 9, ybox% + 7), 1, BF
- ELSE
- LINE (xbox% + 3, ybox% + 2)-(xbox% + 9, ybox% + 7), 0, BF
- END IF
- MouseShow
- END IF
- END IF
- RETURN
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- MOUSSUBS
-
- The MOUSSUBS toolbox presents a collection of subprograms for accessing
- and using your mouse. Your computer must have CGA graphics capability and
- a mouse for this program to be useful. If you have a mouse but are limited
- to monochrome text modes, see the MOUSTCRS.BAS module.
-
- The assembly-language subroutine named MOUSE.ASM must be assembled and
- linked with these routines or included in the user library loaded with
- QuickBASIC. See the MOUSE.ASM subprogram description in Part III of this
- book for more information on doing this.
-
- To use these subprograms in your own programs, load this module (along
- with the MOUSE.ASM routine), and be sure to declare the subprograms used
- by your main program module. For examples of programs that use this module
- as a toolbox, see the OBJECT.BAS, MOUSGCRS.BAS, MOUSTCRS.BAS, and
- WINDOWS.BAS program modules.
-
- Each subprogram that creates cursors defines a graphics-mode mouse cursor
- by filling in the pattern mask string and hot spot location variables.
- After this subprogram is called, call MouseMaskTranslate to translate the
- variables to a binary format string, which should then be passed to the
- MouseSetGcursor subprogram to quickly set the indicated cursor.
-
- You might find it helpful to follow the program listing as the interactive
- demonstration progresses.
-
- ╓┌─┌─────────────────────────────┌──────┌────────────────────────────────────╖
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- MOUSSUBS.BAS Demo module
- Curschek Sub Check mark mouse cursor
- Cursdflt Sub Arrow mouse cursor pointing up and
- left
- Curshand Sub Pointing hand mouse cursor
- Curshour Sub Hourglass mouse cursor
- Cursjet Sub Jet-shaped mouse cursor
- Cursleft Sub Left arrow mouse cursor
- Cursplus Sub Plus sign mouse cursor
- Cursup Sub Up arrow mouse cursor
- Cursx Sub X-mark mouse cursor
- MouseHide Sub Turns off mouse visibility
- MouseInches Sub Sets mouse-to-cursor motion ratio
- MouseInstall Sub Checks mouse availability; resets
- mouse parameters
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- mouse parameters
- MouseLightPen Sub Mouse emulation of a lightpen
- MouseMaskTranslate Sub Translates pattern/hot spot to binary
- MouseMickey Sub Returns motion increments since last
- call
- MouseNow Sub Current state/location of the mouse
- MousePressLeft Sub Location of mouse──left button press
- MousePressRight Sub Location of mouse──right button press
- MousePut Sub Moves cursor to the given position
- MouseRange Sub Limits mouse cursor motion to
- rectangle
- MouseReleaseLeft Sub Location of mouse──left button
- release
- MouseReleaseRight Sub Location of mouse──right button
- release
- MouseSetGcursor Sub Sets graphics-mode mouse cursor
- MouseShow Sub Activates and displays mouse cursor
- MouseSoftCursor Sub Sets text-mode attributes (mouse
- cursor)
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- cursor)
- MouseWarp Sub Sets mouse double-speed threshold
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- Demo Module: MOUSSUBS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MOUSSUBS **
- ' ** Type: Toolbox **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Collection of subprograms for using the Microsoft Mouse.
- '
- ' Note: The assembly-language subroutine named MOUSE.ASM
- ' must be assembled and linked with these routines
- ' or included in the user library loaded with
- ' QuickBASIC.
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' MIXED.QLB/.LIB
- ' Mouse
- ' .MAK FILE: MOUSSUBS.BAS
- ' BITS.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: i% Looping index
- ' mask$ Pattern mask for each graphics mouse cursor
- ' xHot% X hot spot location
- ' yHot% Y hot spot location
- ' curs$ Binary bit pattern for defining mouse cursor
- ' j% Test for left mouse button press and release
- ' leftButton% State of left mouse button
- ' rightButton% State of right mouse button
- ' xMouse% X location of mouse
- ' yMouse% Y location of mouse
- ' mflag% Indicates mouse is available
- ' horizontal% Horizontal mouse mickies
- ' vertical% Vertical mouse mickies
- ' xpLeft% X location of last left button press
- ' ypLeft% Y location of last left button press
- ' xrLeft% X location of last left button release
- ' yrLeft% Y location of last left button release
- ' xpRight% X location of last right button press
- ' ypRight% Y location of last right button press
- ' xrRight% X location of last right button release
- ' yrRight% Y location of last right button release
- ' t0 Timer value
- '
- ' Functions
- DECLARE FUNCTION BinStr2Bin% (b$)
-
- ' Subprograms
- DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- DECLARE SUB MouseRange (x1%, y1%, x2%, y2%)
- DECLARE SUB MousePut (xMouse%, yMouse%)
- DECLARE SUB MouseHide ()
- DECLARE SUB MouseInches (horizontal%, vertical%)
- DECLARE SUB MouseInstall (mflag%)
- DECLARE SUB MouseMickey (horizontal%, vertical%)
- DECLARE SUB MousePressLeft (leftCount%, xMouse%, yMouse%)
- DECLARE SUB MousePressRight (rightCount%, xMouse%, yMouse%)
- DECLARE SUB MouseReleaseLeft (leftCount%, xMouse%, yMouse%)
- DECLARE SUB MouseReleaseRight (rightCount%, xMouse%, yMouse%)
- DECLARE SUB MouseWarp (threshold%)
- DECLARE SUB Cursdflt (mask$, xHot%, yHot%)
- DECLARE SUB Curschek (mask$, xHot%, yHot%)
- DECLARE SUB Curshand (mask$, xHot%, yHot%)
- DECLARE SUB Curshour (mask$, xHot%, yHot%)
- DECLARE SUB Cursjet (mask$, xHot%, yHot%)
- DECLARE SUB Cursleft (mask$, xHot%, yHot%)
- DECLARE SUB Cursplus (mask$, xHot%, yHot%)
- DECLARE SUB Cursup (mask$, xHot%, yHot%)
- DECLARE SUB Cursx (mask$, xHot%, yHot%)
- DECLARE SUB MouseMaskTranslate (mask$, xHot%, yHot%, cursor$)
- DECLARE SUB MouseNow (leftButton%, rightButton%, xMouse%, yMouse%)
- DECLARE SUB MouseSetGcursor (cursor$)
- DECLARE SUB MouseShow ()
-
- ' Check for mouse
- SCREEN 2
- CLS
- MouseInstall mflag%
- PRINT "MouseInstall ... "; mflag%
-
- ' Demonstrate the available graphics-mode cursors
- PRINT
- PRINT "Click left mouse button to see the graphics-mode cursors..."
- MouseShow
-
- FOR i% = 1 TO 9
- SELECT CASE i%
- CASE 1
- Curschek mask$, xHot%, yHot%
- CASE 2
- Curshand mask$, xHot%, yHot%
- CASE 3
- Curshour mask$, xHot%, yHot%
- CASE 4
- Cursjet mask$, xHot%, yHot%
- CASE 5
- Cursleft mask$, xHot%, yHot%
- CASE 6
- Cursplus mask$, xHot%, yHot%
- CASE 7
- Cursup mask$, xHot%, yHot%
- CASE 8
- Cursx mask$, xHot%, yHot%
- CASE ELSE
- Cursdflt mask$, xHot%, yHot%
- END SELECT
- MouseMaskTranslate mask$, xHot%, yHot%, curs$
- FOR j% = -1 TO 0
- DO
- MouseNow leftButton%, rightButton%, xMouse%, yMouse%
- LOOP UNTIL leftButton% = j%
- NEXT j%
- MouseSetGcursor curs$
- NEXT i%
-
- ' Mouse hide and show
- PRINT "MouseHide ... (Press any key to continue)"
- MouseHide
- DO
- LOOP UNTIL INKEY$ <> ""
- PRINT "MouseShow ... (Press any key to continue)"
- MouseShow
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' Mouse inches per screen
- MouseHide
- PRINT
- PRINT "Setting MouseWarp to 9999 to prevent doubling of speed."
- MouseWarp 9999
- PRINT
- PRINT "Setting MouseInches to 8 by 11. (8 inches of mouse motion"
- PRINT "across desk to move across screen, and 11 inches vertical"
- PRINT "mouse motion from top to bottom of screen) ..."
- PRINT
- PRINT "Press any key to continue"
- MouseInches 8, 11
- MouseShow
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' Resetting the mouse
- MouseHide
- PRINT
- PRINT "Resetting the mouse"
- MouseInstall mflag%
-
- ' Show realtime mouse data
- CLS
- PRINT "Instantaneous mouse information (Press any key to continue)"
- MouseShow
- DO
- MouseMickey horizontal%, vertical%
- MouseNow leftButton%, rightButton%, xMouse%, yMouse%
- MousePressLeft leftCount%, xpLeft%, ypLeft%
- MouseReleaseLeft leftCount%, xrLeft%, yrLeft%
- MousePressRight rightCount%, xpRight%, ypRight%
- MouseReleaseRight rightCount%, xrRight%, yrRight%
- LOCATE 3, 1
- PRINT "Mickies ";
- PRINT USING "#######, #######"; horizontal%, vertical%
- PRINT "Position ";
- PRINT USING "#######, #######"; xMouse%, yMouse%
- PRINT
- PRINT "Buttons ";
- PRINT USING "#######, #######"; leftButton%, rightButton%
- PRINT
- PRINT "Left Press ";
- PRINT USING "#######, #######"; xpLeft%, ypLeft%
- PRINT "Left Release ";
- PRINT USING "#######, #######"; xrLeft%, yrLeft%
- PRINT
- PRINT "Right Press ";
- PRINT USING "#######, #######"; xpRight%, ypRight%
- PRINT "Right Release ";
- PRINT USING "#######, #######"; xrRight%, yrRight%
- LOOP UNTIL INKEY$ <> ""
-
- ' Mouse placement
- CLS
- MouseHide
- PRINT "MousePut..."
- MouseShow
- FOR i% = 1 TO 20
- xMouse% = RND * 639
- yMouse% = RND * 199
- MousePut xMouse%, yMouse%
- t0 = TIMER
- DO
- LOOP UNTIL TIMER - t0 > .2
- NEXT i%
-
- ' Range limiting
- CLS
- MouseHide
- PRINT "Range limited to a rectangular area ..."
- PRINT "Press any key to continue"
- MouseShow
- MouseRange 200, 50, 400, 100
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' All done
- SCREEN 0
- CLS
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Curschek
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining a check mark cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Curschek **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (check mark).
- '
- ' EXAMPLE OF USE: Curschek mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Curschek (mask$, xHot%, yHot%)
- '
- SUB Curschek (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "1111111111110000"
- mask$ = mask$ + "1111111111100000"
- mask$ = mask$ + "1111111111000000"
- mask$ = mask$ + "1111111110000001"
- mask$ = mask$ + "1111111100000011"
- mask$ = mask$ + "0000011000000111"
- mask$ = mask$ + "0000000000001111"
- mask$ = mask$ + "0000000000011111"
- mask$ = mask$ + "1100000000111111"
- mask$ = mask$ + "1111000001111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000110"
- mask$ = mask$ + "0000000000001100"
- mask$ = mask$ + "0000000000011000"
- mask$ = mask$ + "0000000000110000"
- mask$ = mask$ + "0000000001100000"
- mask$ = mask$ + "0111000011000000"
- mask$ = mask$ + "0001110110000000"
- mask$ = mask$ + "0000011100000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
-
- xHot% = 6
- yHot% = 7
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Cursdflt
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining the default cursor (an arrow pointing up and left).
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Cursdflt **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a default graphics-mode mouse cursor (arrow pointing up and lef
- '
- ' EXAMPLE OF USE: Cursdflt mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATION: DECLARE SUB Cursdflt (mask$, xHot%, yHot%)
- '
- SUB Cursdflt (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1001111111111111"
- mask$ = mask$ + "1000111111111111"
- mask$ = mask$ + "1000011111111111"
- mask$ = mask$ + "1000001111111111"
- mask$ = mask$ + "1000000111111111"
- mask$ = mask$ + "1000000011111111"
- mask$ = mask$ + "1000000001111111"
- mask$ = mask$ + "1000000000111111"
- mask$ = mask$ + "1000000000011111"
- mask$ = mask$ + "1000000000001111"
- mask$ = mask$ + "1000000000000111"
- mask$ = mask$ + "1000100001111111"
- mask$ = mask$ + "1001100001111111"
- mask$ = mask$ + "1111110000111111"
- mask$ = mask$ + "1111110000111111"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0010000000000000"
- mask$ = mask$ + "0011000000000000"
- mask$ = mask$ + "0011100000000000"
- mask$ = mask$ + "0011110000000000"
- mask$ = mask$ + "0011111000000000"
- mask$ = mask$ + "0011111100000000"
- mask$ = mask$ + "0011111110000000"
- mask$ = mask$ + "0011111111000000"
- mask$ = mask$ + "0011111111100000"
- mask$ = mask$ + "0011111000000000"
- mask$ = mask$ + "0010001100000000"
- ──────────────────────────────────────────────────────────────────────────
-
- mask$ = mask$ + "0000001100000000"
-
- mask$ = mask$ + "0000000110000000"
-
- mask$ = mask$ + "0000000110000000"
-
-
-
- xHot% = 1
-
- yHot% = 1
-
-
-
- END SUB
-
-
- Subprogram: Curshand
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining a pointing hand cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Curshand **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (pointing hand).
- '
- ' EXAMPLE OF USE: Curshand mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Curshand (mask$, xHot%, yHot%)
- '
- SUB Curshand (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "1110000111111111"
- mask$ = mask$ + "1110000111111111"
- mask$ = mask$ + "1110000111111111"
- mask$ = mask$ + "1110000111111111"
- mask$ = mask$ + "1110000111111111"
- mask$ = mask$ + "1110000000000000"
- mask$ = mask$ + "1110000000000000"
- mask$ = mask$ + "1110000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
-
- mask$ = mask$ + "0001111000000000"
- mask$ = mask$ + "0001001000000000"
- mask$ = mask$ + "0001001000000000"
- mask$ = mask$ + "0001001000000000"
- mask$ = mask$ + "0001001000000000"
- mask$ = mask$ + "0001001111111111"
- mask$ = mask$ + "0001001001001001"
- mask$ = mask$ + "0001001001001001"
- mask$ = mask$ + "1111001001001001"
- mask$ = mask$ + "1001000000000001"
- mask$ = mask$ + "1001000000000001"
- mask$ = mask$ + "1001000000000001"
- mask$ = mask$ + "1000000000000001"
- mask$ = mask$ + "1000000000000001"
- mask$ = mask$ + "1000000000000001"
- mask$ = mask$ + "1111111111111111"
-
- xHot% = 5
- yHot% = 0
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Curshour
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining an hourglass cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Curshour **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (hourglass).
- '
- ' EXAMPLE OF USE: Curshour mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Curshour (mask$, xHot%, yHot%)
- '
- SUB Curshour (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "1000000000000001"
- mask$ = mask$ + "1100000000000011"
- mask$ = mask$ + "1110000000000111"
- mask$ = mask$ + "1111000000001111"
- mask$ = mask$ + "1110000000000111"
- mask$ = mask$ + "1100000000000011"
- mask$ = mask$ + "1000000000000001"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0111111111111110"
- mask$ = mask$ + "0110000000000110"
- mask$ = mask$ + "0011000000001100"
- mask$ = mask$ + "0001100000011000"
- mask$ = mask$ + "0000110000110000"
- mask$ = mask$ + "0000011001100000"
- mask$ = mask$ + "0000001111000000"
- mask$ = mask$ + "0000011001100000"
- mask$ = mask$ + "0000110000110000"
- mask$ = mask$ + "0001100110011000"
- mask$ = mask$ + "0011001111001100"
- mask$ = mask$ + "0110011111100110"
- mask$ = mask$ + "0111111111111110"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
-
- xHot% = 7
- yHot% = 7
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Cursjet
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining a jet aircraft cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Cursjet **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (jet aircraft).
- '
- ' EXAMPLE OF USE: Cursjet mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Cursjet (mask$, xHot%, yHot%)
- '
- SUB Cursjet (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111011111111"
- mask$ = mask$ + "1111110001111111"
- mask$ = mask$ + "1111100000111111"
- mask$ = mask$ + "1111100000111111"
- mask$ = mask$ + "1111100000111111"
- mask$ = mask$ + "1111000000011111"
- mask$ = mask$ + "1110000000001111"
- mask$ = mask$ + "1100000000000111"
- mask$ = mask$ + "1000000000000011"
- mask$ = mask$ + "1000000000000011"
- mask$ = mask$ + "1111100000111111"
- mask$ = mask$ + "1111100000111111"
- mask$ = mask$ + "1111000000011111"
- mask$ = mask$ + "1110000000001111"
- mask$ = mask$ + "1111111111111111"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000100000000"
- mask$ = mask$ + "0000001110000000"
- mask$ = mask$ + "0000001110000000"
- mask$ = mask$ + "0000001110000000"
- mask$ = mask$ + "0000011111000000"
- mask$ = mask$ + "0000111111100000"
- mask$ = mask$ + "0001111111110000"
- mask$ = mask$ + "0011111111111000"
- mask$ = mask$ + "0110001110001100"
- mask$ = mask$ + "0000001110000000"
- mask$ = mask$ + "0000001110000000"
- mask$ = mask$ + "0000011111000000"
- mask$ = mask$ + "0000110001100000"
- mask$ = mask$ + "0000000000000000"
-
- xHot% = 7
- yHot% = 1
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Cursleft
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining a left arrow cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Cursleft **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (left arrow).
- '
- ' EXAMPLE OF USE: Cursleft mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Cursleft (mask$, xHot%, yHot%)
- '
- SUB Cursleft (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "1111111000011111"
- mask$ = mask$ + "1111000000011111"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "1111000000011111"
- mask$ = mask$ + "1111111000011111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000011000000"
- mask$ = mask$ + "0000011111000000"
- mask$ = mask$ + "0111111111111110"
- mask$ = mask$ + "0000011111000000"
- mask$ = mask$ + "0000000011000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
-
- xHot% = 0
- yHot% = 3
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Cursplus
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining a plus sign cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Cursplus **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (plus sign).
- '
- ' EXAMPLE OF USE: Cursplus mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Cursplus (mask$, xHot%, yHot%)
- '
- SUB Cursplus (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "1111110000111111"
- mask$ = mask$ + "1111110000111111"
- mask$ = mask$ + "1111110000111111"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "1111110000111111"
- mask$ = mask$ + "1111110000111111"
- mask$ = mask$ + "1111110000111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0111111111111110"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
-
- xHot% = 7
- yHot% = 4
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Cursup
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining an up arrow cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Cursup **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (up arrow).
- '
- ' EXAMPLE OF USE: Cursup mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Cursup (mask$, xHot%, yHot%)
- '
- SUB Cursup (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "1111100111111111"
- mask$ = mask$ + "1111000011111111"
- mask$ = mask$ + "1110000001111111"
- mask$ = mask$ + "1110000001111111"
- mask$ = mask$ + "1100000000111111"
- mask$ = mask$ + "1100000000111111"
- mask$ = mask$ + "1000000000011111"
- mask$ = mask$ + "1000000000011111"
- mask$ = mask$ + "0000000000001111"
- mask$ = mask$ + "0000000000001111"
- mask$ = mask$ + "1111000011111111"
- mask$ = mask$ + "1111000011111111"
- mask$ = mask$ + "1111000011111111"
- mask$ = mask$ + "1111000011111111"
- mask$ = mask$ + "1111000011111111"
- mask$ = mask$ + "1111000011111111"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000011000000000"
- mask$ = mask$ + "0000111100000000"
- mask$ = mask$ + "0000111100000000"
- mask$ = mask$ + "0001111110000000"
- mask$ = mask$ + "0001111110000000"
- mask$ = mask$ + "0011111111000000"
- mask$ = mask$ + "0011111111000000"
- mask$ = mask$ + "0111111111100000"
- mask$ = mask$ + "0000011000000000"
- mask$ = mask$ + "0000011000000000"
- mask$ = mask$ + "0000011000000000"
- mask$ = mask$ + "0000011000000000"
- mask$ = mask$ + "0000011000000000"
- mask$ = mask$ + "0000011000000000"
- mask$ = mask$ + "0000000000000000"
-
- xHot% = 5
- yHot% = 0
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Cursx
-
- Creates a graphics mouse cursor; fills in the pattern mask and hot spot
- values for defining an X-mark cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Cursx **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Defines a graphics-mode mouse cursor (X mark).
- '
- ' EXAMPLE OF USE: Cursx mask$, xHot%, yHot%
- ' PARAMETERS: mask$ Pattern mask for creating cursor
- ' xHot% X location for cursor hot spot
- ' yHot% Y location for cursor hot spot
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Cursx (mask$, xHot%, yHot%)
- '
- SUB Cursx (mask$, xHot%, yHot%) STATIC
-
- mask$ = ""
- mask$ = mask$ + "0000011111100000"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "1100000000000011"
- mask$ = mask$ + "1111000000001111"
- mask$ = mask$ + "1100000000000011"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000110000000"
- mask$ = mask$ + "0000001111000000"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
- mask$ = mask$ + "1111111111111111"
-
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0111000000001110"
- mask$ = mask$ + "0001110000111000"
- mask$ = mask$ + "0000011001100000"
- mask$ = mask$ + "0000001111000000"
- mask$ = mask$ + "0000011001100000"
- mask$ = mask$ + "0001110000111000"
- mask$ = mask$ + "0111000000001110"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
- mask$ = mask$ + "0000000000000000"
-
- xHot% = 7
- yHot% = 4
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseHide
-
- Deactivates the mouse cursor, making it invisible and inaccessible. Use
- the MouseShow subprogram to reactivate the cursor.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseHide **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Hides the mouse cursor.
- '
- ' EXAMPLE OF USE: MouseHide
- '
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseHide ()
- '
- SUB MouseHide STATIC
- Mouse 2, 0, 0, 0
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseInches
-
- Sets the ratio of mouse motion to cursor motion. The horizontal% and
- vertical% parameters indicate the number of inches of desktop motion that
- your mouse must move to move the mouse cursor from one edge of the screen
- to the other. Note that the vertical and horizontal values are independent
- of each other.
-
- Before calling this subprogram, set the double-speed threshold to a large
- value by calling the MouseWarp subprogram. This prevents fast mouse
- motion from doubling the cursor velocity, keeping the motion ratios
- constant.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseInches **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets mouse motion ratio in inches per screen.
- '
- ' EXAMPLE OF USE: MouseInches horizontal%, vertical%
- ' PARAMETERS: horizontal% Inches of horizontal mouse motion per
- ' screen width
- ' vertical% Inches of vertical% mouse motion per
- ' screen height
- ' VARIABLES: h% Calculated value to pass to mouse driver
- ' v% Calculated value to pass to mouse driver
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseInches (horizontal%, vertical%)
- '
- SUB MouseInches (horizontal%, vertical%) STATIC
- IF horizontal% > 100 THEN
- horizontal% = 100
- END IF
- IF vertical% > 100 THEN
- vertical% = 100
- END IF
- h% = horizontal% * 5 \ 2
- v% = vertical% * 8
- Mouse 15, 0, h%, v%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseInstall
-
- Checks the memory-resident mouse driver to determine whether a mouse is
- available. The value of mflag% is returned as 0 if no mouse is available
- and as -1 if one is.
-
- This subprogram also initializes the mouse driver to the default state.
- The original cursor is set, and the mouse velocity, threshold, and other
- parameters are all set to their original states.
-
- Normally, this subprogram is called immediately when a program is run.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseInstall **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Determines whether mouse is available and resets all mouse parameters.
- '
- ' EXAMPLE OF USE: MouseInstall mflag%
- ' PARAMETERS: mflag% Returned indication of mouse availability
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseInstall (mflag%)
- '
- SUB MouseInstall (mflag%) STATIC
- mflag% = 0
- Mouse mflag%, 0, 0, 0
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseLightPen
-
- Activates or deactivates lightpen emulation by the mouse.
-
- The QuickBASIC PEN function provides ten unique functions for accessing
- information on the lightpen, depending on the parameter you pass to it.
- This complete set of lightpen functions can be emulated using the mouse
- rather than the lightpen. To activate lightpen emulation, call
- MouseLightPen with a non-zero parameter. To deactivate lightpen emulation,
- use a zero parameter.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseLightPen **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
-
- ' Activates and deactivates lightpen emulation mode.
- '
- ' EXAMPLE OF USE: MouseLightPen switch%
- ' PARAMETERS: switch% non-zero to activate lightpen emulation,
- ' zero to deactivate
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseLightPen (switch%)
- '
- SUB MouseLightPen (switch%) STATIC
- IF switch% THEN
- Mouse 13, 0, 0, 0
- ELSE
- Mouse 14, 0, 0, 0
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseMaskTranslate
-
- Translates the pattern mask and hot spot values for a given graphics-mode
- mouse cursor to a binary format string suitable for passing to the
- memory-resident mouse driver for setting the cursor.
-
- This translation process is relatively time-consuming and should normally
- only be performed once, when a program first starts up. To save multiple
- cursors for quick switching between cursor types, save only the cursor$
- result from this subprogram. The call to MouseSetCursor, using this binary
- format cursor$, is very fast.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseMaskTranslate **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Translates mouse graphics cursor Mask$ to Cursor$.
- '
- ' EXAMPLE OF USE: MouseMaskTranslate mask$, xHot%, yHot%, cursor$
- ' PARAMETERS: mask$ Pattern mask that defines a mouse
- ' graphics-mode cursor
- ' xHot% X location of the hot spot
- ' yHot% Y location of the hot spot
- ' cursor$ The returned binary buffer string
- ' for the cursor
- ' VARIABLES: i% Looping index
- ' b% Integer formed from string bit representati
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB MouseMaskTranslate (mask$, xHot%, yHot%,
- ' cursor$)
- '
- SUB MouseMaskTranslate (mask$, xHot%, yHot%, cursor$) STATIC
- cursor$ = CHR$(xHot%) + CHR$(yHot%) + STRING$(64, 0)
- IF LEN(mask$) = 512 THEN
- FOR i% = 1 TO 32
- b% = BinStr2Bin%(MID$(mask$, i% * 16 - 15, 16))
- MID$(cursor$, i% + i% + 1, 2) = MKI$(b%)
- NEXT i%
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseMickey
-
- Returns the mouse "mickies," or relative motion counts, since the last
- call to this routine. If the mouse has not been moved since the last call,
- zeros are returned.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseMickey **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reads mouse mickey counts.
- '
- ' EXAMPLE OF USE: MouseMickey horizontal%, vertical%
- ' PARAMETERS: horizontal% Horizontal motion mickey counts
- ' vertical% Vertical motion mickey counts
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseMickey (horizontal, vertical%)
- '
- SUB MouseMickey (horizontal%, vertical%) STATIC
- Mouse 11, 0, horizontal%, vertical%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseNow
-
- Returns the state of the mouse buttons and the mouse location. This
- subprogram is one of the most useful routines presented. Four parameters
- are passed back: the states of the two mouse buttons and the horizontal
- and vertical location of the mouse.
-
- The horizontal position is scaled according to the current video mode. In
- most cases, the X position at the right edge of the screen is 639, no
- matter what the screen pixel range is. Check the returned values for the
- mode you want to use.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseNow **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the state of the mouse.
- '
- ' EXAMPLE OF USE: MouseNow leftButton%, rightButton%, xMouse%, yMouse%
- ' PARAMETERS: leftButton% Indicates left mouse button state
- ' rightButton% Indicates right mouse button state
- ' xMouse% X location of mouse
- ' yMouse% Y location of mouse
- ' VARIABLES: m2% Mouse driver parameter containing button
- ' press information
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseNow (leftButton%, rightButton%,
- ' xMouse%, yMouse%)
- '
- SUB MouseNow (leftButton%, rightButton%, xMouse%, yMouse%) STATIC
- Mouse 3, m2%, xMouse%, yMouse%
- leftButton% = ((m2% AND 1) <> 0)
- rightButton% = ((m2% AND 2) <> 0)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MousePressLeft
-
- Returns the position of the mouse at the time the left button was last
- pressed. Also returned is the number of left button presses since the last
- call to this subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MousePressLeft **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the mouse state at last press of left button.
- '
- ' EXAMPLE OF USE: MousePressLeft leftCount%, xMouse%, yMouse%
- ' PARAMETERS: leftCount% Number of times the left button has been
- ' pressed since the last call to this
- ' subprogram
- ' xMouse% X location of the mouse at the last pres
- ' of the left button
- ' yMouse% Y location of the mouse at the last pres
- ' of the left button
- ' VARIABLES: m1% Parameter for call to mouse driver
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MousePressLeft (leftCount%, xMouse%, yMo
- '
- SUB MousePressLeft (leftCount%, xMouse%, yMouse%) STATIC
- m1% = 5
- leftCount% = 0
- Mouse m1%, leftCount%, xMouse%, yMouse%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MousePressRight
-
- Returns the position of the mouse at the time the right button was last
- pressed. Also returned is the number of right button presses since the
- last call to this subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MousePressRight **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the mouse state at last press of right button.
- '
- SUB MousePressRight (rightCount%, xMouse%, yMouse%) STATIC
- m1% = 5
- rightCount% = 1
- Mouse m1%, rightCount%, xMouse%, yMouse%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MousePut
-
- Allows you to move the mouse to any desired location.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MousePut **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets the mouse position.
- '
- ' EXAMPLE OF USE: MousePut xMouse%, yMouse%
- ' PARAMETERS: xMouse% Horizontal location to place cursor
- ' yMouse% Vertical location to place cursor
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MousePut (xMouse%, yMouse%)
- '
- SUB MousePut (xMouse%, yMouse%) STATIC
- Mouse 4, 0, xMouse%, yMouse%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseRange
-
- Sets a rectangular area of the screen to which the mouse cursor will be
- limited. The mouse cursor will stay in the bounds defined, no matter which
- way the mouse is moved.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseRange **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets mouse range of motion.
- '
- ' EXAMPLE OF USE: MouseRange x1%, y1%, x2%, y2%
- ' PARAMETERS: x1% Upper left corner X coordinate
- ' y1% Upper left corner Y coordinate
- ' x2% Lower right corner X coordinate
- ' y2% Lower right corner Y coordinate
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseRange (x1%, y1%, x2%, y2%)
- '
- SUB MouseRange (x1%, y1%, x2%, y2%) STATIC
- Mouse 7, 0, x1%, x2%
- Mouse 8, 0, y1%, y2%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseReleaseLeft
-
- Returns the position of the mouse at the time the left button was last
- released. Also returned is the number of left button releases since the
- last call to this subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseReleaseLeft **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the mouse state at last release of left button.
- '
- ' EXAMPLE OF USE: MouseReleaseLeft leftCount%, xMouse%, yMouse%
- ' PARAMETERS: leftCount% Number of times the left button has been
- ' released since the last call to this
- ' subprogram
- ' xMouse% X location of the mouse at the last
- ' release of the left button
- ' yMouse% Y location of the mouse at the last
- ' release of the left button
- ' VARIABLES: m1% Parameter for call to mouse driver
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseReleaseLeft (leftCount%, xMouse%,
- ' yMouse%)
- '
- SUB MouseReleaseLeft (leftCount%, xMouse%, yMouse%) STATIC
- m1% = 6
- leftCount% = 0
- Mouse m1%, leftCount%, xMouse%, yMouse%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseReleaseRight
-
- Returns the position of the mouse at the time the right button was last
- released. Also returned is the number of right button releases since the
- last call to this subprogram.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseReleaseRight **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the mouse state at last release of right button.
- '
- ' EXAMPLE OF USE: MouseReleaseRight rightCount%, xMouse%, yMouse%
- ' PARAMETERS: rightCount% Number of times the right button has bee
- ' released since the last call to this
- ' subprogram
- ' xMouse% X location of the mouse at the last
- ' release of the right button
- ' yMouse% Y location of the mouse at the last
- ' release of the right button
- ' VARIABLES: m1% Parameter for call to mouse driver
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseReleaseRight (rightCount%, xMouse%,
- ' yMouse%)
- '
- SUB MouseReleaseRight (rightCount%, xMouse%, yMouse%) STATIC
- m1% = 6
- rightCount% = 1
- Mouse m1%, rightCount%, xMouse%, yMouse%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseSetGcursor
-
- Sets the mouse cursor using the binary-format cursor string created by an
- earlier call to the subprogram MouseMaskTranslate.
-
- To quickly switch among a selection of mouse cursors, keep the
- binary-format cursor strings available, and call this subprogram to change
- cursors.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseSetGcursor **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets mouse graphics cursor using cursor$.
- '
- ' EXAMPLE OF USE: MouseSetGcursor cursor$
- ' PARAMETERS: cursor$ Binary format cursor string
- ' VARIABLES: xHot% X hot spot location
- ' yHot% Y hot spot location
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseSetGcursor (cursor$)
- '
- SUB MouseSetGcursor (cursor$) STATIC
- xHot% = ASC(LEFT$(cursor$, 1))
- yHot% = ASC(MID$(cursor$, 2, 1))
- Mouse 9, xHot%, yHot%, SADD(cursor$) + 2
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseShow
-
- Activates the mouse cursor, making it visible and movable by the mouse. To
- turn the cursor off, use the MouseHide subprogram.
-
- When you are updating the screen, such as when printing text in a graphics
- mode, it's a good idea to hide the mouse just before printing and then
- show it after the printing is done. This helps prevent glitches or blank
- spots from appearing due to overlapping and unsynchronized pixel mapping
- between your program and the mouse driver.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseShow **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Shows the mouse cursor.
- '
- ' EXAMPLE OF USE: MouseShow
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseShow ()
- '
- SUB MouseShow STATIC
- Mouse 1, 0, 0, 0
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseSoftCursor
-
- Sets the software mouse cursor for text mode. This cursor changes the
- attributes of screen characters (foreground/background color, intensity,
- or underscoring) when the display adapter is in text mode. The easiest way
- to get a feel for how these masks work is by running the MOUSTCRS.BAS
- program.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseSoftCursor **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets text-mode software cursor.
- '
- ' EXAMPLE OF USE: MouseSoftCursor screenMask%, cursorMask%
- ' PARAMETERS: screenMask% Integer bit pattern for the screen mask
- ' cursorMask% Integer bit pattern for the cursor mask
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB MouseSoftCursor (screenMaks%, cursorMask%)
- ' DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- '
- SUB MouseSoftCursor (screenMask%, cursorMask%) STATIC
- Mouse 10, 0, screenMask%, cursorMask%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MouseWarp
-
- Sets the double-speed threshold for the mouse in units of mickies per
- second. The default setting is 64 mickies per second.
-
- Whenever the mouse is moved at a rate greater than the threshold value,
- the cursor motion is doubled. This helps zip the cursor across the screen
- during quick moves but allows slower, more accurate motion at slower
- speeds.
-
- To use the MouseInches subprogram to approximate the action of an
- absolute-motion pointing device, set the threshold to a large, unreachable
- value. For example, MouseWarp 9999 effectively turns off the threshold
- checking.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MouseWarp **
- ' ** Type: Subprogram **
- ' ** Module: MOUSSUBS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
-
- ' Sets double-speed threshold.
- '
- ' EXAMPLE OF USE: MouseWarp threshold%
- ' PARAMETERS: threshold% Mickies per second rate of threshold
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- ' DECLARE SUB MouseWarp (threshold%)
- '
- SUB MouseWarp (threshold%) STATIC
- Mouse 19, 0, 0, threshold%
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- MOUSTCRS
-
- The MOUSTCRS program lets you experiment with the screen and cursor masks
- that define the action of the software mouse cursor in text modes.
-
- Run the program and move the mouse cursor to any of the mask bits
- displayed near the bottom of the screen. Click with the left mouse button
- on any bit to toggle that bit, and move the cursor around the screen to
- see how the cursor's appearance is affected.
-
- To set any screen and cursor mask combination in your own programs, record
- the hexadecimal numbers for the two masks, and pass these two numbers to
- the MouseSoftCursor subprogram in the MOUSSUBS.BAS toolbox.
-
-
- Program Module: MOUSTCRS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: MOUSTCRS **
- ' ** Type: Program **
- ' ** Module: MOUSTCRS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: MIXED.QLB/.LIB
- ' Mouse
- ' .MAK FILE: MOUSTCRS.BAS
- ' MOUSSUBS.BAS
- ' BITS.BAS
- ' ATTRIB.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: screenMask% Integer bit mask for screen mask
- ' cursorMask% Integer bit mask for cursor mask
- ' leftCount% Count of left mouse button presses
- ' xm% Mouse X position at last left button pre
- ' ym% Mouse Y position at last left button pre
- ' row% Code for which screen bit row was select
- ' bit% Bit pattern determined by screen column
- ' click on
- ' screenMask$ String of 0s and 1s for bit pattern disp
- ' cursorMask$ String of 0s and 1s for bit pattern disp
- ' i% Looping index
- ' Shex$ Hexadecimal representation of the screen
- ' Chex$ Hexadecimal representation of the cursor
-
- ' Define constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Functions
- DECLARE FUNCTION Bin2BinStr$ (b%)
-
- ' Subprograms
- DECLARE SUB Attrib ()
- DECLARE SUB MouseHide ()
- DECLARE SUB MouseInstall (mouseFlag%)
- DECLARE SUB MousePressLeft (leftCount%, xMouse%, yMouse%)
- DECLARE SUB MouseShow ()
- DECLARE SUB MouseSoftCursor (screenMask%, cursorMask%)
-
- ' Is the mouse out there?
- MouseInstall mouseFlag%
- IF mouseFlag% = 0 THEN
- PRINT "Mouse does not appear to be installed. Check"
- PRINT "your mouse documentation for proper installation."
- PRINT
- SYSTEM
- END IF
-
- ' Put all attributes on the screen
- Attrib
-
- ' Set masks to initial state
- screenMask% = &H77FF
- cursorMask% = &H7700
-
- ' Create the outlined boxes
- COLOR 14, 0
- PRINT " +---+-------+---+--------+----------+--------+
- PRINT " | b | bckgd | i | foregd | char | = |
- PRINT " +-------------+---+-------+---+--------+----------+--------+
- PRINT " | screen mask | 0 | 111 | 0 | 111 | 11111111 | &H77FF |
- PRINT " | cursor mask | 0 | 111 | 0 | 111 | 00000000 | &H7700 |
- PRINT " +-------------+---+-------+---+--------+----------+--------+
-
- ' Print the instructions
- COLOR 11, 0
- PRINT "Click the mouse on any of the mask bits shown. Then, try the"
- PRINT "new cursor by moving across the attribute fields above.";
-
- ' Special indication for quitting
- COLOR 15, 0
- LOCATE 17, 1, 0
- PRINT "Click here";
- LOCATE 18, 1, 0
- PRINT "to Quit - ";
- COLOR 10, 0
- PRINT "X";
-
- ' Put mask bits into boxes on screen
- GOSUB PrintScreenMask
- GOSUB PrintCursorMask
-
- ' Activate the mouse
- MouseShow
-
- ' Do the main processing loop until the quit flag is set
- DO
- GOSUB MainLoop
- LOOP UNTIL quitFlag%
-
- ' All done
- MouseHide
- CLS
- SYSTEM
-
- ' Main processing loop
- MainLoop:
-
- ' Where was mouse when left button was last pressed?
- MousePressLeft leftCount%, xm%, ym%
-
- ' Was it on one of the two important rows of the screen?
- SELECT CASE ym%
- CASE 152
- row% = 1
- CASE 160
- row% = 2
- CASE ELSE
- row% = 0
- END SELECT
-
- ' Was it on an important column?
- SELECT CASE xm%
- CASE 80
- IF ym% = 136 THEN
- quitFlag% = TRUE
- END IF
- CASE 160
- bit% = &H8000
- CASE 200
- bit% = &H4000
- CASE 208
- bit% = &H2000
- CASE 216
- bit% = &H1000
- CASE 256
- bit% = &H800
- CASE 296
- bit% = &H400
- CASE 304
- bit% = &H200
- CASE 312
- bit% = &H100
- CASE 360
- bit% = &H80
- CASE 368
- bit% = &H40
- CASE 376
- bit% = &H20
- CASE 384
- bit% = &H10
- CASE 392
- bit% = &H8
- CASE 400
- bit% = &H4
- CASE 408
- bit% = &H2
- CASE 416
- bit% = &H1
- CASE ELSE
- bit% = 0
- END SELECT
-
- ' Modify the masks and update the cursor
- IF leftCount% THEN
- SELECT CASE row%
- CASE 1
- screenMask% = screenMask% XOR bit%
- CASE 2
- cursorMask% = cursorMask% XOR bit%
- CASE ELSE
- END SELECT
- MouseSoftCursor screenMask%, cursorMask%
- GOSUB PrintScreenMask
- GOSUB PrintCursorMask
- END IF
-
- ' End of main processing loop
- RETURN
-
- ' Put screen mask bits on the screen
- PrintScreenMask:
- COLOR 12, 0
- screenMask$ = ""
- screenMask$ = Bin2BinStr$(screenMask%)
- MouseHide
- FOR i% = 0 TO 15
- SELECT CASE i%
- CASE 0 TO 7
- LOCATE 20, 53 - i%, 0
- PRINT MID$(screenMask$, 16 - i%, 1);
- CASE 8 TO 10
- LOCATE 20, 48 - i%, 0
- PRINT MID$(screenMask$, 16 - i%, 1);
- CASE 11
- LOCATE 20, 44 - i%, 0
- PRINT MID$(screenMask$, 16 - i%, 1);
- CASE 12 TO 14
- LOCATE 20, 40 - i%, 0
- PRINT MID$(screenMask$, 16 - i%, 1);
- CASE 15
- LOCATE 20, 36 - i%, 0
- PRINT MID$(screenMask$, 16 - i%, 1);
- CASE ELSE
- END SELECT
- NEXT i%
- shex$ = "&H" + RIGHT$("000" + HEX$(screenMask%), 4)
- LOCATE 20, 57, 0
- COLOR 10, 0
- PRINT shex$;
- MouseShow
- RETURN
-
- ' Put cursor mask bits on the screen
- PrintCursorMask:
- COLOR 12, 0
- cursorMask$ = ""
- cursorMask$ = Bin2BinStr$(cursorMask%)
- MouseHide
- FOR i% = 0 TO 15
- SELECT CASE i%
- CASE 0 TO 7
- LOCATE 21, 53 - i%, 0
- PRINT MID$(cursorMask$, 16 - i%, 1);
- CASE 8 TO 10
- LOCATE 21, 48 - i%, 0
- PRINT MID$(cursorMask$, 16 - i%, 1);
- CASE 11
- LOCATE 21, 44 - i%, 0
- PRINT MID$(cursorMask$, 16 - i%, 1);
- CASE 12 TO 14
- LOCATE 21, 40 - i%, 0
- PRINT MID$(cursorMask$, 16 - i%, 1);
- CASE 15
- LOCATE 21, 36 - i%, 0
- PRINT MID$(cursorMask$, 16 - i%, 1);
- CASE ELSE
- END SELECT
- NEXT i%
- chex$ = "&H" + RIGHT$("000" + HEX$(cursorMask%), 4)
- LOCATE 21, 57, 0
- COLOR 10, 0
- PRINT chex$;
- MouseShow
- RETURN
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- OBJECT
-
- The OBJECT program lets you interactively create subprograms that produce
- graphics objects for your programs.
-
- When a QuickBASIC program uses the GET and PUT statements for graphics
- animation purposes, you'll often notice the objects being created on the
- screen as the program first starts up. The normal procedure is to create
- the graphics objects using the LINE and DRAW statements and then to save
- the objects in integer arrays using the GET statement. The creation of the
- objects the first time is relatively slow, compared with the very fast PUT
- statement.
-
- The OBJECT program lets you create these objects interactively and
- "off-line" until you're satisfied with their appearance. Then, this
- program automatically writes a subprogram source file that, when loaded or
- merged with your main program, quickly creates the integer arrays by
- simply reading the appropriate integers into the arrays.
-
- The best way to get a feel for this program is to give it a try. Run it,
- and follow the directions. You can edit a DRAW string, try it to see what
- the new object looks like, and then re-edit the string until you like the
- results. When you select the "Save" option, the program automatically
- determines the smallest integer array that will hold the object you've
- created and writes a source code subprogram file that creates and fills an
- integer array with the bit pattern for your object. Later on, you can load
- this source code file and re-edit the object to make other changes.
-
- To use the new object source code in your own program, merge the file into
- the program where you want to use the object. The program should run
- through the statements once, but you can use PUT statements repeatedly to
- animate or duplicate the image.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- OBJECT.BAS Program module
- SaveObject Sub Creates graphics "PUT" file source code
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: OBJECT
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: OBJECT **
- ' ** Type: Program **
- ' ** Module: OBJECT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Allows interactive graphics object creation.
- ' Dumps code for another program to be able to create
- ' the graphics object "PUT array" directly.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' .MAK FILE: OBJECT.BAS
- ' KEYS.BAS
- ' EDIT.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: quitFlag% Indicates user is ready to quit
- ' modeFlag% Indicates a valid graphics mode was sele
- ' mode% Graphics mode
- ' xMax% Maximum screen X coordinate
- ' yMax% Maximum screen Y coordinate
- ' fileName$ Name of object creation subprogram file
- ' exitCode% Return code from EditLine subprogram
- ' t$ Temporary work string while reading file
- ' contents
- ' a$ The DRAW string
- ' editFlag% Indicates an edit of the string is desir
- ' drawErrorFlag% Indicates an error occurred during the D
- ' keyNumber% Integer key code returned by KeyCode%
- ' function
- ' okayFlag% Shared flag for determining array dimens
-
- ' Logical constants
- CONST FALSE = 0
- CONST TRUE = NOT FALSE
-
- ' Key code constants
- CONST SKEYLC = 115
- CONST SKEYUC = SKEYLC - 32
- CONST QKEYLC = 113
- CONST QKEYUC = QKEYLC - 32
- CONST ESC = 27
-
- ' Color constants
- CONST BLACK = 0
- CONST BLUE = 1
- CONST GREEN = 2
- CONST CYAN = 3
- CONST RED = 4
- CONST MAGENTA = 5
- CONST BROWN = 6
- CONST WHITE = 7
- CONST BRIGHT = 8
- CONST BLINK = 16
- CONST YELLOW = BROWN + BRIGHT
-
- ' Functions
- DECLARE FUNCTION KeyCode% ()
-
- ' Subprograms
- DECLARE SUB DrawBox (row1%, col1%, row2%, col2%)
- DECLARE SUB EditBox (a$, row1%, col1%, row2%, col2%)
- DECLARE SUB EditLine (a$, exitCode%)
- DECLARE SUB SaveObject (mode%, xMax%, yMax%, fileName$, a$)
-
- ' Initialization
- SCREEN 0
- CLS
- quitFlag% = FALSE
-
- ' Title
- PRINT "OBJECT - Interactive graphics object editor"
- PRINT
- PRINT
-
- ' Display screen mode table
- PRINT "Adapter SCREEN modes allowed"
- PRINT "---------- --------------------"
- PRINT "Monochrome (none)"
- PRINT "Hercules 3"
- PRINT "CGA 1,2"
- PRINT "EGA 1,2,7,8,9"
- PRINT "MCGA 1,2,11,13"
- PRINT "VGA 1,2,7,8,9,11,12,13"
- PRINT
-
- ' Ask user for the graphics screen mode
- DO
- PRINT "Enter a SCREEN mode number, ";
- INPUT "based on your graphics adapter "; mode%
- modeFlag% = TRUE
- SELECT CASE mode%
- CASE 1, 7, 13
- xMax% = 319
- yMax% = 199
- CASE 2, 8
- xMax% = 639
- yMax% = 199
- CASE 9, 10
- xMax% = 639
- yMax% = 349
- CASE 11, 12
- xMax% = 639
- yMax% = 479
- CASE 3
- xMax% = 719
- yMax% = 347
- CASE ELSE
- modeFlag% = FALSE
- END SELECT
- LOOP UNTIL modeFlag% = TRUE
-
- ' Ask user for the filename
- fileName$ = "IMAGEARY.BAS" + SPACE$(20)
- SCREEN 0
- WIDTH 80
- CLS
- COLOR WHITE, BLACK
- PRINT "Name of the file where source code will be written:"
- PRINT
- PRINT "Edit the default filename IMAGEARY.BAS ";
- PRINT "if desired, and then press Enter..."
- PRINT
- PRINT SPACE$(12);
- COLOR YELLOW, BLUE
- EditLine fileName$, exitCode%
- COLOR WHITE, BLACK
-
- ' Try to read in previous contents of the file
- ON ERROR GOTO FileError
- OPEN fileName$ FOR INPUT AS #1
- ON ERROR GOTO 0
- DO UNTIL EOF(1)
- LINE INPUT #1, t$
- IF INSTR(t$, "(DRAW$)") THEN
- t$ = MID$(t$, INSTR(t$, CHR$(34)) + 1)
- t$ = LEFT$(t$, INSTR(t$, CHR$(34)) - 1)
- a$ = a$ + t$
- END IF
- LOOP
- CLOSE #1
-
- ' Main loop
- DO
-
- ' Prepare for DRAW string editing by the user
- SCREEN 0
- WIDTH 80
- CLS
- editFlag% = FALSE
-
- ' Display useful information
- PRINT "OBJECT - Screen mode"; mode%
- PRINT
- PRINT "Edit the DRAW string workspace; then press"
- PRINT "the Esc key to try out your creation..."
- PRINT
- PRINT , " Cn Color"
- PRINT , " H U E Mx,y Move absolute"
- PRINT , " \ | / M+|/-x,y Move relative"
- PRINT , " L - - R An Angle (1=90,2=180...)"
- PRINT , " / | \ TAn Turn angle (-360 to 360)"
- PRINT , " G D F Sn Scale factor"
- PRINT , " Pc,b Paint (color, border)"
- PRINT "(These commands are described in detail in the ";
- PRINT "Microsoft QuickBASIC Language Reference)"
-
- ' Input DRAW string via EditBox subprogram
- COLOR GREEN + BRIGHT, BLUE
- DrawBox 15, 1, 24, 80
- COLOR YELLOW, BLUE
- EditBox a$, 15, 1, 24, 80
-
- ' Try out the DRAW string
- SCREEN mode%
- drawErrorFlag% = FALSE
- ON ERROR GOTO DrawError
- DRAW a$
- ON ERROR GOTO 0
-
- ' Give user idea of what to do
- LOCATE 1, 1
- PRINT "<S>ave, <Esc> to edit, or <Q>uit"
-
- ' Get next valid keystroke
- DO UNTIL editFlag% OR drawErrorFlag% OR quitFlag%
-
- ' Grab key code
- keyNumber% = KeyCode%
-
- ' Process the keystroke
- SELECT CASE keyNumber%
-
- CASE ESC
- editFlag% = TRUE
-
- CASE QKEYLC, QKEYUC
- quitFlag% = TRUE
-
- CASE SKEYLC, SKEYUC
- SaveObject mode%, xMax%, yMax%, fileName$, a$
-
- CASE ELSE
- END SELECT
-
- LOOP
-
- LOOP UNTIL quitFlag%
-
- ' All done
- CLS
- SCREEN 0
- WIDTH 80
- END
-
- FileError:
- ' Create the new file
- OPEN fileName$ FOR OUTPUT AS #1
- CLOSE #1
- OPEN fileName$ FOR INPUT AS #1
- RESUME NEXT
-
- DrawError:
- drawErrorFlag% = TRUE
- SCREEN 0
- CLS
- PRINT "Your DRAW string caused an error"
- PRINT
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
- RESUME NEXT
-
- ArrayError:
- okayFlag% = FALSE
- RESUME NEXT
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SaveObject
-
- Creates a source code subprogram module file for the OBJECT program.
-
- This subprogram performs the tricky task of finding the boundaries of the
- graphics object, dimensioning an integer array of exactly the right size,
- getting the object from the screen and into the array, and writing a
- source code subprogram file that will recreate the array when merged into
- a different program.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SaveObject **
- ' ** Type: Subprogram **
- ' ** Module: OBJECT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Creates source code file for creating graphics mode
- ' objects for efficient "PUT" graphics.
- '
- ' EXAMPLE OF USE: SaveObject mode%, xMax%, yMax%, fileName$, a$
- ' PARAMETERS: mode% Graphics mode
- ' xMax% Maximum X screen coordinate for given
- ' graphics mode
- ' yMax% Maximum Y screen coordinate for given
- ' graphics mode
- ' fileName$ Name of source code file to edit and/or
- ' create
- ' a$ The DRAW string that creates the object
- ' initially
- ' VARIABLES: okayFlag% Shared flag used to determine array size
- ' size% Array sizing
- ' edge% Array for efficiently finding edges of obj
- ' stepSize% Scanning step for search for object edges
- ' yTop% Y coordinate at top edge of object
- ' yBot% Y coordinate at bottom edge of object
- ' y1% Starting edge search Y coordinate
- ' y2% Ending edge search Y coordinate
- ' i% Looping index
- ' xLeft% X coordinate at left edge of object
- ' xRight% X coordinate at right edge of object
- ' x1% Starting edge search X coordinate
- ' x2% Ending edge search X coordinate
- ' object%() Array to hold GET object from screen
- ' objName$ Name of object, derived from filename
- ' ndx% Index to any special characters in objName
- ' ary$ Name of array, derived from filename
- ' d$ Works string for building lines for file
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION SaveObject (mode%, xMax%, yMax%,
- ' fileName$, a$)
- '
- SUB SaveObject (mode%, xMax%, yMax%, fileName$, a$) STATIC
-
- ' Shared error trap variable
- SHARED okayFlag%
-
- ' Select the right array size for the mode
- SELECT CASE mode%
- CASE 1, 2
- size% = 93
- CASE 7, 8
- size% = 367
- CASE 9
- size% = 667
- CASE 10
- size% = 334
- CASE 11
- size% = 233
- CASE 12
- size% = 927
- CASE 13
- size% = 161
- CASE ELSE
- END SELECT
-
- ' Build the array space
- DIM edge%(size%)
-
- ' Scan to find top and bottom edges of the object
- stepSize% = 32
- yTop% = yMax%
- yBot% = 0
- y1% = 17
- y2% = yMax%
- DO
- FOR y% = y1% TO y2% STEP stepSize%
- IF y% < yTop% OR y% > yBot% THEN
- GET (0, y%)-(xMax%, y%), edge%
- LINE (0, y%)-(xMax%, y%)
- FOR i% = 2 TO size%
- IF edge%(i%) THEN
- IF y% < yTop% THEN
- yTop% = y%
- END IF
- IF y% > yBot% THEN
- yBot% = y%
- END IF
- i% = size%
- END IF
- NEXT i%
- PUT (0, y%), edge%, PSET
- END IF
- NEXT y%
- IF yTop% <= yBot% THEN
- y1% = yTop% - stepSize% * 2
- y2% = yBot% + stepSize% * 2
- IF y1% < 17 THEN
- y1% = 17
- END IF
- IF y2% > yMax% THEN
- y2% = yMax%
- END IF
- END IF
- stepSize% = stepSize% \ 2
- LOOP UNTIL stepSize% = 0
-
- ' Scan to find left and right edges of the object
- stepSize% = 32
- xLeft% = xMax%
- xRight% = 0
- x1% = 0
- x2% = xMax%
- DO
- FOR x% = x1% TO x2% STEP stepSize%
- IF x% < xLeft% OR x% > xRight% THEN
- GET (x%, yTop%)-(x%, yBot%), edge%
- LINE (x%, yTop%)-(x%, yBot%)
- FOR i% = 2 TO size%
- IF edge%(i%) THEN
- IF x% < xLeft% THEN
- xLeft% = x%
- END IF
- IF x% > xRight% THEN
- xRight% = x%
- END IF
- i% = size%
- END IF
- NEXT i%
- PUT (x%, yTop%), edge%, PSET
- END IF
- NEXT x%
- IF xLeft% <= xRight% THEN
- x1% = xLeft% - stepSize% * 2
- x2% = xRight% + stepSize% * 2
- IF x1% < 0 THEN
- x1% = 0
- END IF
- IF x2% > xMax% THEN
- x2% = xMax%
- END IF
- END IF
- stepSize% = stepSize% \ 2
- LOOP UNTIL stepSize% = 0
-
- ' Draw border around the object
- LINE (xLeft% - 1, yTop% - 1)-(xRight% + 1, yBot% + 1), , B
-
- ' Build the right size integer array
- stepSize% = 256
- size% = 3
- DO
- DO
- IF size% < 3 THEN
- size% = 3
- END IF
- REDIM object%(size%)
- okayFlag% = TRUE
- ON ERROR GOTO ArrayError
- GET (xLeft%, yTop%)-(xRight%, yBot%), object%
- ON ERROR GOTO 0
- IF okayFlag% = FALSE THEN
- size% = size% + stepSize%
- ELSE
- IF stepSize% > 1 THEN
- size% = size% - stepSize%
- END IF
- END IF
- LOOP UNTIL okayFlag%
- stepSize% = stepSize% \ 2
- LOOP UNTIL stepSize% = 0
-
- ' Make the name of the object
- objName$ = LTRIM$(RTRIM$(fileName$)) + "."
- ndx% = INSTR(objName$, "\")
- DO WHILE ndx%
- objName$ = MID$(objName$, ndx% + 1)
- ndx% = INSTR(objName$, "\")
- LOOP
- ndx% = INSTR(objName$, ":")
- DO WHILE ndx%
- objName$ = MID$(objName$, ndx% + 1)
- ndx% = INSTR(objName$, ":")
- LOOP
- ndx% = INSTR(objName$, ".")
- objName$ = LCASE$(LEFT$(objName$, ndx% - 1))
- IF objName$ = "" THEN
- objName$ = "xxxxxx"
- END IF
-
- ' Make array name
- ary$ = objName$ + "%("
-
- ' Open the file for the new source lines
- OPEN fileName$ FOR OUTPUT AS #1
-
- ' Print the lines
- PRINT #1, " "
- PRINT #1, " ' " + objName$
- FOR i% = 1 TO LEN(a$) STEP 50
- PRINT #1, " ' (DRAW$) "; CHR$(34);
- PRINT #1, MID$(a$, i%, 50); CHR$(34)
- NEXT i%
- PRINT #1, " DIM " + ary$; "0 TO";
- PRINT #1, STR$(size%) + ")"
- PRINT #1, " FOR i% = 0 TO"; size%
- PRINT #1, " READ h$"
- PRINT #1, " " + ary$ + "i%) = VAL(";
- PRINT #1, CHR$(34) + "&H" + CHR$(34);
- PRINT #1, " + h$)"
- PRINT #1, " NEXT i%"
- FOR i% = 0 TO size%
- IF d$ = "" THEN
- d$ = " DATA "
- ELSE
- d$ = d$ + ","
- END IF
- d$ = d$ + HEX$(object%(i%))
- IF LEN(d$) > 60 OR i% = size% THEN
- PRINT #1, d$
- d$ = ""
- END IF
- NEXT i%
- PRINT #1, " "
-
- ' Close the file
- CLOSE
-
- ' Erase the border around the object
- LINE (xLeft% - 1, yTop% - 1)-(xRight% + 1, yBot% + 1), 0, B
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PARSE
-
- The PARSE toolbox demonstrates the ParseLine and ParseWord subprograms.
- A sample string of text (x$) is parsed by each of these subprograms, and
- the results are displayed for review.
-
- The purpose of these subprograms is to split a string into substrings,
- where each substring is delineated by any of a given set of characters
- that you define. For example, a string can be parsed into individual words
- by splitting the string wherever spaces or commas occur.
-
- A common use for these subprograms would be the processing of a list of
- commands passed to a QuickBASIC program from the MS-DOS command line,
- available in the special variable COMMAND$. The HEX2BIN, BIN2HEX, and
- QBFMT programs use the PARSE toolbox in this way.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- PARSE.BAS Demo module
- ParseLine Sub Breaks a string into individual words
- ParseWord Sub Parses and removes first word from string
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: PARSE
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: PARSE **
- ' ** Type: Toolbox **
- ' ** Module: PARSE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: a$() Array of words parsed from x$
- ' x$ String to be parsed
- ' sep$ Characters defining word separation
- ' word$ Each word from the string
- ' n% Index to each word in array
-
- DECLARE SUB ParseLine (x$, sep$, a$())
- DECLARE SUB ParseWord (a$, sep$, word$)
-
- ' Initialization
- CLS
- DIM a$(1 TO 99)
-
- ' Demonstrate ParseWord
- x$ = "This is a test line. A,B,C, etc."
- sep$ = " ,"
- PRINT "x$:", x$
- PRINT "sep$:", CHR$(34); sep$; CHR$(34)
- ParseWord x$, sep$, word$
- PRINT "ParseWord x$, sep$, word$"
- PRINT "x$:", x$
- PRINT "word$:", word$
-
- ' Demonstrate ParseLine
- PRINT
- x$ = "This is a test line. A,B,C, etc."
- sep$ = " ,"
- PRINT "x$:", x$
- PRINT "sep$:", CHR$(34); sep$; CHR$(34)
- ParseLine x$, sep$, a$()
- PRINT "ParseLine x$, sep$, a$()"
- PRINT "a$()..."
- DO
- n% = n% + 1
- PRINT n%, a$(n%)
- LOOP UNTIL a$(n% + 1) = ""
-
- ' All done
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ParseLine
-
- Parses a string into individual words, returning the list of words in a
- string array. You can list any characters in sep$ to define the division
- between words, but the most commonly used characters are space, comma, and
- tab. The string array will contain a null string after the last word
- parsed from the string.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ParseLine **
- ' ** Type: Subprogram **
- ' ** Module: PARSE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Breaks a string into an array of words, as defined
- ' by any characters listed in sep$.
- '
- ' EXAMPLE OF USE: ParseLine x$, sep$, a$()
- ' PARAMETERS: x$ String to be parsed
- ' sep$ List of characters defined as word separators
- ' a$() Returned array of words
- ' VARIABLES: t$ Temporary work string
- ' i% Index to array entries
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB ParseLine (x$, sep$, a$())
- '
- SUB ParseLine (x$, sep$, a$()) STATIC
- t$ = x$
- FOR i% = LBOUND(a$) TO UBOUND(a$)
- ParseWord t$, sep$, a$(i%)
- IF a$(i%) = "" THEN
- EXIT FOR
- END IF
- NEXT i%
- t$ = ""
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ParseWord
-
- Extracts the first word from the front of a string, returning the word and
- the original string minus the leading word. You can call this routine
- repeatedly to parse out each word, one at a time. You set the characters
- that separate words in sep$. For example, to parse words separated by
- either spaces or commas, set as follows:
-
-
- sep$ = " ,"
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ParseWord **
- ' ** Type: Subprogram **
- ' ** Module: PARSE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Breaks off the first word in a$, as delimited by
- ' any characters listed in sep$.
- '
- ' EXAMPLE OF USE: ParseWord a$, sep$, word$
- ' PARAMETERS: a$ String to be parsed
- ' sep$ List of characters defined as word separato
- ' word$ Returned first word parsed from a$
- ' VARIABLES: lena% Length of a$
- ' i% Looping index
- ' j% Looping index
- ' k% Looping index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB ParseWord (a$, sep$, word$)
- '
- SUB ParseWord (a$, sep$, word$) STATIC
- word$ = ""
- lena% = LEN(a$)
- IF a$ = "" THEN
- EXIT SUB
- END IF
- FOR i% = 1 TO lena%
- IF INSTR(sep$, MID$(a$, i%, 1)) = 0 THEN
- EXIT FOR
- END IF
- NEXT i%
- FOR j% = i% TO lena%
- IF INSTR(sep$, MID$(a$, j%, 1)) THEN
- EXIT FOR
- END IF
- NEXT j%
- FOR k% = j% TO lena%
- IF INSTR(sep$, MID$(a$, k%, 1)) = 0 THEN
- EXIT FOR
- END IF
- NEXT k%
- IF i% > lena% THEN
- a$ = ""
- EXIT SUB
- END IF
- IF j% > lena% THEN
- word$ = MID$(a$, i%)
- a$ = ""
- EXIT SUB
- END IF
- word$ = MID$(a$, i%, j% - i%)
- IF k% > lena% THEN
- a$ = ""
- ELSE
- a$ = MID$(a$, k%)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PROBSTAT
-
- The PROBSTAT toolbox is a collection of functions for probability and
- statistics calculations.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- PROBSTAT.BAS Demo module
- ArithmeticMean# Func Arithmetic mean of an array of
- numbers
- Combinations# Func Combinations of n items, r at a time
- Factorial# Func Factorial of a number
- GeometricMean# Func Geometric mean of an array of numbers
- HarmonicMean# Func Harmonic mean of an array of numbers
- Permutations# Func Permutations of n items, r at a time
- QuadraticMean# Func Quadratic mean of an array of numbers
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: PROBSTAT
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: PROBSTAT **
- ' ** Type: Toolbox **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates several probability- and statistics-
- ' related mathematical functions.
- '
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: a#() Array of numbers to be processed
- ' i% Index into array
- ' n& Number of items for combinations and permuta
- ' r& Quantity for combinations and permutations
- '
- DECLARE FUNCTION Combinations# (n&, r&)
- DECLARE FUNCTION Factorial# (n&)
- DECLARE FUNCTION Permutations# (n&, r&)
- DECLARE FUNCTION GeometricMean# (a#())
- DECLARE FUNCTION HarmonicMean# (a#())
- DECLARE FUNCTION ArithmeticMean# (a#())
- DECLARE FUNCTION QuadraticMean# (a#())
-
- ' Demonstrations
- CLS
- PRINT "PROBSTAT"
- PRINT
- PRINT "Array of numbers..."
- DIM a#(-3 TO 6)
- FOR i% = -3 TO 6
- READ a#(i%)
- PRINT a#(i%),
- NEXT i%
- PRINT
- DATA 1.2,3.4,5.6,7.8,9.1,2.3,4.5,6.7,8.9,1.2
-
- PRINT
- PRINT "Arithmetic mean = "; ArithmeticMean#(a#())
- PRINT "Geometric mean = "; GeometricMean#(a#())
- PRINT "Harmonic mean = "; HarmonicMean#(a#())
- PRINT "Quadratic mean = "; QuadraticMean#(a#())
- PRINT
-
- n& = 17
- r& = 5
- PRINT "Combinations of"; n&; "objects taken";
- PRINT r&; "at a time = "; Combinations#(n&, r&)
-
- PRINT "Permutations of"; n&; "objects taken";
- PRINT r&; "at a time = "; Permutations#(n&, r&)
-
- PRINT
- PRINT "Factorial of 17 = "; Factorial#(17&)
-
- ' All done
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ArithmeticMean#
-
- Returns the arithmetic mean of an array of double-precision numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ArithmeticMean# **
- ' ** Type: Function **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the arithmetic mean of an array of numbers.
- '
- ' EXAMPLE OF USE: ArithmeticMean# a#()
- ' PARAMETERS: a#() Array of double-precision numbers to be
- ' processed
- ' VARIABLES: n% Count of array entries
- ' sum# Sum of the array entries
- ' i% Looping index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ArithmeticMean# (a#())
- '
- FUNCTION ArithmeticMean# (a#()) STATIC
- n% = 0
- sum# = 0
- FOR i% = LBOUND(a#) TO UBOUND(a#)
- n% = n% + 1
- sum# = sum# + a#(i%)
- NEXT i%
- ArithmeticMean# = sum# / n%
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Combinations#
-
- Calculates the number of combinations of n& items taken r& at a time. This
- function returns a double-precision result to allow for larger answers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Combinations# **
- ' ** Type: Function **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the number of combinations of n& items
- ' taken r& at a time.
- '
- ' EXAMPLE OF USE: c# = Combinations#(n&, r&)
- ' PARAMETERS: n& Number of items
- ' r& Taken r& at a time
- ' VARIABLES: result# Working result variable
- ' j& Working copy of r&
- ' k& Difference between n& and r&
- ' h& Values from r& through n&
- ' i& Values from 1 through j&
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Combinations# (n&, r&)
- '
- FUNCTION Combinations# (n&, r&) STATIC
- result# = 1
- j& = r&
- k& = n& - r&
- h& = n&
- IF j& > k& THEN
- SWAP j&, k&
- END IF
- FOR i& = 1 TO j&
- result# = (result# * h&) / i&
- h& = h& - 1
- NEXT i&
- Combinations# = result#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Factorial#
-
- Returns the factorial of a long integer. The returned value is
- double-precision, allowing for larger arguments. This is a recursive
- function. If the argument n& is greater than 1, n& is multiplied by the
- result of finding the factorial of n& - 1. The result is that this
- function will call itself n& times.
-
- Notice that the STATIC keyword is missing from the end of the FUNCTION
- statement because recursive functions must not be defined as STATIC.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Factorial# **
- ' ** Type: Function **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the factorial of n& (recursive).
- '
- ' EXAMPLE OF USE: f# = Factorial#(n&)
- ' PARAMETERS: n& Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Factorial# (n&)
- '
- FUNCTION Factorial# (n&)
- IF n& > 1 THEN
- Factorial# = n& * Factorial#(n& - 1)
- ELSE
- Factorial# = 1
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: GeometricMean#
-
- Returns the geometric mean of an array of double-precision numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: GeometricMean# **
- ' ** Type: Function **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the geometric mean of an array of numbers.
- '
- ' EXAMPLE OF USE: gm# = GeometricMean#(a#())
- ' PARAMETERS: a#() Array of numbers to be processed
- ' VARIABLES: n% Count of numbers
- ' product# Product of all the numbers
- ' i% Index to array entries
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION GeometricMean# (a#())
- '
- FUNCTION GeometricMean# (a#()) STATIC
- n% = 0
- product# = 1
- FOR i% = LBOUND(a#) TO UBOUND(a#)
- n% = n% + 1
- product# = product# * a#(i%)
- NEXT i%
- GeometricMean# = product# ^ (1 / n%)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: HarmonicMean#
-
- Returns the harmonic mean of an array of double-precision numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: HarmonicMean# **
- ' ** Type: Function **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the harmonic mean of an array of numbers.
- '
- ' EXAMPLE OF USE: hm# = HarmonicMean#(a#())
- ' PARAMETERS: a#() Array of numbers to be processed
- ' VARIABLES: n% Number of array entries
- ' sum# Sum of the reciprocal of each number
- ' i% Index to each array entry
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION HarmonicMean# (a#())
- '
- FUNCTION HarmonicMean# (a#()) STATIC
- n% = 0
- sum# = 0
- FOR i% = LBOUND(a#) TO UBOUND(a#)
- n% = n% + 1
- sum# = sum# + 1# / a#(i%)
- NEXT i%
- HarmonicMean# = n% / sum#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Permutations#
-
- Returns the number of permutations of n& items taken r& at a time.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Permutations# **
- ' ** Type: Function **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the permutations of n& items taken r& at a time.
- '
- ' EXAMPLE OF USE: perm# = Permutations#(n&, r&)
- ' PARAMETERS: n& Number of items
- ' r& Taken r& at a time
- ' VARIABLES: p# Working variable for permutations
- ' i& Loop index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Permutations# (n&, r&)
- '
- FUNCTION Permutations# (n&, r&) STATIC
- p# = 1
- FOR i& = n& - r& + 1 TO n&
- p# = p# * i&
- NEXT i&
- Permutations# = p#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: QuadraticMean#
-
- Returns the quadratic mean of an array of double-precision numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: QuadraticMean# **
- ' ** Type: Function **
- ' ** Module: PROBSTAT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the quadratic mean of an array of numbers.
- '
- ' EXAMPLE OF USE: qm# = QuadraticMean#(a#())
- ' PARAMETERS: a#() Array of numbers to be processed
- ' VARIABLES: n% Count of array entries
- ' sum# Sum of the square of each number
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION QuadraticMean# (a#())
- '
- FUNCTION QuadraticMean# (a#()) STATIC
- n% = 0
- sum# = 0
- FOR i% = LBOUND(a#) TO UBOUND(a#)
- n% = n% + 1
- sum# = sum# + a#(i%) ^ 2
- NEXT i%
- QuadraticMean# = SQR(sum# / n%)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- QBFMT
-
- The QBFMT program reformats QuickBASIC modules by indenting the lines
- according to the structure of the statements. For example, all lines found
- between matching DO and LOOP statements are indented four character
- columns more than the DO and LOOP statements. Of course, nested structures
- are indented even farther.
-
- One advantage of processing a file with this program is that improperly
- matched statements are detected. Improper matching can happen if, for
- example, you forget to type an END IF statement to match an IF. A special
- comment line is placed in the file at the point where each error is
- detected.
-
- This utility program was an immense help throughout the creation of this
- book. Each module was formatted with this program, resulting in a
- consistent structure, style, and general appearance to the listings.
-
- Notice that QuickBASIC programs to be processed by the QBFMT program must
- be saved in text format and have the extension .BAS.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- QBFMT.BAS Program module
- Indent Sub Performs line indention
- SetCode Sub Determines indention code by keyword
- SplitUp Sub Splits line into major components
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: QBFMT
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: QBFMT **
- ' ** Type: Program **
- ' ** Module: QBFMT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reformats a QuickBASIC program by indenting
- ' lines according to the structure of the statements. The
- ' default amount is 4 spaces if no indention parameter
- ' is given on the command line.
- '
- ' USAGE: QBFMT filename [indention]
- ' Command$ = filename [indention]
- ' .MAK FILE: QBFMT.BAS
- ' PARSE.BAS
- ' STRINGS.BAS
- ' PARAMETERS: filename(.BAS) Name of QuickBASIC module to be formatted
- ' the module must be saved in "Text" format
- ' VARIABLES: md$ Working copy of COMMAND$ contents
- ' fileName$ Name of QuickBASIC module to be formatted
- ' dpoint% Position of the decimal point character
- ' in cmd$
- ' ndent$ Part of cmd$ dealing with optional
- ' indention amount
- ' indention% Number of character columns per
- ' indention level
- ' progline$ Each line of the file being processed
- ' indentLevel% Keeps track of current indention amount
- ' nest$ Message placed in file if faulty structur
- ' detected
-
- DECLARE FUNCTION LtrimSet$ (a$, set$)
- DECLARE FUNCTION RtrimSet$ (a$, set$)
- DECLARE SUB Indent (a$, indention%, indentLevel%)
- DECLARE SUB ParseWord (a$, sep$, word$)
- DECLARE SUB SetCode (a$, keyWord$, code%)
- DECLARE SUB SplitUp (a$, comment$, keyWord$)
-
- ' Decipher the user command line
- cmd$ = COMMAND$
- IF cmd$ = "" THEN
- PRINT
- PRINT "Usage: QBFMT filename(.BAS) [indention]"
- SYSTEM
- ELSE
- ParseWord cmd$, " ,", fileName$
- dpoint% = INSTR(fileName$, ".")
- IF dpoint% THEN
- fileName$ = LEFT$(fileName$, dpoint% - 1)
- END IF
- ParseWord cmd$, " ,", ndent$
- indention% = VAL(ndent$)
- IF indention% < 1 THEN
- indention% = 4
- END IF
- END IF
-
- ' Try to open the indicated files
- PRINT
- ON ERROR GOTO ErrorTrapOne
- OPEN fileName$ + ".BAS" FOR INPUT AS #1
- OPEN fileName$ + ".@$@" FOR OUTPUT AS #2
- ON ERROR GOTO 0
-
- ' Process each line of the file
- DO
- LINE INPUT #1, progLine$
- Indent progLine$, indention%, indentLevel%
- PRINT progLine$
- PRINT #2, progLine$
- IF indentLevel% < 0 OR (EOF(1) AND indentLevel% <> 0) THEN
- SOUND 555, 5
- SOUND 333, 9
- nest$ = "'<<<<<<<<<<<<<<<<<<<<< Nesting error detected!"
- PRINT nest$
- PRINT #2, nest$
- indentLevel% = 0
- END IF
- LOOP UNTIL EOF(1)
-
- ' Close all files
- CLOSE
-
- ' Delete any old .BAK file
- ON ERROR GOTO ErrorTrapTwo
- KILL fileName$ + ".BAK"
- ON ERROR GOTO 0
-
- ' Rename the files
- NAME fileName$ + ".BAS" AS fileName$ + ".BAK"
- NAME fileName$ + ".@$@" AS fileName$ + ".BAS"
-
- ' We're done
- END
-
- '----------- Error trapping routines
-
- ErrorTrapOne:
- PRINT "Error while opening files"
- SYSTEM
-
- ErrorTrapTwo:
- RESUME NEXT
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Indent
-
- Performs the task of indenting each line of a program for the QBFMT
- program. The indention amount is determined by the first word of each
- line, and spaces are added to the front end of each line accordingly.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Indent **
- ' ** Type: Subprogram **
- ' ** Module: QBFMT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Determines the indention for each line.
- '
- ' EXAMPLE OF USE: Indent a$, indention%, indentLevel%
- ' PARAMETERS: a$ Program line to be indented
- ' indention% Spaces to add for each indention level
- ' indentLevel% Level of indention
- ' VARIABLES: comment$ Part of program line that represents a
- ' REMARK
- ' keyWord$ First word of the program line
- ' code% Indention control code determined by
- ' keyWord$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Indent (a$, indention%, indentLevel%)
- '
- SUB Indent (a$, indention%, indentLevel%) STATIC
-
- ' Break line into manageable parts
- SplitUp a$, comment$, keyWord$
-
- IF keyWord$ <> "" THEN
-
- ' Set indention code according to type of keyword
- SetCode a$, keyWord$, code%
-
- ' Build a string of spaces for the indicated indention
- SELECT CASE code%
- CASE -2
- a$ = SPACE$(indention% * indentLevel%) + a$
- CASE -1
- a$ = SPACE$(indention% * indentLevel%) + a$
- indentLevel% = indentLevel% - 1
- CASE 0
- a$ = SPACE$(indention% * (indentLevel% + 1)) + a$
- CASE 1
- indentLevel% = indentLevel% + 1
- a$ = SPACE$(indention% * indentLevel%) + a$
- CASE ELSE
- END SELECT
- ELSE
- a$ = SPACE$(indention% * indentLevel% + 2)
- END IF
-
- ' Round out the position of trailing comments
- IF comment$ <> "" THEN
- IF a$ <> SPACE$(LEN(a$)) AND a$ <> "" THEN
- a$ = a$ + SPACE$(16 - (LEN(a$) MOD 16))
- END IF
- END IF
-
- ' Tack the comment back onto the end of the line
- a$ = a$ + comment$
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SetCode
-
- Determines the indention code for the QBFMT program based on the first
- word of each program line. For example, if the first word of a program
- line is FOR, a code number is returned that signals the QBFMT program to
- indent the following lines one more level. When NEXT is encountered, the
- indention level decreases by one.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SetCode **
- ' ** Type: Subprogram **
- ' ** Module: QBFMT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Determines a code number for the type of indention
- ' implied by the various types of keywords that begin
- ' each line of QuickBASIC programs.
- '
- ' EXAMPLE OF USE: SetCode a$, keyWord$, code%
- ' PARAMETERS: a$ Program line to indent
- ' keyWord$ First word of the program line
- ' code% Returned code indicating the action to be
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB SetCode (a$, keyWord$, code%)
- '
- SUB SetCode (a$, keyWord$, code%) STATIC
- SELECT CASE keyWord$
- CASE "DEF"
- IF INSTR(a$, "=") THEN
- code% = 0
- ELSE
- IF INSTR(a$, " SEG") = 0 THEN
- code% = 1
- END IF
- END IF
- CASE "ELSE"
- code% = -2
- CASE "ELSEIF"
- code% = -2
- CASE "CASE"
- code% = -2
- CASE "END"
- IF a$ <> "END" THEN
- code% = -1
- ELSE
- code% = 0
- END IF
- CASE "FOR"
- code% = 1
- CASE "DO"
- code% = 1
- CASE "SELECT"
- code% = 1
- CASE "IF"
- IF RIGHT$(a$, 4) = "THEN" THEN
- code% = 1
- ELSE
- code% = 0
- END IF
- CASE "NEXT"
- code% = -1
- CASE "LOOP"
- code% = -1
- CASE "SUB"
- code% = 1
- CASE "FUNCTION"
- code% = 1
- CASE "TYPE"
- code% = 1
- CASE "WHILE"
- code% = 1
- CASE "WEND"
- code% = -1
- CASE ELSE
- code% = 0
- END SELECT
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SplitUp
-
- Breaks each program line into its major components for the QBFMT program.
- Leading spaces and tabs are removed, and the first word and any REMARK
- part are returned. Later, after the line is indented the proper amount,
- the parts of the line are patched back together and output to the program
- listing file.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SplitUp **
- ' ** Type: Subprogram **
- ' ** Module: QBFMT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Splits the line into statement, comment, and keyword.
- '
- ' EXAMPLE OF USE: SplitUp a$, comment$, keyWord$
- ' PARAMETERS: a$ Program line to be split up
- ' comment$ Part of line following "REM" or "'"
- ' keyWord$ First word of program line
- ' VARIABLES: set$ Characters to be trimmed, space and tab
- ' strFlag% Indication of a quoted string
- ' k% Index to start of REMARK
- ' i% Looping index
- ' m% Pointer to REMARK
- ' sptr% Pointer to first space following the
- ' first word in a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB SplitUp (a$, comment$, keyWord$)
- '
- SUB SplitUp (a$, comment$, keyWord$) STATIC
- set$ = " " + CHR$(9)
- strFlag% = 0
- k% = 0
- FOR i% = LEN(a$) TO 1 STEP -1
- IF MID$(a$, i%, 1) = CHR$(34) THEN
- IF strFlag% = 0 THEN
- strFlag% = 1
- ELSE
- strFlag% = 0
- END IF
- END IF
- IF MID$(a$, i%, 1) = "'" OR MID$(a$, i%, 3) = "REM" THEN
- IF strFlag% = 0 THEN
- k% = i%
- END IF
- END IF
- NEXT i%
- IF k% > 0 THEN
- m% = 0
- FOR j% = k% - 1 TO 1 STEP -1
- IF INSTR(set$, MID$(a$, j%, 1)) = 0 THEN
- IF m% = 0 THEN m% = j%
- END IF
- NEXT j%
- IF m% THEN
- comment$ = MID$(a$, m% + 1)
- a$ = LEFT$(a$, m%)
- ELSE
- comment$ = a$
- a$ = ""
- END IF
- ELSE
- comment$ = ""
- END IF
- a$ = LtrimSet$(a$, set$)
- a$ = RtrimSet$(a$, set$)
- comment$ = LtrimSet$(comment$, set$)
- comment$ = RtrimSet$(comment$, set$)
- sptr% = INSTR(a$, " ")
- IF sptr% THEN
- keyWord$ = UCASE$(LEFT$(a$, sptr% - 1))
- ELSE
- keyWord$ = UCASE$(a$)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- QBTREE
-
- The QBTREE program performs a recursive directory search and then displays
- all file entries indented for each level of subdirectory encountered. If a
- command line parameter is given, the search starts at the indicated path.
- If no command line parameter is given, the search begins with the current
- directory.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- QBTREE.BAS Program module
- FileTreeSearch Sub Recursive directory search routine
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: QBTREE
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: QBTREE **
- ' ** Type: Program **
- ' ** Module: QBTREE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' This program creates a list of directories and
- ' subdirectories, and all files in them. If no
- ' command line path is given, the search
- ' begins with the current directory.
- '
- ' USAGE: QBTREE [path]
- ' REQUIREMENTS: MIXED.QLB/.LIB
- ' .MAK FILE: QBTREE.BAS
- ' FILEINFO.BAS
- ' PARAMETERS: path Path for starting directory search
- ' VARIABLES: path$ Path string, from the command line, or set
- ' to "*.*"
- ' indent% Indention amount for printing
-
-
- TYPE RegTypeX
- ax AS INTEGER
- bx AS INTEGER
- cx AS INTEGER
- dx AS INTEGER
- bp AS INTEGER
- si AS INTEGER
- di AS INTEGER
- flags AS INTEGER
- ds AS INTEGER
- es AS INTEGER
- END TYPE
-
- TYPE FileDataType
- finame AS STRING * 12
- year AS INTEGER
- month AS INTEGER
- day AS INTEGER
- hour AS INTEGER
- minute AS INTEGER
- second AS INTEGER
- attribute AS INTEGER
- size AS LONG
- END TYPE
-
- ' Subprograms
- DECLARE SUB Interruptx (intnum%, inreg AS RegTypeX, outreg AS RegTypeX)
- DECLARE SUB FindFirstFile (path$, dta$, result%)
- DECLARE SUB FindNextFile (dta$, result%)
- DECLARE SUB GetFileData (dta$, file AS FileDataType)
- DECLARE SUB FileTreeSearch (path$, indent%)
-
- ' Create structure for deciphering the DTA file search results
- DIM file AS FileDataType
-
- ' Get the command line path for starting the file search
- path$ = COMMAND$
-
- ' If no path was given, then use "*.*" to search the current directory
- IF path$ = "" THEN
- path$ = "*.*"
- END IF
-
- ' If only a drive was given, then add "*.*"
- IF LEN(path$) = 2 AND RIGHT$(path$, 1) = ":" THEN
- path$ = path$ + "*.*"
- END IF
-
- ' Adjust the given path if necessary
- IF INSTR(path$, "*") = 0 AND INSTR(path$, "?") = 0 THEN
- FindFirstFile path$, dta$, result%
- IF result% = 0 OR RIGHT$(path$, 1) = "\" THEN
- IF RIGHT$(path$, 1) <> "\" THEN
- path$ = path$ + "\"
- END IF
- path$ = path$ + "*.*"
- END IF
- END IF
-
- ' Start with a clean slate
- CLS
-
- ' Call the recursive search subprogram
- FileTreeSearch path$, indent%
-
- ' That's all there is to it
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: FileTreeSearch
-
- Performs a recursive search for filenames in directories. Whenever a
- subdirectory is encountered, the subprogram builds a modified search path
- string (by adding the subdirectory name to the end of the current search
- path) and calls itself again. In this way, all files in all subdirectories
- are located, starting with the initial search path given.
-
- The filenames are printed with an indention amount that is a function of
- the level of recursion. This means that each subdirectory entry is
- indented four spaces more than its parent directory.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FileTreeSearch **
- ' ** Type: Subprogram **
- ' ** Module: QBTREE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Directory searching and listing subprogram for
- ' the QBTREE program. (recursive)
- '
- ' EXAMPLE OF USE: FileTreeSearch path$, indent%
- ' PARAMETERS: path$ Path for search of files
- ' indent% Level of indention, function of recursion
- ' level
- ' VARIABLES: file Structure of type FileDataType
- ' path$ Path for search of files
- ' dta$ Disk Transfer Area buffer string
- ' result% Returned result code from FindFirstFile or
- ' FindNextFile
- ' newPath$ Path with added subdirectory for recursive
- ' search
- ' MODULE LEVEL
- ' DECLARATIONS: TYPE FileDataType
- ' finame AS STRING * 12
- ' year AS INTEGER
- ' month AS INTEGER
- ' day AS INTEGER
- ' hour AS INTEGER
- ' minute AS INTEGER
- ' second AS INTEGER
- ' attribute AS INTEGER
- ' size AS LONG
- ' END TYPE
- '
- ' DECLARE SUB FindFirstFile (path$, dta$, result%)
- ' DECLARE SUB FindNextFile (dta$, result%)
- ' DECLARE SUB GetFileData (dta$, file AS FileDataType)
- ' DECLARE SUB FileTreeSearch (path$, indent%)
- '
- SUB FileTreeSearch (path$, indent%)
-
- ' Create structure for deciphering the DTA file search results
- DIM file AS FileDataType
-
- ' Find the first file given the current search path
- FindFirstFile path$, dta$, result%
-
- ' Search through the directory for all files
- DO UNTIL result%
-
- ' Unpack the Disk Transfer Area for file information
- GetFileData dta$, file
-
- ' Skip the "." and ".." files
- IF LEFT$(file.finame, 1) <> "." THEN
-
- ' Print the filename, indented to show tree structure
- PRINT SPACE$(indent% * 4); file.finame;
-
- ' Print any other desired file information here
- PRINT TAB(50); file.size;
- PRINT TAB(58); file.attribute
-
- ' If we found a directory, then recursively search through it
- IF file.attribute AND &H10 THEN
-
- ' Modify path$ to add this new directory to the search pa
- newPath$ = path$
- IF INSTR(newPath$, "\") = 0 THEN
- newPath$ = "\" + newPath$
- END IF
- DO WHILE RIGHT$(newPath$, 1) <> "\"
- newPath$ = LEFT$(newPath$, LEN(newPath$) - 1)
- LOOP
- newPath$ = newPath$ + file.finame + "\*.*"
-
- ' Example of recursion here
- FileTreeSearch newPath$, indent% + 1
-
- END IF
-
- END IF
-
- ' Try to find the next file in this directory
- FindNextFile dta$, result%
-
- LOOP
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- QCAL
-
- The QCAL program provides scientific calculator functions from the MS-DOS
- command line. This program is a modified and expanded version of
- MINICAL.BAS, presented earlier in this book. The original version's goal
- was to demonstrate the methods used to create a small, modular program.
- The functionality of the program wasn't the important issue. Here, the
- program has been enhanced, and several new functions and capabilities make
- this program more useful as a utility. Run the program by typing QCAL
- HELP, QCAL ?, or QCAL, and a list of the available functions will be
- displayed. In addition to the original five functions, several new
- trigonometric, hyperbolic, and logarithmic functions have been added.
-
- You might want to review the original MINICAL program, which is on pages
- 5 through 18. You'll find an explanation of how the numeric values are
- placed on the stack and how the functions operate on those values.
-
- Because of the modular, structured organization of QuickBASIC programs,
- you can easily modify this program to include other functions. To add a
- new function, modify the Process and QcalHelp subprograms where
- applicable, and follow the same pattern of stack and variable
- manipulations exhibited by the other routines when writing your own.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- QCAL.BAS Program module
- DisplayStack Sub Displays final results of the program
- NextParameter$ Func Extracts number or command from
- COMMAND$
- Process Sub Controls action for command line
- parameters
- QcalHelp Sub Provides a "Help" display for program
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: QCAL
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: QCAL **
- ' ** Type: Program **
- ' ** Module: QCAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: QCAL [number] [function] [...]
- ' .MAK FILE: QCAL.BAS
- ' QCALMATH.BAS
- ' PARAMETERS: [number] Numbers to be placed on the stack
- ' [function] Operations to be performed on the stack
- ' contents
- ' VARIABLES: cmd$ Working copy of COMMAND$
- ' stack#() Array representing the numeric stack
- ' ptr% Index into the stack
- ' parm$ Each number of command extracted from cm
-
- ' Constants
- CONST PI = 3.141592653589793#
-
- ' Functions
- DECLARE FUNCTION AbsoluteX# (x#)
- DECLARE FUNCTION Add# (y#, x#)
- DECLARE FUNCTION ArcCosine# (x#)
- DECLARE FUNCTION ArcHypCosine# (x#)
- DECLARE FUNCTION ArcHypSine# (x#)
- DECLARE FUNCTION ArcHypTangent# (x#)
- DECLARE FUNCTION ArcSine# (x#)
- DECLARE FUNCTION ArcTangent# (x#)
- DECLARE FUNCTION Ceil# (x#)
- DECLARE FUNCTION ChangeSign# (x#)
- DECLARE FUNCTION Cosine# (x#)
- DECLARE FUNCTION Divide# (y#, x#)
- DECLARE FUNCTION Exponential# (x#)
- DECLARE FUNCTION FractionalPart# (x#)
- DECLARE FUNCTION HypCosine# (x#)
- DECLARE FUNCTION HypSine# (x#)
- DECLARE FUNCTION HypTangent# (x#)
- DECLARE FUNCTION IntegerPart# (x#)
- DECLARE FUNCTION LogBase10# (x#)
- DECLARE FUNCTION LogBaseN# (y#, x#)
- DECLARE FUNCTION LogE# (x#)
- DECLARE FUNCTION Modulus# (y#, x#)
- DECLARE FUNCTION Multiply# (y#, x#)
- DECLARE FUNCTION NextParameter$ (cmd$)
- DECLARE FUNCTION OneOverX# (x#)
- DECLARE FUNCTION Sign# (x#)
- DECLARE FUNCTION Sine# (x#)
- DECLARE FUNCTION SquareRoot# (x#)
- DECLARE FUNCTION Subtract# (y#, x#)
- DECLARE FUNCTION Tangent# (x#)
- DECLARE FUNCTION Xsquared# (x#)
- DECLARE FUNCTION YRaisedToX# (y#, x#)
-
- ' Subprograms
- DECLARE SUB QcalHelp ()
- DECLARE SUB Process (parm$, stack#(), ptr%)
- DECLARE SUB DisplayStack (stack#(), ptr%)
- DECLARE SUB SwapXY (stack#(), ptr%)
-
- ' Get the command line
- cmd$ = COMMAND$
-
- ' First check if user is asking for help
- IF cmd$ = "" OR cmd$ = "HELP" OR cmd$ = "?" THEN
- QcalHelp
- SYSTEM
- END IF
-
- ' Create a pseudo stack
- DIM stack#(1 TO 20)
- ptr% = 0
-
- ' Process each part of the command line
- DO UNTIL cmd$ = ""
- parm$ = NextParameter$(cmd$)
- Process parm$, stack#(), ptr%
- IF ptr% < 1 THEN
- PRINT "Not enough stack values"
- SYSTEM
- END IF
- LOOP
-
- ' Display results
- DisplayStack stack#(), ptr%
-
- ' All done
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: DisplayStack
-
- Displays the final results of the QCAL program. When the QCAL program is
- finished, one or more numeric values are left on the stack, representing
- the final values of the calculations. If the stack has a single value
- remaining on it, this number is displayed with the label Result.... If,
- however, two or more values are left on the stack after QCAL has acted on
- all functions, the values are displayed with the label Stack ...,
- indicating to the user that more than a single result was left on the
- stack.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: DisplayStack **
- ' ** Type: Subprogram **
- ' ** Module: QCAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Displays the value(s) left on the stack when QCAL
- ' is finished processing the command line.
- '
- ' EXAMPLE OF USE: DisplayStack stack#(), ptr%
- ' PARAMETERS: stack#() Array of numbers representing the stack
- ' ptr% Index into the stack
- ' VARIABLES: i% Looping index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB DisplayStack (stack#(), ptr%)
- '
- SUB DisplayStack (stack#(), ptr%) STATIC
- PRINT
- IF ptr% > 1 THEN
- PRINT "Stack ... ",
- ELSE
- PRINT "Result... ",
- END IF
- FOR i% = 1 TO ptr%
- PRINT stack#(i%),
- NEXT i%
- PRINT
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: NextParameter$
-
- Returns the first group of nonspace characters found at the left of the
- passed string. The passed string is then trimmed of these characters,
- along with any extra spaces.
-
- The PARSE.BAS module contains alternative routines that perform the same
- function in a slightly different way. Take a look at the ParseWord and
- ParseLine routines found there. The NextParameter$ subprogram
- demonstrates how the code from a module can be copied and modified for a
- specific purpose, with any extra code removed. This results in a smaller
- program but has the disadvantage that any future changes to the
- PARSE.BAS module will probably not show up here in the QCAL.BAS module.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: NextParameter$ **
- ' ** Type: Function **
- ' ** Module: QCAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Extracts parameters from the front of the
- ' command line. Parameters are groups of any
- ' characters separated by spaces.
- '
- ' EXAMPLE OF USE: parm$ = NextParameter$(cmd$)
- ' PARAMETERS: cmd$ The working copy of COMMAND$
- ' VARIABLES: parm$ Each number or command from cmd$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION NextParameter$ (cmd$)
- '
- FUNCTION NextParameter$ (cmd$) STATIC
- parm$ = ""
- DO WHILE LEFT$(cmd$, 1) <> " " AND cmd$ <> ""
- parm$ = parm$ + LEFT$(cmd$, 1)
- cmd$ = MID$(cmd$, 2)
- LOOP
- DO WHILE LEFT$(cmd$, 1) = " " AND cmd$ <> ""
- cmd$ = MID$(cmd$, 2)
- LOOP
- NextParameter$ = parm$
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Process
-
- Acts upon each command line parameter. If the parameter is a valid
- function, the function is called, and the stack is adjusted appropriately.
- If the parameter isn't a recognizable function, it is assumed to be a
- numeric quantity. The VAL function converts the parameter to its numeric
- equivalent, and the result is pushed on the stack, ready for the next
- operation.
-
- This subprogram demonstrates a fairly long CASE statement. The same logic
- could be developed using IF THEN, ELSE IF, ELSE, and END IF statements,
- but the CASE statement is ideal for making selections from a large number
- of choices in this way.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Process **
- ' ** Type: Subprogram **
- ' ** Module: QCAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Processes each command parameter for the QCAL
- ' program.
- '
- ' EXAMPLE OF USE: Process parm$, stack#(), ptr%
- ' PARAMETERS: parm$ The command line parameter to be processed
- ' stack#() Array of numbers representing the stack
- ' ptr% Index pointing to last stack entry
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Process (parm$, stack#(), ptr%)
- '
- SUB Process (parm$, stack#(), ptr%) STATIC
- SELECT CASE parm$
- CASE "+"
- ptr% = ptr% - 1
- IF ptr% > 0 THEN
- stack#(ptr%) = Add#(stack#(ptr%), stack#(ptr% + 1))
- END IF
- CASE "-"
- ptr% = ptr% - 1
- IF ptr% > 0 THEN
- stack#(ptr%) = Subtract#(stack#(ptr%), stack#(ptr% + 1))
- END IF
- CASE "*"
- ptr% = ptr% - 1
- IF ptr% > 0 THEN
- stack#(ptr%) = Multiply#(stack#(ptr%), stack#(ptr% + 1))
- END IF
- CASE "/"
- ptr% = ptr% - 1
- IF ptr% > 0 THEN
- stack#(ptr%) = Divide#(stack#(ptr%), stack#(ptr% + 1))
- END IF
- CASE "CHS"
- IF ptr% > 0 THEN
- stack#(ptr%) = ChangeSign#(stack#(ptr%))
- END IF
- CASE "ABS"
- IF ptr% > 0 THEN
- stack#(ptr%) = AbsoluteX#(stack#(ptr%))
- END IF
- CASE "SGN"
- IF ptr% > 0 THEN
- stack#(ptr%) = Sign#(stack#(ptr%))
- END IF
- CASE "INT"
- IF ptr% > 0 THEN
- stack#(ptr%) = IntegerPart#(stack#(ptr%))
- END IF
- CASE "MOD"
- ptr% = ptr% - 1
- IF ptr% > 0 THEN
- stack#(ptr%) = Modulus#(stack#(ptr%), stack#(ptr% + 1))
- END IF
- CASE "FRC"
- IF ptr% > 0 THEN
- stack#(ptr%) = FractionalPart#(stack#(ptr%))
- END IF
- CASE "1/X"
- IF ptr% > 0 THEN
- stack#(ptr%) = OneOverX#(stack#(ptr%))
- END IF
- CASE "SQR"
- IF ptr% > 0 THEN
- stack#(ptr%) = SquareRoot#(stack#(ptr%))
- END IF
- CASE "X2"
- IF ptr% > 0 THEN
- stack#(ptr%) = Xsquared#(stack#(ptr%))
- END IF
- CASE "SIN"
- IF ptr% > 0 THEN
- stack#(ptr%) = Sine#(stack#(ptr%))
- END IF
- CASE "COS"
- IF ptr% > 0 THEN
- stack#(ptr%) = Cosine#(stack#(ptr%))
- END IF
- CASE "TAN"
- IF ptr% > 0 THEN
- stack#(ptr%) = Tangent#(stack#(ptr%))
- END IF
- CASE "ASN"
- IF ptr% > 0 THEN
- stack#(ptr%) = ArcSine#(stack#(ptr%))
- END IF
- CASE "ACS"
- IF ptr% > 0 THEN
- stack#(ptr%) = ArcCosine#(stack#(ptr%))
- END IF
- CASE "ATN"
- IF ptr% > 0 THEN
- stack#(ptr%) = ArcTangent#(stack#(ptr%))
- END IF
- CASE "HSN"
- IF ptr% > 0 THEN
- stack#(ptr%) = HypSine#(stack#(ptr%))
- END IF
- CASE "HCS"
- IF ptr% > 0 THEN
- stack#(ptr%) = HypCosine#(stack#(ptr%))
- END IF
- CASE "HTN"
- IF ptr% > 0 THEN
- stack#(ptr%) = HypTangent#(stack#(ptr%))
- END IF
- CASE "AHS"
- IF ptr% > 0 THEN
- stack#(ptr%) = ArcHypSine#(stack#(ptr%))
- END IF
- CASE "AHC"
- IF ptr% > 0 THEN
- stack#(ptr%) = ArcHypCosine#(stack#(ptr%))
- END IF
- CASE "AHT"
- IF ptr% > 0 THEN
- stack#(ptr%) = ArcHypTangent#(stack#(ptr%))
- END IF
- CASE "LOG"
- IF ptr% > 0 THEN
- stack#(ptr%) = LogE#(stack#(ptr%))
- END IF
- CASE "LOG10"
- IF ptr% > 0 THEN
- stack#(ptr%) = LogBase10#(stack#(ptr%))
- END IF
- CASE "LOGN"
- ptr% = ptr% - 1
- IF ptr% > 0 THEN
- stack#(ptr%) = LogBaseN#(stack#(ptr%), stack#(ptr% + 1))
- END IF
- CASE "EXP"
- IF ptr% > 0 THEN
- stack#(ptr%) = Exponential#(stack#(ptr%))
- END IF
- CASE "CEIL"
- IF ptr% > 0 THEN
- stack#(ptr%) = Ceil#(stack#(ptr%))
- END IF
- CASE "Y^X"
- ptr% = ptr% - 1
- IF ptr% > 0 THEN
- stack#(ptr%) = YRaisedToX#(stack#(ptr%), stack#(ptr% + 1))
- END IF
- CASE "PI"
- ptr% = ptr% + 1
- stack#(ptr%) = PI
- CASE "SWAP"
- SwapXY stack#(), ptr%
- CASE "DUP"
- IF ptr% > 0 THEN
- stack#(ptr% + 1) = stack#(ptr%)
- ptr% = ptr% + 1
- END IF
- CASE ELSE
- ptr% = ptr% + 1
- stack#(ptr%) = VAL(parm$)
- END SELECT
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: QcalHelp
-
- Provides a Help display for the QCAL program.
-
- One feature that sets good software apart from mediocre software is the
- ability to provide on-line help for the user. Nothing is more frustrating
- than a program that terminates suddenly, without any explanation of the
- problem or suggestion for solving it.
-
- The QcalHelp subprogram demonstrates one approach to helping the user with
- a program. Entering any of the following command lines will cause the QCAL
- program to call QcalHelp:
-
-
- QCAL HELP
- QCAL ?
- QCAL
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: QcalHelp **
- ' ** Type: Subprogram **
- ' ** Module: QCAL.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Displays a help screen when QCAL is run with no
- ' parameters or with a parameter of ? or HELP.
- '
- ' EXAMPLE OF USE: QcalHelp
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB QcalHelp ()
- '
- SUB QcalHelp STATIC
- PRINT
- PRINT "Usage: QCAL [number] [function] [...] <Enter>"
- PRINT
- PRINT "Numbers are placed on an RPN stack, and functions operate"
- PRINT "on the stacked quantities. When the program is finished,"
- PRINT "whatever is left on the stack is displayed."
- PRINT
- PRINT "List of available functions..."
- PRINT
- PRINT "Two numbers: + - * /"
- PRINT "One number: CHS ABS SGN INT MOD FRC CHS 1/X SQR X2 CEIL
- PRINT "Trigonometric: SIN COS TAN ASN ACS ATN"
- PRINT "Hyperbolic: HSN HCS HTN AHS AHC AHT"
- PRINT "Logarithmic: LOG LOG10 LOGN EXP Y^X"
- PRINT "Constants: PI"
- PRINT "Stack: SWAP DUP"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- QCALMATH
-
- QCALMATH is a toolbox of scientific functions for the QCAL program.
- Several functions included in QCALMATH are similar to functions provided
- by QuickBASIC. You could shorten QCALMATH by deleting these functions here
- and coding the QuickBASIC routines directly in the Process subprogram,
- located in the QCAL.BAS module. However, there's something to be said for
- keeping the functions as shown here: QCALMATH checks for additional error
- conditions and generates clear messages if errors exist. For example,
- although the SquareRoot# function duplicates a QuickBASIC function,
- SquareRoot# checks for values less than 0 before trying to find the
- square root and prints a clear message if such an attempt is made.
-
- It's easy to add your own functions to the QCAL program. Simply create
- the function in the same format and style as shown in this module. You'll
- also need to modify the Process subprogram in the QCAL module to let the
- program call the new function. For the final touch, be sure to add the new
- function to the list displayed by the QcalHelp subprogram.
-
- QCALMATH is the only toolbox in this book that doesn't have any
- module-level code to demonstrate the subprograms and functions. The QCAL
- program loads this toolbox and provides the demonstration code.
-
- ╓┌─┌─────────────────────────────┌──────┌────────────────────────────────────╖
- Name Type Description
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- QCALMATH.BAS Toolbox
- AbsoluteX# Func Absolute value of a number
- Add# Func Sum of two numbers
- ArcCosine# Func Arc cosine function of a number
- ArcHypCosine# Func Inverse hyperbolic cosine of a number
- ArcHypSine# Func Inverse hyperbolic sine of a number
- ArcHypTangent# Func Inverse hyperbolic tangent of a
- number
- ArcSine# Func Inverse sine of a number
- ArcTangent# Func Inverse tangent of a number
- Ceil# Func Smallest whole number greater than a
- number
- ChangeSign# Func Reverses sign of a number
- Cosine# Func Cosine of a number
- Divide# Func Result of dividing two numbers
- Dup Sub Duplicates top entry on the stack
- Exponential# Func Exponential function of a number
- FractionalPart# Func Fractional part of a number
- HypCosine# Func Hyperbolic cosine of a number
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- HypCosine# Func Hyperbolic cosine of a number
- HypSine# Func Hyperbolic sine of a number
- HypTangent# Func Hyperbolic tangent of a number
- IntegerPart# Func Integer part of a number
- LogBase10# Func Log base 10 of a number
- LogBaseN# Func Log base N of a number
- LogE# Func Natural logarithm of a number
- Modulus# Func Remainder of the division of two
- numbers
- Multiply# Func Product of two numbers
- OneOverX# Func Result of dividing 1 by a number
- Sign# Func Sign of a number
- Sine# Func Sine of a number
- SquareRoot# Func Square root of a number
- Subtract# Func Difference between two numbers
- SwapXY Sub Swaps top two entries on the stack
- Tangent# Func Tangent of a number
- Xsquared# Func Square of a number
- YRaisedToX# Func Number raised to the power of a
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- YRaisedToX# Func Number raised to the power of a
- second
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- Toolbox: QCALMATH
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: QCALMATH **
- ' ** Type: Toolbox **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Collection of math functions and subprograms for
- ' the QCAL program.
- '
- ' USAGE: (loaded by the QCAL program)
- '.MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' Constants
- CONST PI = 3.141592653589793#
- CONST L10 = 2.302585092994046#
-
- ' Functions
- DECLARE FUNCTION AbsoluteX# (x#)
- DECLARE FUNCTION Add# (y#, x#)
- DECLARE FUNCTION ArcCosine# (x#)
- DECLARE FUNCTION ArcHypCosine# (x#)
- DECLARE FUNCTION ArcHypSine# (x#)
- DECLARE FUNCTION ArcHypTangent# (x#)
- DECLARE FUNCTION ArcSine# (x#)
- DECLARE FUNCTION ArcTangent# (x#)
- DECLARE FUNCTION Ceil# (x#)
- DECLARE FUNCTION ChangeSign# (x#)
- DECLARE FUNCTION Cosine# (x#)
- DECLARE FUNCTION Divide# (y#, x#)
- DECLARE FUNCTION Exponential# (x#)
- DECLARE FUNCTION FractionalPart# (x#)
- DECLARE FUNCTION HypCosine# (x#)
- DECLARE FUNCTION HypSine# (x#)
- DECLARE FUNCTION HypTangent# (x#)
- DECLARE FUNCTION IntegerPart# (x#)
- DECLARE FUNCTION LogBase10# (x#)
- DECLARE FUNCTION LogBaseN# (y#, x#)
- DECLARE FUNCTION LogE# (x#)
- DECLARE FUNCTION Modulus# (y#, x#)
- DECLARE FUNCTION Multiply# (y#, x#)
- DECLARE FUNCTION OneOverX# (x#)
- DECLARE FUNCTION Sign# (x#)
- DECLARE FUNCTION Sine# (x#)
- DECLARE FUNCTION SquareRoot# (x#)
- DECLARE FUNCTION Subtract# (y#, x#)
- DECLARE FUNCTION Tangent# (x#)
- DECLARE FUNCTION Xsquared# (x#)
- DECLARE FUNCTION YRaisedToX# (y#, x#)
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: AbsoluteX#
-
- Returns the absolute value of the passed value. The absolute value of a
- number is that number's positive value.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: AbsoluteX# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = AbsoluteX#(x#)
- ' PARAMETERS: x# Double-precision value to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION AbsoluteX# (x#)
- '
- FUNCTION AbsoluteX# (x#) STATIC
- AbsoluteX# = ABS(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Add#
-
- Returns the sum of two double-precision numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Add# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: z# = Add#(y#, x#)
- ' PARAMETERS: y# First number
- ' x# Second number
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Add# (y#, x#)
- '
- FUNCTION Add# (y#, x#) STATIC
- Add# = y# + x#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ArcCosine#
-
- Returns the arc cosine of a number; the returned angle is expressed in
- radians. If the number passed is less than 1, an error message is
- displayed, and the program terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ArcCosine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = ArcCosine#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ArcCosine# (x#)
- '
- FUNCTION ArcCosine# (x#) STATIC
- x2# = x# * x#
- IF x2# < 1# THEN
- ArcCosine# = PI / 2# - ATN(x# / SQR(1# - x# * x#))
- ELSE
- PRINT "Error: ACS(x#) where x# < 1"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ArcHypCosine#
-
- Returns the inverse hyperbolic cosine of a number. If the number passed is
- less than or equal to 1, an error message is displayed, and the program
- terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ArcHypCosine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = ArcHypCosine#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ArcHypCosine# (x#)
- '
- FUNCTION ArcHypCosine# (x#) STATIC
- IF ABS(x#) > 1# THEN
- ArcHypCosine# = LOG(x# + SQR(x# * x# - 1#))
- ELSE
- PRINT "Error: AHS(x#) where -1 <= x# <= +1"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ArcHypSine#
-
- Returns the inverse hyperbolic sine of a number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ArcHypSine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = ArcHypSine#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION AryHypSine# (x#)
- '
- FUNCTION ArcHypSine# (x#) STATIC
- ArcHypSine# = LOG(x# + SQR(1# + x# * x#))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ArcHypTangent#
-
- Returns the inverse hyperbolic tangent of a number. If the number passed
- is less than -1 or greater than 1, an error message is displayed, and the
- program terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ArcHypTangent# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = ArcHypTangent#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ArcHypTangent# (x#)
- '
- FUNCTION ArcHypTangent# (x#) STATIC
- IF ABS(x#) < 1 THEN
- ArcHypTangent# = LOG((1# + x#) / (1# - x#)) / 2#
- ELSE
- PRINT "Error: AHT(x#) where x# <= -1 or x# >= +1"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ArcSine#
-
- Returns the inverse sine of a number. If the number passed is greater than
- or equal to 1, the function displays an error message, and the program
- terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ArcSine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = ArcSine#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ArcSine# (x#)
- '
- FUNCTION ArcSine# (x#) STATIC
- x2# = x# * x#
- IF x2# < 1# THEN
- ArcSine# = ATN(x# / SQR(1# - x# * x#))
- ELSE
- PRINT "Error: ASN(x#) where x# >= 1"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ArcTangent#
-
- Returns the inverse tangent of a number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ArcTangent# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = ArcTangent#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ArcTangent# (x#)
- '
- FUNCTION ArcTangent# (x#) STATIC
- ArcTangent# = ATN(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Ceil#
-
- Returns the smallest whole number that is greater than a number. For
- example, Ceil#(3.14) returns 4, Ceil#(-3.14) returns -3, and Ceil#(17)
- returns 17.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Ceil# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Ceil#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Ceil# (x#)
- '
- FUNCTION Ceil# (x#) STATIC
- Ceil# = -INT(-x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ChangeSign#
-
- Returns a number with its sign changed. This function could easily be
- deleted from QCAL by changing the Process subprogram so that it directly
- performs negation in the CASE statement in which the CHS command is acted
- upon. I decided to provide a consistent interface between the functions in
- the QCALMATH module and the Process subprogram, however, making it
- easier to add, delete, or modify functions as desired.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ChangeSign# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = ChangeSign#(x#)
- ' PARAMETERS: x# Number to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ChangeSign# (x#)
- '
- FUNCTION ChangeSign# (x#) STATIC
- ChangeSign# = -x#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Cosine#
-
- Returns the cosine of an angle.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Cosine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Cosine#(x#)
- ' PARAMETERS: x# Angle to be evaluated
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Cosine# (x#)
- '
- FUNCTION Cosine# (x#) STATIC
- Cosine# = COS(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Divide#
-
- Returns the result of dividing two numbers. If a division by 0 is
- attempted, the function displays an error message, and the program
- terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Divide# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Divide#(y#, x#)
- ' PARAMETERS: y# Number to be processed
- ' x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Divide# (y#, x#)
- '
- FUNCTION Divide# (y#, x#) STATIC
- IF x# <> 0 THEN
- Divide# = y# / x#
- ELSE
- PRINT "Error: Division by zero"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Dup
-
- Duplicates the top entry on the stack for the QCAL program.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Dup **
- ' ** Type: Subprogram **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: Dup stack#(), ptr%
- ' PARAMETERS: stack#() Numeric stack
- ' ptr% Index to last entry on stack
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Dup (Stack#(), ptr%)
- '
- SUB Dup (stack#(), ptr%) STATIC
- IF ptr% THEN
- ptr% = ptr% + 1
- stack#(ptr%) = stack#(ptr% - 1)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Exponential#
-
- Returns the exponential function of a number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Exponential# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Exponential#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Exponential# (x#)
- '
- FUNCTION Exponential# (x#) STATIC
- Exponential# = EXP(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: FractionalPart#
-
- Returns the fractional part of a number. For example, the fractional part
- of 3.14 is .14, of -3.14 is -.14, and of 17 is 0.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FractionalPart# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = FractionalPart#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION FractionalPart# (x#)
- '
- FUNCTION FractionalPart# (x#) STATIC
- IF x# >= 0 THEN
- FractionalPart# = x# - INT(x#)
- ELSE
- FractionalPart# = x# - INT(x#) - 1#
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: HypCosine#
-
- Returns the hyperbolic cosine of a number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: HypCosine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = HypCosine#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION HypCosine# (x#)
- '
- FUNCTION HypCosine# (x#) STATIC
- HypCosine# = (EXP(x#) + EXP(-x#)) / 2#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: HypSine#
-
- Returns the hyperbolic sine of a number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: HypSine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = HypSine#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION HypSine# (x#)
- '
- FUNCTION HypSine# (x#) STATIC
- HypSine# = (EXP(x#) - EXP(-x#)) / 2#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: HypTangent#
-
- Returns the hyperbolic tangent of a number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: HypTangent# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = HypTangent#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION HypTangent# (x#)
- '
- FUNCTION HypTangent# (x#) STATIC
- HypTangent# = (EXP(x#) - EXP(-x#)) / (EXP(x#) + EXP(-x#))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IntegerPart#
-
- Returns the integer part of a number. For example, the integer part of
- 3.14 is 3, of -3.14 is -4, and of 17 is 17.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: IntegerPart# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = IntegerPart#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION IntegerPart# (x#)
- '
- FUNCTION IntegerPart# (x#) STATIC
- IntegerPart# = INT(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: LogBase10#
-
- Returns the logarithm, base 10, of a number. If the number is not greater
- than 0, the function displays an error message, and the program
- terminates.
-
- Look in the listing at the constant L10, defined in the module-level code
- of QCALMATH. This constant is the double-precision natural logarithm of
- 10. The constant can be replaced with LOG(10), its mathematic equivalent,
- but using a constant makes the program faster and the compiled program
- shorter.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: LogBase10# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Log10#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION LogBase10# (x#)
- '
- FUNCTION LogBase10# (x#) STATIC
- IF x# > 0 THEN
- LogBase10# = LOG(x#) / L10
- ELSE
- PRINT "Error: LOG10(x#) where x# <= 0"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: LogBaseN#
-
- Returns the logarithm, base N, of a number. This function checks for
- several possible error conditions. The number to be processed must be
- greater than 0, and the base for finding the logarithm must be greater
- than 0 and must not be exactly 1. If one of these checks fails, a message
- is displayed, and the program terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: LogBaseN# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = LogBaseN#(y#, x#)
- ' PARAMETERS: y# Number to be processed
- ' x# The base for finding the logarithm
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION LogBaseN# (y#, x#)
- '
- FUNCTION LogBaseN# (y#, x#) STATIC
- IF x# <= 0 THEN
- PRINT "Error: LOGN(y#, x#) where x# <= 0"
- SYSTEM
- ELSEIF x# = 1# THEN
- PRINT "Error: LOGN(y#, x#) where x# = 1"
- SYSTEM
- ELSEIF y# <= 0 THEN
- PRINT "Error: LOGN(y#, x#) where y# is <= 0"
- SYSTEM
- ELSE
- LogBaseN# = LOG(y#) / LOG(x#)
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: LogE#
-
- Returns the natural logarithm of a number. The QuickBASIC function LOG()
- is used to calculate the logarithm, but this function first checks that
- the number is greater than 0. If the number is equal to or less than 0, an
- error message is displayed, and the program terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: LogE# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = LogE#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION LogE# (x#)
- '
- FUNCTION LogE# (x#) STATIC
- IF x# > 0 THEN
- LogE# = LOG(x#)
- ELSE
- PRINT "Error: LOGE(x#) where x# <= 0"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Modulus#
-
- Returns the remainder of the division of two numbers. If a division by 0
- is attempted, the function displays an error message, and the program
- terminates. The function is valid for non-integer quantities.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Modulus# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Modulus#(y#, x#)
- ' PARAMETERS: y# Number to be divided
- ' x# Number for dividing by
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Modulus# (y#, x#)
- '
- FUNCTION Modulus# (y#, x#) STATIC
- IF x# <> 0 THEN
- Modulus# = y# - INT(y# / x#) * x#
- ELSE
- PRINT "Error: MOD(y#, x#) where x# = 0"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Multiply#
-
- Returns the product of two numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Multiply# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Multiply#(y#, x#)
- ' PARAMETERS: y# First number to be processed
- ' x# Second number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Multiply# (y#, x#)
- '
- FUNCTION Multiply# (y#, x#) STATIC
- Multiply# = y# * x#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: OneOverX#
-
- Returns the result of dividing 1 by a number. If a division by 0 is
- attempted, the function displays an error message, and the program
- terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: OneOverX# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = OneOverX#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION OneOverX# (x#)
- '
- FUNCTION OneOverX# (x#) STATIC
- IF x# <> 0 THEN
- OneOverX# = 1# / x#
- ELSE
- PRINT "Error: 1/x where x = 0"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Sign#
-
- Returns -1 for all negative numbers, 1 for positive numbers, and 0 for
- zero.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Sign# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Sign#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Sign# (x#)
- '
- FUNCTION Sign# (x#) STATIC
- Sign# = SGN(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Sine#
-
- Returns the sine of an angle; assumes the angle is expressed in radians.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Sine# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Sine#(x#)
- ' PARAMETERS: x# Angle, expressed in radians
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Sine# (x#)
- '
- FUNCTION Sine# (x#) STATIC
- Sine# = SIN(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: SquareRoot#
-
- Returns the square root of a number. Before the QuickBASIC SQR function is
- used to actually find the square root, the number is checked to be sure it
- isn't negative. If it is, an error message is displayed, and the program
- terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SquareRoot# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = SquareRoot#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION SquareRoot# (x#)
- '
- FUNCTION SquareRoot# (x#) STATIC
- IF x# >= 0 THEN
- SquareRoot# = SQR(x#)
- ELSE
- PRINT "Error: SQR(x#) where x# < 0"
- SYSTEM
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Subtract#
-
- Returns the difference of two numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Subtract# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Subtract#(y#, x#)
- ' PARAMETERS: y# Number to be processed
- ' x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Subtract# (y#, x#)
- '
- FUNCTION Subtract# (y#, x#) STATIC
- Subtract# = y# - x#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: SwapXY
-
- Swaps the top two entries on the stack.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: SwapXY **
- ' ** Type: Subprogram **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: SwapXY stack#(), ptr%
- ' PARAMETERS: stack#() Numeric stack
- ' ptr% Pointer to top of stack
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB SwapXY (stack#(), ptr%
- '
- SUB SwapXY (stack#(), ptr%) STATIC
- IF ptr% > 1 THEN
- SWAP stack#(ptr%), stack#(ptr% - 1)
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Tangent#
-
- Returns the tangent of an angle; assumes the angle is in radians.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Tangent# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Tangent#(x#)
- ' PARAMETERS: x# Angle, expressed in radians
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Tangent# (x#)
- '
- FUNCTION Tangent# (x#) STATIC
- Tangent# = TAN(x#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Xsquared#
-
- Returns the square of a number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Xsquared# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: y# = Xsquared#(x#)
- ' PARAMETERS: x# Number to be processed
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Xsquared# (x#)
- '
- FUNCTION Xsquared# (x#) STATIC
- Xsquared# = x# * x#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: YRaisedToX#
-
- Returns a number raised to the power of a second number.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: YRaisedToX# **
- ' ** Type: Function **
- ' ** Module: QCALMATH.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' EXAMPLE OF USE: z# = YRaisedToX#(y#, x#)
- ' PARAMETERS: y# Number to be raised to a power
- ' x# Power to raise the other number to
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION YRaisedToX# (y#, x#)
- '
- FUNCTION YRaisedToX# (y#, x#) STATIC
- YRaisedToX# = y# ^ x#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- RANDOMS
-
- The RANDOMS toolbox provides a collection of random number generators.
-
- At the heart of these routines are two techniques, which are described in
- The Art of Computer Programming, Vol. 2, Seminumerical Algorithms, by
- Donald Knuth and which are combined to form the method in the Rand&
- function. The Rand& function returns pseudorandom integers in the range 0
- through 999999999. No multiplication or division is used, the algorithm is
- easily translated to any language that supports 32-bit integers, and all
- digits in the returned numbers are equally random. A table-shuffling
- technique further increases the randomness of the sequence.
-
- Several other functions use the random long integers returned by the
- Rand& function to create other random number distributions. For example,
- the RandReal!(x!, y!) function returns random real numbers in the range x!
- through y!. One common example of this function, RandReal!(0!, 1!),
- returns a pseudorandom, single-precision, floating-point value in the
- range 0 through 1.
-
- The RandShuffle subprogram and the RandInteger% function are used by
- CIPHER to generate a repeatable but secure sequence of random byte values
- in the range 0 through 255. See the CIPHER program for more information
- on using this file-ciphering technique.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- RANDOMS.BAS Demo module
- Rand& Func Long integers
- RandExponential! Func Real value with exponential
- distribution from mean
- RandFrac! Func Single-precision positive value < 1.0
- RandInteger% Func Integers within desired range
- RandNormal! Func Single-precision value from mean
- and standard deviation
- RandReal! Func Single-precision value in desired
- range
- RandShuffle Sub Initializes random number generator
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: RANDOMS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RANDOMS **
- ' ** Type: Toolbox **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: i% Loop index for generating pseudorandom numbers
-
- DECLARE FUNCTION Rand& ()
- DECLARE FUNCTION RandExponential! (mean!)
- DECLARE FUNCTION RandFrac! ()
- DECLARE FUNCTION RandInteger% (a%, b%)
- DECLARE FUNCTION RandNormal! (mean!, stddev!)
- DECLARE FUNCTION RandReal! (x!, y!)
-
- DECLARE SUB RandShuffle (key$)
-
- ' Array of long integers for generating all randoms
- DIM SHARED r&(1 TO 100)
-
- ' Clear the screen
- CLS
-
- ' Shuffle the random number generator, creating a
- ' unique sequence for every possible second
- RandShuffle DATE$ + TIME$
-
- PRINT "Rand&"
- FOR i% = 1 TO 5
- PRINT Rand&,
- NEXT i%
- PRINT
-
- PRINT "RandInteger%(0, 9)"
- FOR i% = 1 TO 5
- PRINT RandInteger%(0, 9),
- NEXT i%
- PRINT
-
- PRINT "RandReal!(-10!, 10!)"
- FOR i% = 1 TO 5
- PRINT RandReal!(-10!, 10!),
- NEXT i%
- PRINT
-
- PRINT "RandExponential!(100!)"
- FOR i% = 1 TO 5
- PRINT RandExponential!(100!),
- NEXT i%
- PRINT
-
- PRINT "RandNormal!(100!, 10!)"
- FOR i% = 1 TO 5
- PRINT RandNormal!(100!, 10!),
- NEXT i%
- PRINT
-
- PRINT "RandFrac!"
- FOR i% = 1 TO 5
- PRINT RandFrac!,
- NEXT i%
- PRINT
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Rand&
-
- Returns a pseudorandom long integer in the range 0 through 999999999,
- inclusive. Using the Rand& function provides you several advantages: It is
- fast because a minimal number of mathematical manipulations are performed;
- the sequence length is long, much greater than 2^55; and all digits in the
- returned random integer are equally random.
-
- The array of long integers, r&(1 TO 100), is shared by this function and
- the RandShuffle subprogram. This array contains a table of 55 random
- integers, a table of 42 values for shuffling the order of the random
- numbers upon output, two index pointers into the first 55 values, and the
- last generated random integer.
-
- You must call the RandShuffle subprogram once before you use the Rand&
- function. This initializes the tables and presets the two index numbers
- used to access table entries. If you don't call RandShuffle
-
- first, the Rand& function stops, you receive a Subscript out of range
- error message, and the program halts.
-
- Here's how Rand& works. The index numbers stored in r&(98) and r&(99) are
- always in the range 1 through 55 and are used to access two numbers stored
- in the first 55 entries of r&(). The first of these values is subtracted
- from the second, and if the result is less than zero, 1000000000 is added
- to bring the result somewhere into the range 0 through 999999999. This
- result replaces the number at the first location accessed. Finally, the
- two index numbers are decremented by 1, adjusted if necessary so that they
- remain in the range 1 through 55, and stored back in r&(98) and r&(99) for
- the next call to this routine.
-
- This table subtraction algorithm results in a good-quality random long
- integer, but an additional technique is used within Rand& to generate a
- significantly more random sequence of numbers. The generated number is
- used to point to one of the 42 entries in the locations r&(56) through
- r&(97). The previously generated number stored at that location is
- extracted, saved in r&(100), and replaced with the number just generated.
- Finally, the value saved in r&(100) is returned as the result. This
- randomly shuffles the order of the output values and effectively
- obliterates any subtle patterns that the sequence might have.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Rand& **
- ' ** Type: Function **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a pseudorandom long integer in the range
- ' 0 through 999999999.
- '
- ' EXAMPLE OF USE: n& = Rand&
- ' PARAMETERS: (none)
- ' VARIABLES: i% First index into random number table
- ' j% Second index into random number table
- ' t& Working variable
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Rand& ()
- ' DIM SHARED r&(1 TO 100)
- '
- FUNCTION Rand& STATIC
-
- ' Get the pointers into the table
- i% = r&(98)
- j% = r&(99)
-
- ' Subtract the two table values
- t& = r&(i%) - r&(j%)
-
- ' Adjust result if less than zero
- IF t& < 0 THEN
- t& = t& + 1000000000
- END IF
-
- ' Replace table entry with new random number
- r&(i%) = t&
-
- ' Decrement first index, keeping in range 1 through 55
- IF i% > 1 THEN
- r&(98) = i% - 1
- ELSE
- r&(98) = 55
- END IF
-
- ' Decrement second index, keeping in range 1 through 55
- IF j% > 1 THEN
- r&(99) = j% - 1
- ELSE
- r&(99) = 55
- END IF
-
- ' Use last random number to index into shuffle table
- i% = r&(100) MOD 42 + 56
-
- ' Grab random from table as current random number
- r&(100) = r&(i%)
-
- ' Put new calculated random into table
- r&(i%) = t&
-
- ' Return the random number grabbed from the table
- Rand& = r&(100)
-
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: RandExponential!
-
- Returns a pseudorandom real value with an exponential distribution, which
- is defined by the passed value of the mean.
-
- Be sure to call the RandShuffle subprogram before using this function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RandExponential! **
- ' ** Type: Function **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns an exponentially distributed pseudorandom,
- ' single-precision number given the mean of the
- ' distribution.
- '
- ' EXAMPLE OF USE: x! = RandExponential!(mean!)
- ' PARAMETERS: mean! The mean of the exponential distribution
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION RandExponential! (mean!)
- '
- FUNCTION RandExponential! (mean!) STATIC
- RandExponential! = -mean! * LOG(RandFrac!)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: RandFrac!
-
- Returns a pseudorandom real value in the range 0 through 1. This function
- is similar to the QuickBASIC function RND, but has a much longer sequence
- and a more random distribution.
-
- Be sure to call the RandShuffle subprogram before using this function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RandFrac! **
- ' ** Type: Function **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a pseudorandom, single-precision number
- ' in the range 0 through 1.
- '
- ' EXAMPLE OF USE: x! = RandFrac!
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION RandFrac! ()
- '
- FUNCTION RandFrac! STATIC
- RandFrac! = Rand& / 1E+09
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: RandInteger%
-
- Returns a pseudorandom integer in the range a% through b%, inclusive. For
- example, RandInteger%(0, 9) returns a random digit from 0 through 9.
-
- The passed value of a% must be less than b%; if it is not, this function
- generates incorrect random numbers. These parameters must be in the legal
- range of 16-bit signed integers, not less than -32768 nor greater than
- 32767.
-
- Be sure to call the RandShuffle subprogram before using this function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RandInteger% **
- ' ** Type: Function **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a pseudorandom integer in the range
- ' a% to b% inclusive.
- '
- ' EXAMPLE OF USE: n% = RandInteger%(a%, b%)
- ' PARAMETERS: a% Minimum value for returned integer
- ' b% Maximum value for returned integer
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION RandInteger% (a%, b%)
- '
- FUNCTION RandInteger% (a%, b%) STATIC
- RandInteger% = a% + (Rand& MOD (b% - a% + 1))
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: RandNormal!
-
- Returns pseudorandom real values with a normal distribution, which is
- defined by the passed mean and standard deviation.
-
- Be sure to call the RandShuffle subprogram before using this function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RandNormal! **
- ' ** Type: Function **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a normally distributed single-precision,
- ' pseudorandom number given the mean and standard deviation.
- '
- ' EXAMPLE OF USE: x! = RandNormal!(mean!, stddev!)
- ' PARAMETERS: mean! Mean of the distribution of returned
- ' values
- ' stddev! Standard deviation of the distribution
- ' VARIABLES: u1! Pseudorandom positive real value
- ' less than 1
- ' u2! Pseudorandom positive real value
- ' less than 1
- ' x! Working value
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION RandNormal! (mean!, stddev!)
- '
- FUNCTION RandNormal! (mean!, stddev!) STATIC
- u1! = RandFrac!
- u2! = RandFrac!
- x! = SQR(-2! * LOG(u1!)) * COS(6.283185 * u2)
- RandNormal! = mean! + stddev! * x!
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: RandReal!
-
- Returns a pseudorandom real value in the range x! through y! For example,
- RandReal!(-10!, 10!) returns a floating-point, single-precision value in
- the range -10 through +10.
-
- Be sure to call the RandShuffle subprogram before using this function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RandReal! **
- ' ** Type: Function **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a pseudorandom, single-precision real
- ' number in the range x! to y!.
- ' EXAMPLE OF USE: z! = RandReal!(x!, y!)
- ' PARAMETERS: x! Minimum for returned value
- ' y! Maximum for returned value
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION RandReal! (x!, y!)
- '
- FUNCTION RandReal! (x!, y!) STATIC
- RandReal! = x! + (y! - x!) * (Rand& / 1E+09)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: RandShuffle
-
- Initializes the sequence of random numbers that the Rand& function
- returns. The r&() array contains all the values necessary for the Rand&
- function. This subprogram initializes all values in r&() based on the
- characters passed in key$. Refer to the Rand& function for a description
- of the contents of the shared array r&().
-
- The passed string key$ is first modified to a length of 97 characters.
- Notice that an arbitrary string (in this subprogram, Abra Ca Da Bra) is
- concatenated to the front end of key$. Any string can be used, but at
- least one character must have an odd byte number. This guarantees that at
- least one initial table entry will be odd, a necessity of this
- random-number-generation algorithm.
-
- Each character of the new key string (k$) is used to generate a
- pseudorandom long integer to be entered in the first 97 entries of r&().
- To "warm up" the sequence, 997 iterations of the Rand& algorithm, slightly
- modified, are performed on the table.
-
- Finally, starting values for the index values necessary for the Rand&
- function are stored in r&(98) and r&(99), and an initial value for the
- last generated number is stored in r&(100).
-
- All the other random number generators in this toolbox call the Rand&
- function, which generates an error and quits if RandShuffle isn't run
- first to initialize r&(). Therefore, you must be sure to call RandShuffle
- once during a program run before calling any of these functions.
-
- To generate the same sequence every time the program is run, pass the same
- key$ each time. To generate a unique sequence each time, pass a unique
- string. For example, to generate a unique sequence for every clock tick of
- your computer's existence, you could enter RandShuffle(DATE$ + TIME$ +
- STR$(TIMER)).
-
- The key$ can be any reasonable length, but only the first 83 characters
- are used to seed the generator. Because there are 256 possible characters
- for each of the 83, there are 256^83 possible unique sequences. It's safe
- to say you'll never run out!
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RandShuffle **
- ' ** Type: Subprogram **
- ' ** Module: RANDOMS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Creates original table of pseudorandom long integers
- ' for use by the function Rand&. The contents of key$
- ' are used to seed the table.
- '
- ' EXAMPLE OF USE: RandShuffle(key$)
- ' PARAMETERS: key$ String used to seed the generator
- ' r&(1 TO 100) (shared) Array of long integers for
- ' generating pseudorandom numbers
- ' VARIABLES: k$ Modified key string
- ' i% Index into k$, index into table
- ' j% Index into table
- ' k% Loop count for warming up generator
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB RandShuffle (key$)
- '
- SUB RandShuffle (key$) STATIC
-
- ' Form 97-character string, with key$ as part of it
- k$ = LEFT$("Abra Ca Da Bra" + key$ + SPACE$(83), 97)
-
- ' Use each character to seed table
- FOR i% = 1 TO 97
- r&(i%) = ASC(MID$(k$, i%, 1)) * 8171717 + i% * 997&
- NEXT i%
-
- ' Preserve string space
- k$ = ""
-
- ' Initialize pointers into table
- i% = 97
- j% = 12
-
- ' Randomize the table to get it warmed up
- FOR k% = 1 TO 997
-
- ' Subtract entries pointed to by i% and j%
- r&(i%) = r&(i%) - r&(j%)
-
- ' Adjust result if less than zero
- IF r&(i%) < 0 THEN
- r&(i%) = r&(i%) + 1000000000
- END IF
-
- ' Decrement first index, keeping in range of 1 through 97
- IF i% > 1 THEN
- i% = i% - 1
- ELSE
- i% = 97
- END IF
-
- ' Decrement second index, keeping in range of 1 through 97
- IF j% > 1 THEN
- j% = j% - 1
- ELSE
- j% = 97
- END IF
-
- NEXT k%
-
- ' Initialize pointers for use by Rand& function
- r&(98) = 55
- r&(99) = 24
-
- ' Initialize pointer for shuffle table lookup by Rand& function
- r&(100) = 77
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- STDOUT
-
- The STDOUT toolbox is a collection of subprograms for outputting
- characters through the MS-DOS standard output channel rather than through
- the QuickBASIC PRINT statement.
-
- QuickBASIC bypasses the ANSI.SYS driver. However, some nice features are
- built into this driver, and this toolbox lets you access them from
- QuickBASIC. For example, the AssignKey subprogram lets you redefine keys
- on the keyboard to any character or string of characters you want.
-
- Be sure you load the ANSI.SYS driver before trying this program. Several
- of the escape code sequences create meaningless output if the ANSI.SYS
- driver is not resident. In most cases, a statement similar to the
- following in your CONFIG.SYS file will load the ANSI.SYS driver at boot-up
- time:
-
-
- DEVICE = \DOS\ANSI.SYS
-
- When you run the STDOUT demo module, pay close attention to the prompts
- that appear. In one case you are prompted to press the "a" and "b" keys,
- immediately before the program exits to MS-DOS via the SHELL statement. Be
- sure you press "a" and then "b" to prevent the program from getting lost.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- STDOUT.BAS Demo module
- AssignKey Sub Reassigns a string to a key
- Attribute Sub Sets screen color (ANSI driver
- definition)
- ClearLine Sub Clears current line from cursor to end of
- line
- ClearScreen Sub Clears screen
- CrLf Sub Sends carriage return and line feed
- CursorDown Sub Moves cursor down specified number of
- lines
- CursorHome Sub Moves cursor to upper left corner of
- screen
- CursorLeft Sub Moves cursor left specified number of
- spaces
- CursorPosition Sub Moves cursor to specified row and column
- CursorRight Sub Moves cursor right specified number of
- spaces
- CursorUp Sub Moves cursor up specified number of lines
- StdOut Sub Sends a string to standard output channel
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: STDOUT
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: STDOUT **
- ' ** Type: Toolbox **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: MIXED.QLB/.LIB
- ' ANSI.SYS
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: t0 Timer variable
- ' bell$ ASCII character 7 (bell)
-
- ' Attribute definitions
- CONST NORMAL = 0
- CONST BRIGHT = 1
- CONST UNDERSCORE = 4
- CONST BLINK = 5
- CONST REVERSE = 7
- CONST INVISIBLE = 8
- CONST BLACKFOREGROUND = 30
- CONST REDFOREGROUND = 31
- CONST GREENFOREGROUND = 32
- CONST YELLOWFOREGROUND = 33
- CONST BLUEFOREGROUND = 34
- CONST MAGENTAFOREGROUND = 35
- CONST CYANFOREGROUND = 36
- CONST WHITEFOREGROUND = 37
- CONST BLACKBACKGROUND = 40
- CONST REDBACKGROUND = 41
- CONST GREENBACKGROUND = 42
- CONST YELLOWBACKGROUND = 43
- CONST BLUEBACKGROUND = 44
- CONST MAGENTABACKGROUND = 45
- CONST CYANBACKGROUND = 46
- CONST WHITEBACKGROUND = 47
-
- TYPE RegTypeX
- ax AS INTEGER
- bx AS INTEGER
- cx AS INTEGER
- dx AS INTEGER
- Bp AS INTEGER
- si AS INTEGER
- di AS INTEGER
- flags AS INTEGER
- ds AS INTEGER
- es AS INTEGER
- END TYPE
-
- ' Subprograms
- DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX, outreg AS RegTypeX)
- DECLARE SUB ClearLine ()
- DECLARE SUB ClearScreen ()
- DECLARE SUB StdOut (a$)
- DECLARE SUB CrLf ()
- DECLARE SUB CursorPosition (row%, col%)
- DECLARE SUB CursorDown (n%)
- DECLARE SUB CursorLeft (n%)
- DECLARE SUB CursorRight (n%)
- DECLARE SUB CursorUp (n%)
- DECLARE SUB AssignKey (keyCode%, assign$)
- DECLARE SUB Attribute (attr%)
-
- ' Demonstrate the ClearLine and ClearScreen routines
- CLS
- PRINT "This will be erased quickly, in two steps..."
- t0 = TIMER
- DO
- LOOP UNTIL TIMER - t0 > 2
- LOCATE 1, 27
- ClearLine
- t0 = TIMER
- DO
- LOOP UNTIL TIMER - t0 > 2
- LOCATE 15, 1
- ClearScreen
-
- ' Demonstrate the StdOut routine
- bell$ = CHR$(7)
- StdOut "Sending a 'Bell' to StdOut" + bell$
- CrLf
-
- ' Set cursor position
- CursorPosition 3, 20
- StdOut "* CursorPosition 3, 20"
- CrLf
-
- ' Move the cursor around the screen
- StdOut "Cursor movements..."
- CrLf
- CursorDown 1
- StdOut "Down 1"
- CursorRight 12
- StdOut "Right 12"
- CursorDown 2
- StdOut "Down 2"
- CursorLeft 99
- StdOut "Left 99"
- CrLf
-
- ' Character attributes
- CrLf
- Attribute YELLOWFOREGROUND
- Attribute BRIGHT
- Attribute BLUEBACKGROUND
- StdOut "Bright yellow on blue"
- CrLf
- Attribute NORMAL
- StdOut "Back to normal attributes"
- CrLf
- '
- ' Key reassignment
- AssignKey 97, "REM The 'a' and 'b' keys have been redefined" + CHR$(13)
- AssignKey 98, "EXIT" + CHR$(13)
- CursorDown 1
- Attribute BRIGHT
- Attribute YELLOWFOREGROUND
- StdOut "NOTE:"
- CrLf
- StdOut "Press the 'a' key and then the 'b' key ... "
- CrLf
- StdOut "The program will then continue ........ "
- Attribute NORMAL
- CrLf
- SHELL
- AssignKey 97, ""
- AssignKey 98, ""
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: AssignKey
-
- Assigns a string to any key on the keyboard. The first parameter is the
- key code number returned by the ASC(INKEY$) statement for a given key
- press. The second parameter is a string of characters assigned to the
- indicated key. The string can be a maximum of 63 characters in length. If
- the string is null, the original key definition is returned to the key.
-
- One complication arises if the key normally returns an extended key code.
- Recall that such keys return CHR$(0), followed by a second character that
- identifies the key. The AssignKey subprogram recognizes negative key
- numbers as extended key codes. Pass the negative of the second byte of an
- extended key code to indicate the key.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: AssignKey **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Assigns a string to any key using ANSI.SYS driver.
- '
- ' EXAMPLE OF USE: AssignKey keyCode%, assign$
- ' PARAMETERS: keyCode% ASCII number for key to be reassigned
- ' assign$ String to assign to key
- ' VARIABLES: k$ Command string for ANSI.SYS driver
- ' i% Index to each character of assign$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB AssignKey (keyCode%, assign$)
- '
- SUB AssignKey (keyCode%, assign$) STATIC
- IF keyCode% <= 0 THEN
- k$ = "[0;"
- ELSE
- k$ = "["
- END IF
- k$ = k$ + MID$(STR$(keyCode%), 2)
- IF assign$ <> "" THEN
- FOR i% = 1 TO LEN(assign$)
- k$ = k$ + ";" + MID$(STR$(ASC(MID$(assign$, i%))), 2)
- NEXT i%
- END IF
- StdOut CHR$(27) + k$ + "p"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Attribute
-
- Sets screen color attributes as defined by the ANSI.SYS driver.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Attribute **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sets the foreground, background, and other color
- ' attributes.
- '
- ' EXAMPLE OF USE: Attribute attr%
- ' PARAMETERS: attr% Number for attribute to be set
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB StdOut (a$)
- ' DECLARE SUB Attribute (attr%)
- '
- SUB Attribute (attr%) STATIC
- StdOut CHR$(27) + "[" + MID$(STR$(attr%), 2) + "m"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ClearLine
-
- Sends to standard output the ANSI.SYS escape-code sequence that erases the
- current line from the cursor to the end of the line. The current cursor
- position is maintained.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ClearLine **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Clears the display line from the current cursor
- ' position to the end of the line.
- '
- ' EXAMPLE OF USE: ClearLine
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB ClearLine ()
- ' DECLARE SUB StdOut (a$)
- '
- SUB ClearLine STATIC
- StdOut CHR$(27) + "[K"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: ClearScreen
-
- Sends to standard output the ANSI.SYS escape-code sequence that clears the
- screen; positions the cursor at the top left of the screen.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ClearScreen **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Clears the screen and moves the cursor to the
- ' home position.
- '
- ' EXAMPLE OF USE: ClearScreen
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB ClearScreen ()
- ' DECLARE SUB StdOut (a$)
- '
- SUB ClearScreen STATIC
- StdOut CHR$(27) + "[2J"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: CrLf
-
- Sends carriage return and line feed to a standard output.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CrLf **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Sends line feed and carriage return characters
- ' to standard output.
- '
- ' EXAMPLE OF USE: CrLf
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB StdOut (a$)
- ' DECLARE SUB CrLf ()
- '
- SUB CrLf STATIC
- StdOut CHR$(13) + CHR$(10)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: CursorDown
-
- Sends to standard output the ANSI.SYS escape-code sequence that moves the
- cursor down the screen n% lines. The cursor stays in the same column and
- stops at the bottom line of the screen.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CursorDown **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Moves the cursor n% lines down the screen.
- '
- ' EXAMPLE OF USE: CursorDown n%
- ' PARAMETERS: n% Number of lines to move the cursor down
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB StdOut (a$)
- ' DECLARE SUB CursorDown (n%)
- '
- SUB CursorDown (n%) STATIC
- StdOut CHR$(27) + "[" + MID$(STR$(n%), 2) + "B"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: CursorHome
-
- Sends to standard output the ANSI.SYS escape-code sequence that moves the
- cursor to the home position; does not erase the display.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CursorHome **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Moves the cursor to the top left of the
- ' screen.
- '
- ' EXAMPLE OF USE: CursorHome
- ' PARAMETERS: (none)
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB CursorHome
- '
- SUB CursorHome STATIC
- StdOut CHR$(27) + "[H"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: CursorLeft
-
- Sends to standard output the ANSI.SYS escape-code sequence that moves the
- cursor to the left n% columns. The cursor stays in the same row and stops
- at the left column of the screen.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CursorLeft **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Moves the cursor n% columns left on the screen.
- '
- ' EXAMPLE OF USE: CursorLeft n%
- ' PARAMETERS: n% Number of columns to move the cursor left
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB CursorLeft (n%)
- '
- SUB CursorLeft (n%) STATIC
- StdOut CHR$(27) + "[" + MID$(STR$(n%), 2) + "D"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: CursorPosition
-
- Sends to standard output the ANSI.SYS escape-code sequence that moves the
- cursor to a given row and column.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CursorPosition **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Moves the cursor to the indicated row and column.
- '
- ' EXAMPLE OF USE: CursorPosition row%, col%
- ' PARAMETERS: row% Row to move the cursor to
- ' col% Column to move the cursor to
- ' VARIABLES: row$ String representation of row%
- ' col$ String representation of col%
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB CursorPosition (row%, col%)
- '
- SUB CursorPosition (row%, col%) STATIC
- row$ = MID$(STR$(row%), 2)
- col$ = MID$(STR$(col%), 2)
- StdOut CHR$(27) + "[" + row$ + ";" + col$ + "H"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: CursorRight
-
- Sends to standard output the ANSI.SYS escape-code sequence that moves the
- cursor to the right n% columns. The cursor stays in the same row and stops
- at the right column of the screen.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CursorRight **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Moves the cursor n% columns right on the screen.
- '
- ' EXAMPLE OF USE: CursorRight n%
- ' PARAMETERS: n% Number of columns to move the cursor right
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB CursorRight (n%)
- '
- SUB CursorRight (n%) STATIC
- StdOut CHR$(27) + "[" + MID$(STR$(n%), 2) + "C"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: CursorUp
-
- Sends to standard output the ANSI.SYS escape-code sequence that moves the
- cursor up the screen n% lines. The cursor stays in the same column and
- stops at the top line of the screen.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CursorUp **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Moves the cursor n% lines up the screen.
- '
- ' EXAMPLE OF USE: CursorUp n%
- ' PARAMETERS: n% Number of lines to move the cursor up
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB CursorUp (n%)
- '
- SUB CursorUp (n%) STATIC
- StdOut CHR$(27) + "[" + MID$(STR$(n%), 2) + "A"
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: StdOut
-
- Sends a string of bytes to the standard output device. The string is
- output through the MS-DOS function for string output, bypassing the
- QuickBASIC PRINT statement.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: StdOut **
- ' ** Type: Subprogram **
- ' ** Module: STDOUT.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Writes string to the MS-DOS standard output.
- '
- ' EXAMPLE OF USE: StdOut a$
- ' PARAMETERS: a$ String to be output
- ' VARIABLES: regX Structure of type RegTypeX
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB InterruptX (intnum%, inreg AS RegTypeX,
- ' outreg AS RegTypeX)
- ' DECLARE SUB StdOut (a$)
- '
- SUB StdOut (a$) STATIC
- DIM regX AS RegTypeX
- regX.ax = &H4000
- regX.cx = LEN(a$)
- regX.bx = 1
- regX.ds = VARSEG(a$)
- regX.dx = SADD(a$)
- InterruptX &H21, regX, regX
- IF regX.flags AND 1 THEN
- PRINT "Error while calling StdOut:"; regX.ax
- SYSTEM
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- STRINGS
-
- The STRINGS toolbox provides several common (and not so common)
- string-manipulation functions and subprograms.
-
- ╓┌─┌────────────────────────┌───────┌────────────────────────────────────────╖
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- STRINGS.BAS Demo module
- Ascii2Ebcdic$ Func Converts string from ASCII to EBCDIC
- BestMatch$ Func Returns best match to input string
- BuildAEStrings Sub Builds ASCII and EBCDIC character
- translation tables
- Center$ Func Centers string by padding with spaces
- Detab$ Func Replaces tab characters with spaces
- Ebcdic2Ascii$ Func Converts a string from EBCDIC to ASCII
- Entab$ Func Replaces spaces with tab characters
- FilterIn$ Func Retains only specified characters in
- string
- FilterOut$ Func Deletes specified characters from string
- Lpad$ Func Returns left-justified input string
- LtrimSet$ Func Deletes specified characters from left
- Ord% Func Returns byte number for ANSI mnemonic
- Repeat$ Func Combines multiple copies into one string
- Replace$ Func Replaces specified characters in string
- Reverse$ Func Reverses order of characters in a string
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- Reverse$ Func Reverses order of characters in a string
- ReverseCase$ Func Reverses case for each character in a
- string
- Rpad$ Func Returns right-justified input string
- RtrimSet$ Func Deletes specified characters from right
- Translate$ Func Exchanges characters in string from table
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- Demo Module: STRINGS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: STRINGS **
- ' ** Type: Toolbox **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- ' USAGE: No command line parameters
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: a$ Working string for demonstrations
- ' b$ Working string for demonstrations
- ' c$ Working string for demonstrations
- ' x$ Working string for demonstrations
- ' y$ Working string for demonstrations
- ' set$ Set of characters that define word separation
-
- DECLARE FUNCTION Ascii2Ebcdic$ (a$)
- DECLARE FUNCTION BestMatch$ (a$, x$, y$)
- DECLARE FUNCTION Center$ (a$, n%)
- DECLARE FUNCTION Detab$ (a$, tabs%)
- DECLARE FUNCTION Ebcdic2Ascii$ (e$)
- DECLARE FUNCTION Entab$ (a$, tabs%)
- DECLARE FUNCTION FilterIn$ (a$, set$)
- DECLARE FUNCTION FilterOut$ (a$, set$)
- DECLARE FUNCTION Lpad$ (a$, n%)
- DECLARE FUNCTION LtrimSet$ (a$, set$)
- DECLARE FUNCTION Ord% (a$)
- DECLARE FUNCTION Repeat$ (a$, n%)
- DECLARE FUNCTION Replace$ (a$, find$, substitute$)
- DECLARE FUNCTION Reverse$ (a$)
- DECLARE FUNCTION ReverseCase$ (a$)
- DECLARE FUNCTION Rpad$ (a$, n%)
- DECLARE FUNCTION RtrimSet$ (a$, set$)
- DECLARE FUNCTION Translate$ (a$, f$, t$)
-
- ' Subprograms
- DECLARE SUB BuildAEStrings ()
-
- ' Quick demonstrations
- CLS
- a$ = "This is a test"
- PRINT "a$", , a$
- PRINT "ReverseCase$(a$)", ReverseCase$(a$)
- PRINT "Reverse$(a$)", , Reverse$(a$)
- PRINT "Repeat$(a$, 3)", Repeat$(a$, 3)
- PRINT
-
- set$ = "T this"
- PRINT "set$", , set$
- PRINT "LtrimSet$(a$, set$)", LtrimSet$(a$, set$)
- PRINT "RtrimSet$(a$, set$)", RtrimSet$(a$, set$)
- PRINT "FilterOut$(a$, set$)", FilterOut$(a$, set$)
- PRINT "FilterIn$(a$, set$)", FilterIn$(a$, set$)
- PRINT
-
- a$ = "elephant"
- x$ = "alpha"
- y$ = "omega"
- PRINT "a$", , a$
- PRINT "x$", , x$
- PRINT "y$", , y$
- PRINT "BestMatch$(a$, x$, y$)", BestMatch$(a$, x$, y$)
- PRINT
-
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
-
- CLS
- a$ = "BEL"
- PRINT "a$", , a$
- PRINT "Ord%(a$)", , Ord%(a$)
- PRINT
-
- a$ = "This is a test"
- find$ = "s"
- substitute$ = "<s>"
- PRINT "a$", , , a$
- PRINT "find$", , , find$
- PRINT "substitute$", , , substitute$
- PRINT "Replace$(a$, find$, substitute$)", Replace$(a$, find$, substitut
- PRINT
-
- PRINT "a$", , a$
- PRINT "Lpad$(a$, 40)", , ":"; Lpad$(a$, 40); ":"
- PRINT "Rpad$(a$, 40)", , ":"; Rpad$(a$, 40); ":"
- PRINT "Center$(a$, 40)", ":"; Center$(a$, 40); ":"
- PRINT
-
- a$ = "a$ character" + STRING$(2, 9) + "count" + CHR$(9) + "is"
- PRINT a$; LEN(a$)
- PRINT "a$ = Detab$(a$, 8)"
- a$ = Detab$(a$, 8)
- PRINT a$; LEN(a$)
- PRINT "a$ = Entab$(a$, 8)"
- a$ = Entab$(a$, 8)
- PRINT a$; LEN(a$)
- PRINT
-
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
-
- CLS
- a$ = "You know this test string has vowels."
- x$ = "aeiou"
- y$ = "eioua"
- PRINT "a$", , a$
- PRINT "x$", , x$
- PRINT "y$", , y$
- PRINT "Translate$(a$, x$, y$)", Translate$(a$, x$, y$)
- PRINT
-
- a$ = "This is a test."
- b$ = Ascii2Ebcdic$(a$)
- c$ = Ebcdic2Ascii$(b$)
- PRINT "a$", , a$
- PRINT "b$ = Ascii2Ebcdic$(a$)", b$
- PRINT "c$ = Ebcdic2Ascii$(b$)", c$
- PRINT
-
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Ascii2Ebcdic$
-
- Converts a string of ASCII characters to EBCDIC equivalents.
-
- Almost all computers use the ASCII character set to define which byte
- represents which character. This standard makes it possible for computers,
- printers, plotters, and other equipment to communicate effectively.
- However, IBM's larger computers have long used the EBCDIC character set,
- an alternative way for computers and peripherals to communicate. If files
- are to be transferred to or from an IBM mainframe, it's necessary to
- translate character bytes between the two methods. This function, along
- with its counterpart Ebcdic2Ascii$, translates strings of characters
- between the ASCII character set and the EBCDIC character set.
-
- These functions and the BuildAEStrings subprogram share a pair of string
- variables, ascii$ and ebcdic$. The SHARED statement lets these two strings
- be accessed by each of these three routines while remaining invisible and
- unalterable to all other parts of a program.
-
- The BuildAEStrings subprogram is called only once, to build both the
- ascii$ and ebcdic$ translation strings the first time that the
- Ascii2Ebcdic$ or Ebcdic2Ascii$ function is called. All subsequent calls
- to these functions use these strings immediately, as the contents of the
- strings are preserved between calls.
-
- Refer to the BuildAEStrings subprogram for more information about how
- these two strings are built. Refer to the Translate$ function for more
- information about the character-by-character translation.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Ascii2Ebcdic$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a$ with each character translated from ASCII to EBCDIC.
- '
- ' EXAMPLE OF USE: e$ = Ascii2Ebcdic$(a$)
- ' PARAMETERS: a$ String of ASCII characters to be
- ' converted
- ' VARIABLES: ebcdic$ Table of translation characters
- ' ascii$ Table of translation characters
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Ascii2Ebcdic$ (a$)
- '
- FUNCTION Ascii2Ebcdic$ (a$) STATIC
- SHARED ebcdic$, ascii$
- IF ebcdic$ = "" THEN
- BuildAEStrings
- END IF
- Ascii2Ebcdic$ = Translate$(a$, ascii$, ebcdic$)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: BestMatch$
-
- Compares two strings with a third and returns the string that most closely
- matches the third.
-
- Everybody's talking "artificial intelligence" these days. Programs capable
- of making decisions based on "fuzzy" facts are already being used for
- voice analysis, pattern matching, and other similar tasks. This function
- provides a way to make an educated guess as to the best pattern match when
- comparing two strings.
-
- The method of comparison used here scans substrings of the target string
- and checks for occurrences of these substrings in each of the other two
- strings. A score is kept for the number of substring matches found for
- each string. The score is weighted heavier for longer substring matches.
- For example, finding an occurrence of the substring "ABC" is worth 6
- points, while finding separate occurrences of "E," "F," and "G" is worth a
- total of only 3 points.
-
- When all substrings of the target string have been checked, the points are
- compared for each test string. The highest score wins, and that string is
- returned as the result.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BestMatch$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns either x$ or y$, whichever is a best match to a$.
- '
- ' EXAMPLE OF USE: b$ = BestMatch$(a$, x$, y$)
- ' PARAMETERS: a$ The string to be matched
- ' x$ The first string to compare with a$
- ' y$ The second string to compare with a$
- ' VARIABLES: ua$ Uppercase working copy of a$
- ' ux$ Uppercase working copy of x$
- ' uy$ Uppercase working copy of y$
- ' lena% Length of a$
- ' i% Length of substrings of ua$
- ' j% Index into ua$
- ' t$ Substrings of ua$
- ' xscore% Accumulated score for substring matches
- ' found in ux$
- ' yscore% Accumulated score for substring matches
- ' found in uy$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION BestMatch$ (a$, x$, y$)
- '
- FUNCTION BestMatch$ (a$, x$, y$) STATIC
- ua$ = UCASE$(a$)
- ux$ = UCASE$(x$)
- uy$ = UCASE$(y$)
- lena% = LEN(ua$)
- FOR i% = 1 TO lena%
- FOR j% = 1 TO lena% - i% + 1
- t$ = MID$(ua$, j%, i%)
- IF INSTR(ux$, t$) THEN
- xscore% = xscore% + i% + i%
- END IF
- IF INSTR(uy$, t$) THEN
- yscore% = yscore% + i% + i%
- END IF
- NEXT j%
- NEXT i%
- IF xscore% > yscore% THEN
- BestMatch$ = x$
- ELSE
- BestMatch$ = y$
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: BuildAEStrings
-
- Initializes the ASCII-EBCDIC translation table strings. This subprogram is
- called once per program run, by either the Ascii2Ebcdic$ or
- Ebcdic2Ascii$ function, when one is called first. Each function checks to
- see whether the shared strings, ascii$ and ebcdic$, are filled in or
- whether they are still null (empty) strings. If they are null, this
- subprogram is called to fill them in before they are used as character
- translation tables.
-
- The method used to fill in the strings can easily create strings
- containing any binary bytes. First, ebcdic$ is created as a string of
- hexadecimal characters, each pair of which represents a single byte. At
- this point, ebcdic$ is twice the desired length. The processing loop near
- the end of the function converts each pair of hexadecimal characters to
- the byte it represents and replaces the hexadecimal characters with these
- bytes. After all hexadecimal character pairs are converted, the STRINGS
-
- first half of ebcdic$ contains the desired string of bytes. The second
- half of ebcdic$ is deleted.
-
- The string variable ascii$ is filled in with binary byte values 0 through
- 127. This string is built to be passed to the Translate$ function, which
- requires a string table for both lookup as well as replacement.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: BuildAEStrings **
- ' ** Type: Subprogram **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Called by the Ascii2Ebcdic$ and Ebcdic2Ascii$
- ' functions to build the translation strings.
- ' This subprogram is called only once.
- '
- ' EXAMPLE OF USE: Called automatically by either the Ascii2Ebcdic$ or
- ' Ebcdic2Ascii$ function
- ' PARAMETERS: ascii$ Shared by Ascii2Ebcdic$, Ebcdic2Ascii$, and
- ' BuildAEStrings
- ' ebcdic$ Shared by Ascii2Ebcdic$, Ebcdic2Ascii$, and
- ' BuildAEStrings
- ' VARIABLES: i% Index into strings
- ' byte% Binary value of character byte
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB BuildAEStrings ()
- '
- SUB BuildAEStrings STATIC
- SHARED ebcdic$, ascii$
- ascii$ = SPACE$(128)
- ebcdic$ = ebcdic$ + "00010203372D2E2F1605250B0C0D0E0F"
- ebcdic$ = ebcdic$ + "101112133C3D322618193F271C1D1E1F"
- ebcdic$ = ebcdic$ + "404F7F7B5B6C507D4D5D5C4E6B604B61"
- ebcdic$ = ebcdic$ + "F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F"
- ebcdic$ = ebcdic$ + "7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6"
- ebcdic$ = ebcdic$ + "D7D8D9E2E3E4E5E6E7E8E94AE05A5F6D"
- ebcdic$ = ebcdic$ + "79818283848586878889919293949596"
- ebcdic$ = ebcdic$ + "979899A2A3A4A5A6A7A8A9C06AD0A107"
- FOR i% = 0 TO 127
- MID$(ascii$, i% + 1, 1) = CHR$(i%)
- byte% = VAL("&H" + MID$(ebcdic$, i% + i% + 1, 2))
- MID$(ebcdic$, i% + 1, 1) = CHR$(byte%)
- NEXT i%
- ebcdic$ = LEFT$(ebcdic$, 128)
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Center$
-
- Returns a string of length n% by padding a$ with spaces on both ends.
-
- The original string is centered in the new string. If n% is less than the
- length of a$ (after any spaces are stripped from the ends), the string is
- returned with no spaces tacked on and with a length greater than n%.
-
- One obvious use for this function is centering titles and labels on a
- printed or displayed page.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Center$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Pads a$ with spaces on both ends until text is
- ' centered and the string length is n%.
- '
- ' EXAMPLE OF USE: b$ = Center$(a$, n%)
- ' PARAMETERS: a$ String of characters to be padded with spac
- ' n% Desired length of resulting string
- ' VARIABLES: pad% Number of spaces to pad at ends of string
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Center$ (a$, n%)
- '
- FUNCTION Center$ (a$, n%) STATIC
- a$ = LTRIM$(RTRIM$(a$))
- pad% = n% - LEN(a$)
- IF pad% > 0 THEN
- Center$ = SPACE$(pad% \ 2) + a$ + SPACE$(pad% - pad% \ 2)
- ELSE
- Center$ = a$
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Detab$
-
- Replaces tab characters with the appropriate number of spaces.
-
- Tab characters are useful for forcing text alignment into predictable
- columns and for conserving space in text files. If you then need to
- exchange the tab characters for the equivalent number of spaces, this
- function lets you do so.
-
- Your computer display and (probably) your printer use a tab spacing
- constant of 8. For this reason, the most common value passed to this
- function for tabs% is 8. Spaces are inserted in a$ in place of tab
- characters to align the following characters into columns that are
- multiples of 8. Displaying or printing the string before and after it's
- processed by this function should result in exactly the same output.
-
- Also see Entab$, which performs exactly the opposite function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name Detab$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Replaces all tab characters with spaces, using
- ' tabs% to determine proper alignment.
- '
- ' EXAMPLE OF USE: b$ = Detab$(a$, tabs%)
- ' PARAMETERS: a$ String with possible tab characters
- ' tabs% Tab spacing
- ' VARIABLES: t$ Working copy of a$
- ' tb$ Tab character
- ' tp% Pointer to position in t$ of a tab charac
- ' sp$ Spaces to replace a given tab character
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Detab$ (a$, tabs%)
- '
- FUNCTION Detab$ (a$, tabs%) STATIC
- t$ = a$
- tb$ = CHR$(9)
- DO
- tp% = INSTR(t$, tb$)
- IF tp% THEN
- Sp$ = SPACE$(tabs% - ((tp% - 1) MOD tabs%))
- t$ = LEFT$(t$, tp% - 1) + Sp$ + MID$(t$, tp% + 1)
- END IF
- LOOP UNTIL tp% = 0
- Detab$ = t$
- t$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Ebcdic2Ascii$
-
- Converts a string of EBCDIC characters to ASCII equivalents. This function
- performs the exact opposite of the Ascii2Ebcdic$ function.
-
- Refer to the Ascii2Ebcdic$ function for more information.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Ebcdic2Ascii$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a$ with each character translated from
- ' EBCDIC to ASCII.
- '
- ' EXAMPLE OF USE: b$ = Ascii2Ebcdic$(a$)
- ' PARAMETERS: a$ String of EBCDIC characters to be converte
- ' VARIABLES: ebcdic$ Table of translation characters
- ' ascii$ Table of translation characters
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Ebcdic2Ascii$ (e$)
- '
- FUNCTION Ebcdic2Ascii$ (e$) STATIC
- SHARED ebcdic$, ascii$
- IF ebcdic$ = "" THEN
- BuildAEStrings
- END IF
- Ebcdic2Ascii$ = Translate$(e$, ebcdic$, ascii$)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Entab$
-
- Replaces spaces with tab characters wherever possible, providing a way to
- compress the size of a text file.
-
- For the opposite function, replacing tabs with appropriate numbers of
- spaces, see Detab$.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Entab$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Replaces groups of spaces, where possible, with
- ' tab characters, keeping the alignment indicated
- ' by the value of tabs%.
- '
- ' EXAMPLE OF USE: b$ = Entab$(a$, tabs%)
- ' PARAMETERS: a$ String with possible tab characters
- ' tabs% Tab spacing
- ' VARIABLES: t$ Working copy of a$
- ' tb$ Tab character
- ' i% Index into t$
- ' k% Count of spaces being replaced
- ' j% Index into t$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Entab$ (a$, tabs%)
- '
- FUNCTION Entab$ (a$, tabs%) STATIC
- t$ = a$
- tb$ = CHR$(9)
- FOR i% = (LEN(t$) \ tabs%) * tabs% + 1 TO tabs% STEP -tabs%
- IF MID$(t$, i% - 1, 1) = " " THEN
- k% = 0
- FOR j% = 1 TO tabs%
- IF MID$(t$, i% - j%, 1) <> " " THEN
- k% = i% - j%
- EXIT FOR
- END IF
- NEXT j%
- IF k% = 0 THEN
- k% = i% - tabs% - 1
- END IF
- t$ = LEFT$(t$, k%) + tb$ + MID$(t$, i%)
- END IF
- NEXT i%
- Entab$ = t$
- t$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: FilterIn$
-
- Filters a string, character by character, and removes any characters that
- are not in the designated set. FilterIn$("EXAMPLE", "AEIOU"), for example,
- returns the string EAE, because all characters, except uppercase vowels,
- are removed from EXAMPLE.
-
- To filter a string by removing characters listed in set$ (as opposed to
- removing all characters not in set$), see the FilterOut$ function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FilterIn$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a$ with all occurrences of any characters
- ' that are not in set$ deleted.
- '
- ' EXAMPLE OF USE: b$ = FilterIn$(a$, set$)
- ' PARAMETERS: a$ String to be processed
- ' set$ Set of characters to be retained
- ' VARIABLES: i% Index into a$
- ' j% Count of characters retained
- ' lena% Length of a$
- ' t$ Working string space
- ' c$ Each character of a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION FilterIn$ (a$, set$)
- '
- FUNCTION FilterIn$ (a$, set$) STATIC
- i% = 1
- j% = 0
- lena% = LEN(a$)
- t$ = a$
- DO UNTIL i% > lena%
- c$ = MID$(a$, i%, 1)
- IF INSTR(set$, c$) THEN
- j% = j% + 1
- MID$(t$, j%, 1) = c$
- END IF
- i% = i% + 1
- LOOP
- FilterIn$ = LEFT$(t$, j%)
- t$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: FilterOut$
-
- Filters a string, character by character, and removes any characters that
- are listed in the designated set. FilterOut$("EXAMPLE", "AEIOU"),
- STRINGSfor example, returns the string XMPL, because all uppercase vowels
- are removed from EXAMPLE.
-
- To filter a string by removing characters not listed in set$ (as opposed
- to removing all characters found in set$), see the FilterIn$ function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: FilterOut$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a$ with all occurrences of any characters
- ' from set$ deleted.
- '
- ' EXAMPLE OF USE: b$ = FilterOut$(a$, set$)
- ' PARAMETERS: a$ String to be processed
- ' set$ Set of characters to be retained
- ' VARIABLES: i% Index into a$
- ' j% Count of characters retained
- ' lena% Length of a$
- ' t$ Working string space
- ' c$ Each character of a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION FilterOut$ (a$, set$)
- '
- FUNCTION FilterOut$ (a$, set$) STATIC
- i% = 1
- j% = 0
- lena% = LEN(a$)
- t$ = a$
- DO UNTIL i% > lena%
- c$ = MID$(a$, i%, 1)
- IF INSTR(set$, c$) = 0 THEN
- j% = j% + 1
- MID$(t$, j%, 1) = c$
- END IF
- i% = i% + 1
- LOOP
- FilterOut$ = LEFT$(t$, j%)
- t$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Lpad$
-
- Returns a left-justified string of n% characters by shifting a$ to the
- left and adding space characters on the right.
-
- This function actually does an amazing amount of work for only one program
- line. First, the string passed as parameter a$ has all spaces removed from
- its left, the final goal being to left justify the string.
-
- The desired string length is n%. To guarantee that you have at least n%
- characters to work with, n% space characters are added to the right of the
- string. Most likely, the string is now longer than desired. So, the LEFT$
- function returns the first n% characters from the string, finishing the
- desired processing of a$ and assigning the result to Lpad$, the name of
- the function.
-
- See Rpad$ for a similar function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Lpad$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string of length n%, with a$ left justified
- ' and padded on the right with spaces.
- '
- ' EXAMPLE OF USE: b$ = Lpad$(a$, n%)
- ' PARAMETERS: a$ String to be left justified and padded
- ' n% Length of string result
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Lpad$ (a$, n%)
- '
- FUNCTION Lpad$ (a$, n%) STATIC
- Lpad$ = LEFT$(LTRIM$(a$) + SPACE$(n%), n%)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: LtrimSet$
-
- Trims characters in set$ from the left of a$ until a character is found
- that is not in set$.
-
- STRINGS
-
- The QuickBASIC LTRIM$() function removes space characters from the end of
- a string. This function goes a step further and lets you remove any of
- several characters from the left of a string. For example,
- LtrimSet$("EXAMPLE", "AXE") returns MPLE.
-
- One use for this function is to remove tabs and spaces from the left of a
- string.
-
- See RtrimSet$ for a similar function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: LtrimSet$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Trims occurrences of any characters in set$
- ' from the left of a$.
- '
- ' EXAMPLE OF USE: b$ = LtrimSet$(a$, set$)
- ' PARAMETERS: a$ String to be trimmed
- ' set$ Set of characters to be trimmed
- ' VARIABLES: i% Index into a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION LtrimSet$ (a$, set$)
- '
- FUNCTION LtrimSet$ (a$, set$) STATIC
- IF a$ <> "" THEN
- FOR i% = 1 TO LEN(a$)
- IF INSTR(set$, MID$(a$, i%, 1)) = 0 THEN
- LtrimSet$ = MID$(a$, i%)
- EXIT FUNCTION
- END IF
- NEXT i%
- END IF
- LtrimSet$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Ord%
-
- Returns the byte number defined by ANSI standard mnemonics.
-
- This function interprets ANSI standard mnemonics for control characters
- and returns the numeric value of the byte the mnemonics represent (the
- ordinal of the mnemonic). Ord%("BEL"), for example, returns 7, the byte
- number for the bell character. (Recall that PRINT CHR$(7) causes your
- computer to beep.)
-
- Other common control-character mnemonics include CR (carriage return), LF
- (line feed), FF (form feed), and NUL (the zero byte value). Many others
- are available, however, including mnemonics for the lowercase alphabetic
- characters.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Ord% **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Similar to ASC() function; returns
- ' numeric byte values for the ANSI standard
- ' mnemonics for control characters.
- '
- ' EXAMPLE OF USE: byte% = Ord%(a$)
- ' PARAMETERS: a$ ANSI standard character mnemonic string
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Ord% (a$)
- '
- FUNCTION Ord% (a$) STATIC
- SELECT CASE UCASE$(a$)
- CASE "NUL" 'Null
- Ord% = 0
- CASE "SOH" 'Start of heading
- Ord% = 1
- CASE "STX" 'Start of text
- Ord% = 2
- CASE "ETX" 'End of text
- Ord% = 3
- CASE "EOT" 'End of transmission
- Ord% = 4
- CASE "ENQ" 'Enquiry
- Ord% = 5
- CASE "ACK" 'Acknowledge
- Ord% = 6
- CASE "BEL" 'Bell
- Ord% = 7
- CASE "BS" 'Backspace
- Ord% = 8
- CASE "HT" 'Horizontal tab
- Ord% = 9
- CASE "LF" 'Line feed
- Ord% = 10
- CASE "VT" 'Vertical tab
- Ord% = 11
- CASE "FF" 'Form feed
- Ord% = 12
- CASE "CR" 'Carriage return
- Ord% = 13
- CASE "SO" 'Shift out
- Ord% = 14
- CASE "SI" 'Shift in
- Ord% = 15
- CASE "DLE" 'Data link escape
- Ord% = 16
- CASE "DC1" 'Device control 1
- Ord% = 17
- CASE "DC2" 'Device control 2
- Ord% = 18
- CASE "DC3" 'Device control 3
- Ord% = 19
- CASE "DC4" 'Device control 4
- Ord% = 20
- CASE "NAK" 'Negative acknowledge
- Ord% = 21
- CASE "SYN" 'Synchronous idle
- Ord% = 22
- CASE "ETB" 'End of transmission block
- Ord% = 23
- CASE "CAN" 'Cancel
- Ord% = 24
- CASE "EM" 'End of medium
- Ord% = 25
- CASE "SUB" 'Substitute
- Ord% = 26
- CASE "ESC" 'Escape
- Ord% = 27
- CASE "FS" 'File separator
- Ord% = 28
- CASE "GS" 'Group separator
- Ord% = 29
- CASE "RS" 'Record separator
- Ord% = 30
- CASE "US" 'Unit separator
- Ord% = 31
- CASE "SP" 'Space
- Ord% = 32
- CASE "UND" 'Underline
- Ord% = 95
- CASE "GRA" 'Grave accent
- Ord% = 96
- CASE "LCA" 'Lowercase a
- Ord% = 97
- CASE "LCB" 'Lowercase b
- Ord% = 98
- CASE "LCC" 'Lowercase c
- Ord% = 99
- CASE "LCD" 'Lowercase d
- Ord% = 100
- CASE "LCE" 'Lowercase e
- Ord% = 101
- CASE "LCF" 'Lowercase f
- Ord% = 102
- CASE "LCG" 'Lowercase g
- Ord% = 103
- CASE "LCH" 'Lowercase h
- Ord% = 104
- CASE "LCI" 'Lowercase i
- Ord% = 105
- CASE "LCJ" 'Lowercase j
- Ord% = 106
- CASE "LCK" 'Lowercase k
- Ord% = 107
- CASE "LCL" 'Lowercase l
- Ord% = 108
- CASE "LCM" 'Lowercase m
- Ord% = 109
- CASE "LCN" 'Lowercase n
- Ord% = 110
- CASE "LCO" 'Lowercase o
- Ord% = 111
- CASE "LCP" 'Lowercase p
- Ord% = 112
- CASE "LCQ" 'Lowercase q
- Ord% = 113
- CASE "LCR" 'Lowercase r
- Ord% = 114
- CASE "LCS" 'Lowercase s
- Ord% = 115
- CASE "LCT" 'Lowercase t
- Ord% = 116
- CASE "LCU" 'Lowercase u
- Ord% = 117
- CASE "LCV" 'Lowercase v
- Ord% = 118
- CASE "LCW" 'Lowercase w
- Ord% = 119
- CASE "LCX" 'Lowercase x
- Ord% = 120
- CASE "LCY" 'Lowercase y
- Ord% = 121
- CASE "LCZ" 'Lowercase z
- Ord% = 122
- CASE "LBR" 'Left brace
- Ord% = 123
- CASE "VLN" 'Vertical line
- Ord% = 124
- CASE "RBR" 'Right brace
- Ord% = 125
- CASE "TIL" 'Tilde
- Ord% = 126
- CASE "DEL" 'Delete
- Ord% = 127
- CASE ELSE 'Not ANSI Standard ORD mnemonic
- Ord% = -1
- END SELECT
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Repeat$
-
- Returns the string result of concatenating n% copies of a$. If the length
- of the result is less than 0 or greater than 32767, an error message is
- displayed, and the program terminates.
-
- To create a string of 80 spaces, you can use the QuickBASIC function
- SPACE$(80). To create a string of 80 equal signs, you can use STRING$(80,
- "="). But how can you create an 80-character string made up of 40
- repetitions of "+-"? The Repeat$ function lets you do so. Repeat$("+-",
- 40) would do the trick.
-
- At first glance, this function looks like more code than is needed.
- Consider the short function on the following page that returns the same
- result.
-
-
- FUNCTION SlowRepeat$ (a$, n%) STATIC
- x$ = ""
- FOR i% = 1 to n%
- x$ = x$ + a$
- NEXT i%
- SlowRepeat$ = x$
- END FUNCTION
-
- In tests of operating speed, this shorter function often ran about 10
- times slower than did the Repeat$ function! The difference is in how the
- string space is handled.
-
- SlowRepeat$ performs much string-manipulation overhead for each n%
- repetition of a$. In particular, the statement x$ = x$ + a$ creates
- working copies of x$ and a$ in the string workspace for each iteration. As
- x$ becomes larger, this shuffling of strings begins to bog down the
- function, even though QuickBASIC performs these functions efficiently.
-
- The Repeat$ function avoids much of this string-manipulation overhead by
- assigning string results to the MID$ of a large string (t$) that was
- created only once. First, t$ is created as a string of spaces long enough
- to hold all n% copies of a$. Each copy of a$ is then assigned to the
- appropriate substring location in t$ by use of the MID$ statement.
-
- This technique can often be used to speed up other string manipulations.
- The difference in speed is often insignificant, except in cases where a
- large number of string operations are performed.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Repeat$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a string formed by concatenating n%
- ' copies of a$ together.
- '
- ' EXAMPLE OF USE: b$ = Repeat$(a$, n%)
- ' PARAMETERS: a$ String to be repeated
- ' n% Number of copies of a$ to concatenate
- ' VARIABLES: lena% Length of a$
- ' lent& Length of result
- ' t$ Work space for building result
- ' ndx% Index into t$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Repeat$ (a$, n%)
- '
- FUNCTION Repeat$ (a$, n%) STATIC
- lena% = LEN(a$)
- lent& = n% * lena%
- IF lent& < 0 OR lent& > 32767 THEN
- PRINT "ERROR: Repeat$ - Negative repetition, or result too long
- SYSTEM
- ELSEIF lent& = 0 THEN
- Repeat$ = ""
- ELSE
- t$ = SPACE$(lent&)
- ndx% = 1
- DO
- MID$(t$, ndx%, lena%) = a$
- ndx% = ndx% + lena%
- LOOP UNTIL ndx% > lent&
- Repeat$ = t$
- t$ = ""
- END IF
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Replace$
-
- Replaces all occurrences of find$ in a$ with substitute$.
-
- One common function provided by text editors and word processors is the
- ability to globally replace occurrences of character strings with other
- character strings. This function performs such a global replacement in a
- single string. By using this function repeatedly, you can globally edit
- entire files of strings.
-
- For example, Replace$ ("This is a test", "i", "ii") returns the string
- Thiis iis a test.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Replace$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Replaces all occurrences of find$ in a$ with substitute$.
- '
- ' EXAMPLE OF USE: b$ = Replace$(a$, find$, substitute$)
- ' PARAMETERS: a$ String to make substring replacements in
- ' find$ Substring to be searched for
- ' substitutes$ String for replacing the found
- ' substrings
- ' VARIABLES: t$ Working copy of a$
- ' lenf% Length of find$
- ' lens% Length of substitute$
- ' i% Index into a$, pointing at substrings
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Replace$ (a$, find$, substitute$)
- '
- FUNCTION Replace$ (a$, find$, substitute$) STATIC
- t$ = a$
- lenf% = LEN(find$)
- lens% = LEN(substitute$)
- i% = 1
- DO
- i% = INSTR(i%, t$, find$)
- IF i% = 0 THEN
- EXIT DO
- END IF
- t$ = LEFT$(t$, i% - 1) + substitute$ + MID$(t$, i% + lenf%)
- i% = i% + lens%
- LOOP
- Replace$ = t$
- t$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Reverse$
-
- Quickly reverses the order of all characters in a string. For example,
- Reverse$("QuickBASIC") returns CISABkciuQ.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Reverse$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Reverses the order of all characters in a$.
- '
- ' EXAMPLE OF USE: b$ = Reverse$(a$)
- ' PARAMETERS: a$ String to be processed
- ' VARIABLES: n% Length of the string
- ' r$ Working string space
- ' i% Index into the string
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Reverse$ (a$)
- '
- FUNCTION Reverse$ (a$) STATIC
- n% = LEN(a$)
- r$ = a$
- FOR i% = 1 TO n%
- MID$(r$, i%, 1) = MID$(a$, n% - i% + 1, 1)
- NEXT i%
- Reverse$ = r$
- r$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: ReverseCase$
-
- Changes the case of all alphabetical characters in a passed string.
- Nonalphabetic characters are left undisturbed.
-
- Some text editors can change the case of characters from the current
- cursor location to the end of the line. This function was designed with
- that concept in mind. ReverseCase$("Testing 1,2,3"), for example, returns
- tESTING 1,2,3.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: ReverseCase$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Changes all lowercase characters to uppercase
- ' and all uppercase characters to lowercase.
- '
- ' EXAMPLE OF USE: b$ = ReverseCase$(a$)
- ' PARAMETERS: a$ String to be processed
- ' VARIABLES: r$ Working copy of a$
- ' i% Index into r$
- ' t$ Character from middle of a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION ReverseCase$ (a$)
- '
- FUNCTION ReverseCase$ (a$) STATIC
- r$ = a$
- FOR i% = 1 TO LEN(a$)
- t$ = MID$(a$, i%, 1)
- IF LCASE$(t$) <> t$ THEN
- MID$(r$, i%, 1) = LCASE$(t$)
- ELSE
- MID$(r$, i%, 1) = UCASE$(t$)
- END IF
- NEXT i%
- ReverseCase$ = r$
- r$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Rpad$
-
- Returns a right-justified string of n% characters by shifting a$ to the
- right as far as possible and adding space characters on the left.
-
- See Lpad$ for a similar function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Rpad$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns string of length n%, with a$ right justified
- ' and padded on the left with spaces.
- '
- ' EXAMPLE OF USE: b$ = Rpad$(a$, n%)
- ' PARAMETERS: a$ String to be right justified and padded
- ' n% Length of string result
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Rpad$ (a$, n%)
- '
- FUNCTION Rpad$ (a$, n%) STATIC
- Rpad$ = RIGHT$(SPACE$(n%) + RTRIM$(a$), n%)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: RtrimSet$
-
- Trims characters in set$ from the right of a$ until a character is found
- that is not in set$.
-
- The QuickBASIC RTRIM$() function removes space characters from the right
- of a string. This function goes a step further and lets you remove any of
- several characters from the right of a string. For example,
- RtrimSet$("EXAMPLE", "LEAVE") returns EXAMP.
-
- One use for this function is to remove tabs and spaces from the right of a
- string.
-
- See LtrimSet$ for a similar function.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: RtrimSet$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Trims occurrences of any characters in set$
- ' from the right of a$.
- '
- ' EXAMPLE OF USE: b$ = LtrimSet$(a$, set$)
- ' PARAMETERS: a$ String to be trimmed
- ' set$ Set of characters to be trimmed
- ' VARIABLES: i% Index into a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION RtrimSet$ (a$, set$)
- '
- FUNCTION RtrimSet$ (a$, set$) STATIC
- IF a$ <> "" THEN
- FOR i% = LEN(a$) TO 1 STEP -1
- IF INSTR(set$, MID$(a$, i%, 1)) = 0 THEN
- RtrimSet$ = LEFT$(a$, i%)
- EXIT FUNCTION
- END IF
- NEXT i%
- END IF
- RtrimSet$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Translate$
-
- Performs a table-lookup translation of the characters in a$. Each
- character in a$ is searched for in f$. If found, the character is replaced
- by the character located in the same position in t$. Take a look at a
- simple example to help clarify the explanation.
-
- Translate$("EXAMPLE", "ABCDE", "vwxyz") returns zXvMPLz. The first
- character of "EXAMPLE" is found in the fifth character position of
- "ABCDE," so it is replaced with the fifth character of "vwxyz." (The "E"
- is replaced with a "z.") Then each remaining character in "EXAMPLE" is
- searched for and replaced in the same way.
-
- The Ascii2Ebcdic$ and Ebcdic2Ascii$ functions call this function to
- translate characters from one standard set to the other.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Translate$ **
- ' ** Type: Function **
- ' ** Module: STRINGS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns a$ with each character translated from
- ' f$ to t$. If a character from a$ is found in f$,
- ' it is replaced with the character located
- ' in the same position in t$.
- '
- ' EXAMPLE OF USE: b$ = Translate$ (a$, f$, t$)
- ' PARAMETERS: a$ String to be translated
- ' f$ Table of lookup characters
- ' t$ Table of replacement characters
- ' VARIABLES: ta$ Working copy of a$
- ' lena% Length of a$
- ' lenf% Length of f$
- ' lent% Length of t$
- ' i% Index into ta$
- ' ptr% Pointer into f$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Translate$ (a$, f$, t$)
- '
- FUNCTION Translate$ (a$, f$, t$) STATIC
- ta$ = a$
- lena% = LEN(ta$)
- lenf% = LEN(f$)
- lent% = LEN(t$)
- IF lena% > 0 AND lenf% > 0 AND lent% > 0 THEN
- FOR i% = 1 TO lena%
- ptr% = INSTR(f$, MID$(ta$, i%, 1))
- IF ptr% THEN
- MID$(ta$, i%, 1) = MID$(t$, ptr%, 1)
- END IF
- NEXT i%
- END IF
- Translate$ = ta$
- ta$ = ""
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- TRIANGLE
-
- The TRIANGLE toolbox is a collection of analytical geometry functions and
- subprograms for calculating parts of triangles.
-
- The demonstration module-level code of this toolbox provides a useful
- triangle calculator utility.
-
- Run the program, and enter the known sides and/or angles of a triangle
- when prompted. If it's possible to calculate the remaining sides and
- angles, the program does so and then displays the results.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- TRIANGLE.BAS Demo module
- Deg2Rad# Func Converts degree angular units to
- radians
- Rad2Deg# Func Converts radian angular units to
- degrees
- Triangle Sub Calculates sides and angles of
- triangle
- TriangleArea# Func Calculates area of triangle from 3
- sides
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: TRIANGLE
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: TRIANGLE **
- ' ** Type: Toolbox **
- ' ** Module: TRIANGLE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' .MAK FILE: TRIANGLE.BAS
- ' QCALMATH.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: sA$ User input of side a
- ' sB$ User input of side b
- ' sC$ User input of side c
- ' aA$ User input of angle A
- ' aB$ User input of angle B
- ' aC$ User input of angle C
- ' sA# Side A
- ' sB# Side B
- ' sC# Side C
- ' aA# Angle A
- ' aB# Angle B
- ' aC# Angle C
-
- ' Functions
- DECLARE FUNCTION Deg2Rad# (deg#)
- DECLARE FUNCTION Rad2Deg# (rad#)
- DECLARE FUNCTION ArcCosine# (x#)
- DECLARE FUNCTION ArcSine# (x#)
- DECLARE FUNCTION TriangleArea# (sA#, sB#, sC#)
-
- ' Subprograms
- DECLARE SUB Triangle (sA#, sB#, sC#, aA#, aB#, aC#)
-
- ' Initialization
- SCREEN 2
- CLS
- PRINT "TRIANGLE"
-
- ' Draw a representative triangle
- WINDOW (0, 0)-(1, 1)
- LINE (.3, .7)-(.8, .7)
- LINE -(.4, 1)
- LINE -(.3, .7)
-
- ' Label the triangle sides
- LOCATE 4, 26
- PRINT "a"
- LOCATE 3, 48
- PRINT "b"
- LOCATE 9, 42
- PRINT "c"
-
- ' Label the triangle angles
- LOCATE 7, 55
- PRINT "A"
- LOCATE 7, 28
- PRINT "B"
- LOCATE 2, 33
- PRINT "C"
-
- ' Ask user for the known data
- LOCATE 12, 1
- PRINT "Enter known sides and angles (deg),"
- PRINT "and press Enter for unknowns..."
- LOCATE 16, 1
- LINE INPUT "Side a "; sA$
- LINE INPUT "Side b "; sB$
- LINE INPUT "Side c "; sC$
- PRINT
- LINE INPUT "Angle A "; aA$
- LINE INPUT "Angle B "; aB$
- LINE INPUT "Angle C "; aC$
- PRINT
-
- ' Convert to numeric values
- sA# = VAL(sA$)
- sB# = VAL(sB$)
- sC# = VAL(sC$)
- aA# = Deg2Rad#(VAL(aA$))
- aB# = Deg2Rad#(VAL(aB$))
- aC# = Deg2Rad#(VAL(aC$))
-
- ' Solve for the unknowns
- Triangle sA#, sB#, sC#, aA#, aB#, aC#
-
- ' Output the results
- LOCATE 16, 1
- PRINT "Side a "; sA#
- PRINT "Side b "; sB#
- PRINT "Side c "; sC#
- PRINT
- PRINT "Angle A "; Rad2Deg#(aA#); "Deg"
- PRINT "Angle B "; Rad2Deg#(aB#); "Deg"
- PRINT "Angle C "; Rad2Deg#(aC#); "Deg"
- LOCATE 20, 40
- PRINT "Area = "; TriangleArea#(sA#, sB#, sC#)
-
- ' All done
- LOCATE 24, 1
- PRINT "Press any key to continue";
- DO
- LOOP WHILE INKEY = ""
- SCREEN 0
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Deg2Rad#
-
- Converts degrees to radians.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Deg2Rad# **
- ' ** Type: Function **
- ' ** Module: TRIANGLE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts degree angular units to radians.
- '
- ' EXAMPLE OF USE: r# = Deg2Rad#(deg#)
- ' PARAMETERS: deg# Degrees
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Deg2Rad# (deg#)
- '
- FUNCTION Deg2Rad# (deg#) STATIC
- Deg2Rad# = deg# / 57.29577951308232#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: Rad2Deg#
-
- Converts radians to degrees.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Rad2Deg# **
- ' ** Type: Function **
- ' ** Module: TRIANGLE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Converts radian angular units to degrees.
- '
- ' EXAMPLE OF USE: d# = Rad2Deg#(rad#)
- ' PARAMETERS: rad# Radians
- ' VARIABLES: (none)
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION Rad2Deg# (rad#)
- '
- FUNCTION Rad2Deg# (rad#) STATIC
- Rad2Deg# = rad# * 57.29577951308232#
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Triangle
-
- Calculates sides and angles of a triangle if enough sides and/or angles
- are given to be able to deduce the rest. Any combination of sides and
- angles can be given, although illegal combinations will produce
- unpredictable results.
-
- Double-precision numbers are used throughout this subprogram to maintain
- high accuracy. Change all the pound signs to exclamation points if you
- prefer to work with single-precision numbers.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Triangle **
- ' ** Type: Subprogram **
- ' ** Module: TRIANGLE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Calculates all sides and angles of a triangle,
- ' assuming enough sides and angles are given.
- '
- ' EXAMPLE OF USE: Triangle sA#, sB#, sC#, aA#, aB#, aC#
- ' PARAMETERS: sA# Side A
- ' sB# Side B
- ' sC# Side C
- ' aA# Angle A
- ' aB# Angle B
- ' aC# Angle C
- ' VARIABLES: i% Looping index
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB Triangle (sA#, sB#, sC#, aA#, aB#, aC#)
- '
- SUB Triangle (sA#, sB#, sC#, aA#, aB#, aC#) STATIC
-
- FOR i% = 1 TO 18
-
- IF aA# = 0# THEN
- IF sA# <> 0# AND sB# <> 0# AND sC# <> 0# THEN
- t# = sB# * sB# + sC# * sC# - sA# * sA#
- aA# = ArcCosine#(t# / 2# / sB# / sC#)
- END IF
- END IF
-
- IF aB# = 0# THEN
- IF sA# <> 0# AND sB# <> 0# AND aA# <> 0# THEN
- aB# = ArcSine#(sB# * SIN(aA#) / sA#)
- END IF
- END IF
-
- IF aC# = 0# THEN
- IF aA# <> 0# AND aB# <> 0# THEN
- aC# = 3.141592653589793# - aA# - aB#
- END IF
- END IF
-
- IF sB# = 0# THEN
- IF sA# <> 0# AND aB# <> 0# AND aA# <> 0# THEN
- sB# = sA# * SIN(aB#) / SIN(aA#)
- END IF
- END IF
-
- IF sC# = 0# THEN
- IF sA# <> 0# AND sB# <> 0# AND aC# <> 0# THEN
- t# = sA# * sA# + sB# * sB#
- sC# = SQR(t# - 2# * sA# * sB# * COS(aC#))
- END IF
- END IF
-
- IF i% MOD 2 THEN
- SWAP sB#, sC#
- SWAP aB#, aC#
- ELSE
- SWAP sA#, sB#
- SWAP aA#, aB#
- END IF
-
- NEXT i%
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: TriangleArea#
-
- Calculates the area of a triangle given the three sides of the triangle.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: TriangleArea# **
- ' ** Type: Function **
- ' ** Module: TRIANGLE.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the area of a triangle given the three sides.
- '
- ' EXAMPLE OF USE: TriangleArea# sA#, sB#, sC#
- ' PARAMETERS: sA# Side A
- ' sB# Side B
- ' sC# Side C
- ' VARIABLES: s# Sum of the three sides of the triangle
- ' divided by two
- ' t1# Temporary variable
- ' t2# Temporary variable
- ' t3# Temporary variable
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION TriangleArea# (sA#, sB#, sC#)
- '
- FUNCTION TriangleArea# (sA#, sB#, sC#) STATIC
- s# = (sA# + sB# + sC#) / 2#
- t1# = s# - sA#
- t2# = s# - sB#
- t3# = s# - sC#
- TriangleArea# = SQR(s# * t1# * t2# * t3#)
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- WINDOWS
-
- The WINDOWS demo module demonstrates the windows subprograms. One lets
- you create several types of windows for displaying information and menu
- selections. A second subprogram removes the most recently created window.
-
- The WindowsType data structure completely defines the action and
- appearance of the windows that you can create. Although the list of
- variables in this structure is fairly long, you have the advantage of
- complete control over the windows.
-
- Set the action code to 0, 1, or 2. An action code of 0 indicates a return
- to the calling program immediately after the window is created, leaving
- the window on the screen. You could use this type of window for simply
- displaying information.
-
- An action code of 1 creates the window and then waits for the user to
- press any key before continuing. The code for the key pressed is returned
- to the calling program, making it possible to use a type 1 window to ask
- yes-or-no, multiple choice, or other questions.
-
- An action code of 2 creates the most sophisticated type of window. In this
- case, a menu window is created, providing several methods for the user to
- select from among the available menu choices. One line of the menu window
- is highlighted to indicate the currently selected choice. You can use the
- up and down arrow keys or the mouse to move this highlight to the desired
- line. Clicking with the mouse or pressing the Enter key selects the
- currently highlighted line. You can also press the key for the first
- unique character of a line, which immediately selects that line. The
- Windows subprogram then returns the line number for a type 2 action code
- menu.
-
- The edgeLine variable in the WindowsType data structure should also be set
- to 0, 1, or 2. This parameter tells the Windows subprogram to draw a
- border around the window with 0-, 1-, or 2-line graphics characters.
-
- You can select and control the foreground and background colors for each
- part of a window individually. The color definition constants used in the
- demonstration program can be very useful for setting these parameters.
-
- The row and column variables define the placement of the upper left corner
- of the window. The Windows subprogram automatically sizes the window for
- both the number of lines and the length of the longest line. Be sure to
- place the window where it won't hit the edges of the screen.
-
- The title string appears in the center of the top border of the window,
- and the prompt string appears in the center of the bottom border of the
- display. If these strings are null, nothing is displayed in the window
- borders.
-
- The PCOPY statement copies screen pages for saving and restoring the
- background information under the windows. This technique results in very
- quick window appearance and disappearance without using complicated
- assembly-language routines. In 40-column SCREEN mode 0, you can display up
- to seven windows at once, one for each available screen page. Depending on
- the graphics adapter you have, other video modes let you display two to
- four windows simultaneously.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- WINDOWS.BAS Demo module
- Windows Sub Creates a pop-up window
- WindowsPop Sub Removes last displayed window
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: WINDOWS
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: WINDOWS **
- ' ** Type: Toolbox **
- ' ** Module: WINDOWS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- ' USAGE: No command line parameters
- ' REQUIREMENTS: MIXED.QLB/.LIB
- ' Mouse (optional)
- ' .MAK FILE: WINDOWS.BAS
- ' BITS.BAS
- ' BIOSCALL.BAS
- ' MOUSSUBS.BAS
- ' KEYS.BAS
- ' PARAMETERS: (none)
- ' VARIABLES: w1 Structure of type WindowsType
- ' w2 Structure of type WindowsType
- ' w3 Structure of type WindowsType
- ' w1Text$() Strings to display in first window
- ' w2Text$() Strings to display in second window
- ' w3Text$() Strings to display in third window
- ' w1Title$ Title string for first window
- ' w1Prompt$ Prompt string for first window
- ' w2Title$ Title string for second window
- ' w2Prompt$ Prompt string for second window
- ' w3Title$ Title string for third window
- ' arrow$ String showing up and down arrows
- ' entSymbol$ String showing the Enter key symbol
- ' w3Prompt$ Prompt string for third window
- ' i% Looping index
- ' t0 Timer value
-
-
- ' Define color constants
- CONST BLACK = 0
- CONST BLUE = 1
- CONST GREEN = 2
- CONST CYAN = 3
- CONST RED = 4
- CONST MAGENTA = 5
- CONST BROWN = 6
- CONST WHITE = 7
- CONST BRIGHT = 8
- CONST BLINK = 16
- CONST YELLOW = BROWN + BRIGHT
-
- TYPE WindowsType
- action AS INTEGER
- edgeLine AS INTEGER
- row AS INTEGER
- col AS INTEGER
- fgdEdge AS INTEGER
- bgdEdge AS INTEGER
- fgdBody AS INTEGER
- bgdBody AS INTEGER
- fgdHighlight AS INTEGER
- bgdHighlight AS INTEGER
- fgdTitle AS INTEGER
- bgdTitle AS INTEGER
- fgdPrompt AS INTEGER
- bgdPrompt AS INTEGER
- returnCode AS INTEGER
- END TYPE
-
- ' Functions
- DECLARE FUNCTION InKeyCode% ()
-
- ' Subprograms
- DECLARE SUB Windows (w AS WindowsType, wText$(), wTitle$, wPrompt$)
- DECLARE SUB WindowsPop ()
- DECLARE SUB VideoState (mode%, columns%, page%)
- DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
- DECLARE SUB MouseMickey (horizontal%, vertical%)
- DECLARE SUB MouseNow (leftButton%, rightButton%, xMouse%, yMouse%)
-
- ' Data structures
- DIM w1 AS WindowsType
- DIM w2 AS WindowsType
- DIM w3 AS WindowsType
-
- ' Arrays
- DIM w1Text$(1 TO 5)
- DIM w2Text$(1 TO 3)
- DIM w3Text$(1 TO 9)
-
- ' Define first window
- w1.action = 0
- w1.edgeLine = 1
- w1.row = 2
- w1.col = 3
- w1.fgdEdge = YELLOW
- w1.bgdEdge = BLUE
- w1.fgdBody = BRIGHT + WHITE
- w1.bgdBody = BLUE
- w1.fgdHighlight = 0
- w1.bgdHighlight = 0
- w1.fgdTitle = YELLOW
- w1.bgdTitle = BLUE
- w1.fgdPrompt = YELLOW
- w1.bgdPrompt = BLUE
- w1Title$ = " First Window "
- w1Text$(1) = "This window demonstrates how information"
- w1Text$(2) = "can be displayed without requesting any"
- w1Text$(3) = "response from the user. The action code"
- w1Text$(4) = "is 0, causing an immediate return to the"
- w1Text$(5) = "program after the window is displayed."
- w1Prompt$ = ""
-
- ' Define second window
- w2.action = 1
- w2.edgeLine = 2
- w2.row = 10
- w2.col = 12
- w2.fgdEdge = CYAN + BRIGHT
- w2.bgdEdge = BLACK
- w2.fgdBody = YELLOW
- w2.bgdBody = BLACK
- w2.fgdHighlight = 0
- w2.bgdHighlight = 0
- w2.fgdTitle = CYAN + BRIGHT
- w2.bgdTitle = BLUE
- w2.fgdPrompt = CYAN + BRIGHT
- w2.bgdPrompt = BLUE
- w2Title$ = " Second window, action code is 1 "
- w2Text$(1) = "This window waits for the user to press"
- w2Text$(2) = "any key before continuing. The key code"
- w2Text$(3) = "is passed back to the calling program."
- w2Prompt$ = " Press any key to continue. "
-
- ' Define third window
- w3.action = 2
- w3.edgeLine = 2
- w3.row = 7
- w3.col = 15
- w3.fgdEdge = YELLOW
- w3.bgdEdge = WHITE
- w3.fgdBody = BLACK
- w3.bgdBody = WHITE
- w3.fgdHighlight = WHITE + BRIGHT
- w3.bgdHighlight = BLACK
- w3.fgdTitle = YELLOW
- w3.bgdTitle = WHITE
- w3.fgdPrompt = YELLOW
- w3.bgdPrompt = WHITE
- w3Title$ = " Third window, action is 2 (menu selection) "
- arrows$ = CHR$(24) + " " + CHR$(25) + " "
- entSymbol$ = CHR$(17) + CHR$(196) + CHR$(217)
- w3Prompt$ = " <Character> " + arrows$ + entSymbol$ + " or use mouse "
- w3Text$(1) = "1. This is the first line in the window."
- w3Text$(2) = "2. This is the second."
- w3Text$(3) = "3. This is the third line."
- w3Text$(4) = "4. The fourth."
- w3Text$(5) = "5. The fifth."
- w3Text$(6) = "A. You can press <A> or <a> to select this line."
- w3Text$(7) = "B. You can press <1> to <5> for one of the first 5 lines.
- w3Text$(8) = "C. Try moving the cursor up or down and pressing Enter."
- w3Text$(9) = "D. Also, try the mouse. Click with left button."
-
- ' Initialize the display
- SCREEN 0, , 0, 0
- WIDTH 80
- CLS
- FOR i% = 1 TO 20
- PRINT STRING$(80, 178)
- NEXT i%
- LOCATE 6, 24
- PRINT " * Windows toolbox demonstration * "
-
- ' Wait for any key to be pressed
- LOCATE 22, 1
- PRINT "Press any key to continue"
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' Clear the "press any key" prompt
- LOCATE 22, 1
- PRINT SPACE$(25)
-
- ' Create the three windows
- Windows w1, w1Text$(), w1Title$, w1Prompt$
- Windows w2, w2Text$(), w2Title$, w2Prompt$
- Windows w3, w3Text$(), w3Title$, w3Prompt$
-
- ' Display the result codes, and erase each window
- FOR i% = 1 TO 4
- LOCATE 21, 1
- COLOR WHITE, BLACK
- PRINT "The three return codes...";
- PRINT w1.returnCode; w2.returnCode; w3.returnCode
- COLOR YELLOW
- PRINT "Every five seconds another window will disappear..."
- COLOR WHITE, BLACK
- t0 = TIMER
- DO
- LOOP UNTIL TIMER - t0 > 5
- WindowsPop
- NEXT i%
-
- ' All done
- CLS
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: Windows
-
- Creates a pop-up window for displaying string data or menu selections. The
- data structure of type WindowsType defines the action, colors, borders,
- and other attributes of the windows. If you provide invalid parameters,
- you receive an appropriate error message, and the program terminates.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Windows **
- ' ** Type: Subprogram **
- ' ** Module: WINDOWS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Displays a rectangular window for information display
- ' or menu selection.
- '
- ' EXAMPLE OF USE: Windows w1, wText$(), wTitle$, wPrompt$
- ' PARAMETERS: w1 Structure of type WindowsType
- ' wTest$() Array of strings to be displayed
- ' wTitle$ Title string
- ' wPrompt$ Prompt string
- ' VARIABLES: mode% Current video mode
- ' columns% Current number of character columns
- ' page% Current video page
- ' cursorRow% Saved cursor row position
- ' cursorCol% Saved cursor column position
- ' newpage% Next video page
- ' lbText% Lower boundary of array of text lines
- ' ubText% Upper boundary of array of text lines
- ' i% Looping index
- ' maxlen% Length of longest string to display
- ' length% Length of each array string
- ' row2% Row number at bottom right corner of win
- ' col2% Column number at bottom right corner of
- ' window
- ' ul% Upper left corner border character code
- ' ur% Upper right corner border character code
- ' ll% Lower left corner border character code
- ' lr% Lower right corner border character code
- ' vl% Vertical border character code
- ' hl% Horizontal border character code
- ' r% Index to each line of text
- ' ptr% Highlighted line pointer
- ' lastPtr% Last highlighted line
- ' horizontal% Horizontal mouse mickies
- ' vertical% Vertical mouse mickies
- ' mickies Accumulated vertical mickies
- ' choice$ Set of unique characters for each menu l
- ' tmp$ Work string
- ' kee% Key code returned by InKeyCode% function
- ' leftButton% Mouse left button state
- ' rightButton% Mouse right button state
- ' xMouse% Mouse X position
- ' yMouse% Mouse Y position
- ' MODULE LEVEL
- ' DECLARATIONS: SUB Windows (w AS WindowsType, wText$(), wTitle$,
- ' wPrompt$) STATIC
- '
- SUB Windows (w AS WindowsType, wText$(), wTitle$, wPrompt$) STATIC
- ' Key code numbers
- CONST DOWNARROW = 20480
- CONST ENTER = 13
- CONST ESCAPE = 27
- CONST UPARROW = 18432
-
- ' Determine current video page
- VideoState mode%, columns%, page%
-
- ' Record current cursor location
- cursorRow% = CSRLIN
- cursorCol% = POS(0)
-
- ' Window will be on the next page, if available
- newpage% = page% + 1
- IF newpage% > 7 THEN
- SCREEN , , 0, 0
- PRINT "Error: Windows - not enough video pages"
- SYSTEM
- END IF
-
- ' Copy current page to new page
- PCOPY page%, newpage%
-
- ' Show the current page while building window on new page
- SCREEN , , newpage%, page%
-
- ' Determine array bounds
- lbText% = LBOUND(wText$)
- ubText% = UBOUND(wText$)
-
- ' Check the text array bounds, lower always 1, upper > 0
- IF lbText% <> 1 OR ubText% < 1 THEN
- SCREEN , , 0, 0
- PRINT "Error: Windows - text array dimensioned incorrectly"
- SYSTEM
- END IF
-
- ' Determine longest string in the text array
- maxLen% = 0
- FOR i% = lbText% TO ubText%
- length% = LEN(wText$(i%))
- IF length% > maxLen% THEN
- maxLen% = length%
- END IF
- NEXT i%
-
- ' Determine the bottom right corner of window
- row2% = w.row + ubText% + 1
- col2% = w.col + maxLen% + 3
-
- ' Check that window is on screen
- IF w.row < 1 OR w.col < 1 OR row2% > 25 OR col2% > columns% THEN
- SCREEN , , 0, 0
- PRINT "Error: Windows - part of window is off screen"
- SYSTEM
- END IF
-
- ' Set the edge characters
- SELECT CASE w.edgeLine
- CASE 0
- ul% = 32
- ur% = 32
- ll% = 32
- lr% = 32
- vl% = 32
- hl% = 32
- CASE 1
- ul% = 218
- ur% = 191
- ll% = 192
- lr% = 217
- vl% = 179
- hl% = 196
- CASE 2
- ul% = 201
- ur% = 187
- ll% = 200
- lr% = 188
- vl% = 186
- hl% = 205
- CASE ELSE
- SCREEN , , 0, 0
- PRINT "Error: Windows - Edge line type incorrect"
- SYSTEM
- END SELECT
-
- ' Draw top edge of the box
- LOCATE w.row, w.col, 0
- COLOR w.fgdEdge, w.bgdEdge
- PRINT CHR$(ul%); STRING$(maxLen% + 2, hl%); CHR$(ur%);
-
- ' Draw the body of the window
- FOR r% = w.row + 1 TO row2% - 1
- LOCATE r%, w.col, 0
- COLOR w.fgdEdge, w.bgdEdge
- PRINT CHR$(vl%);
- COLOR w.fgdBody, w.bgdBody
- tmp$ = LEFT$(wText$(r% - w.row) + SPACE$(maxLen%), maxLen%)
- PRINT " "; tmp$; " ";
- COLOR w.fgdEdge, w.bgdEdge
- PRINT CHR$(vl%);
- NEXT r%
-
- ' Draw bottom edge of the box
- LOCATE row2%, w.col, 0
- COLOR w.fgdEdge, w.bgdEdge
- PRINT CHR$(ll%); STRING$(maxLen% + 2, hl%); CHR$(lr%);
-
- ' Center and print top title if present
- IF wTitle$ <> "" THEN
- LOCATE w.row, (w.col + col2% - LEN(wTitle$) + 1) \ 2, 0
- COLOR w.fgdTitle, w.bgdTitle
- PRINT wTitle$;
- END IF
-
- ' Center and print prompt if present
- IF wPrompt$ <> "" THEN
- LOCATE row2%, (w.col + col2% - LEN(wPrompt$) + 1) \ 2, 0
- COLOR w.fgdPrompt, w.bgdPrompt
- PRINT wPrompt$;
- END IF
-
- ' Now make the new page visible and active
- SCREEN , , newpage%, newpage%
-
- ' Take next action based on action code
- SELECT CASE w.action
- CASE 1
-
- ' Get a key code number and return it
- DO
- w.returnCode = InKeyCode%
- LOOP UNTIL w.returnCode
-
- CASE 2
-
- ' Set choice pointer to last selection if known
- IF w.returnCode > 0 AND w.returnCode < ubText% THEN
- ptr% = w.returnCode
- ELSE
- ptr% = 1
- END IF
-
- ' Start with last pointer different, to update highlighting
- IF ptr% > 1 THEN
- lastPtr% = 1
- ELSE
- lastPtr% = 2
- END IF
-
- ' Clear any mouse mickey counts
- MouseMickey horizontal%, vertical%
- mickies% = 0
-
- ' Create unique key selection string
- choice$ = ""
- FOR i% = 1 TO ubText%
- tmp$ = UCASE$(LTRIM$(wText$(i%)))
- DO
- IF tmp$ <> "" THEN
- t$ = LEFT$(tmp$, 1)
- tmp$ = MID$(tmp$, 2)
- IF INSTR(choice$, t$) = 0 THEN
- choice$ = choice$ + t$
- END IF
- ELSE
- SCREEN 0, , 0
- PRINT "Error: Windows - No unique character"
- SYSTEM
- END IF
- LOOP UNTIL LEN(choice$) = i%
- NEXT i%
-
- ' Main loop, monitor mouse and keyboard
- DO
-
- ' Add the mouse mickies
- MouseMickey horizontal%, vertical%
- mickies% = mickies% + vertical%
-
- ' Check for enough mickies
- IF mickies% < -17 THEN
- mickies% = 0
- IF ptr% > 1 THEN
- ptr% = ptr% - 1
- END IF
- ELSEIF mickies% > 17 THEN
- mickies% = 0
- IF ptr% < ubText% THEN
- ptr% = ptr% + 1
- END IF
- END IF
-
- ' Check keyboard
- kee% = InKeyCode%
- IF kee% >= ASC("a") AND kee% <= ASC("z") THEN
- kee% = ASC(UCASE$(CHR$(kee%)))
- END IF
- SELECT CASE kee%
- CASE UPARROW
- IF ptr% > 1 THEN
- ptr% = ptr% - 1
- END IF
- CASE DOWNARROW
- IF ptr% < ubText% THEN
- ptr% = ptr% + 1
- END IF
- CASE ENTER
- w.returnCode = ptr%
- CASE ESCAPE
- w.returnCode = -1
- CASE ELSE
- w.returnCode = INSTR(choice$, CHR$(kee%))
- IF w.returnCode THEN
- ptr% = w.returnCode
- END IF
- END SELECT
-
- ' Check the left mouse button
- MouseNow leftButton%, rightButton%, xMouse%, yMouse%
- IF leftButton% THEN
- w.returnCode = ptr%
- END IF
-
- ' Update the highlight if line has changed
- IF ptr% <> lastPtr% THEN
- LOCATE lastPtr% + w.row, w.col + 2, 0
- COLOR w.fgdBody, w.bgdBody
- tmp$ = LEFT$(wText$(lastPtr%) + SPACE$(maxLen%), maxLen
- PRINT tmp$;
- LOCATE ptr% + w.row, w.col + 2, 0
- COLOR w.fgdHighlight, w.bgdHighlight
- tmp$ = LEFT$(wText$(ptr%) + SPACE$(maxLen%), maxLen%)
- PRINT tmp$;
- lastPtr% = ptr%
- END IF
-
- LOOP WHILE w.returnCode = 0
-
- CASE ELSE
- w.returnCode = 0
- END SELECT
-
- ' Reset the cursor position
- LOCATE cursorRow%, cursorCol%
-
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: WindowsPop
-
- Removes the most recently created window from the screen. The SCREEN
- statement is used to change the apage and vpage parameters simultaneously,
- resulting in nearly instant removal of the window.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: WindowsPop **
- ' ** Type: Subprogram **
- ' ** Module: WINDOWS.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Removes last displayed window.
- '
- ' EXAMPLE OF USE: WindowsPop
- ' PARAMETERS: (none)
- ' VARIABLES: mode% Current video mode
- ' columns% Current number of display columns
- ' page% Current display page
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE SUB WindowsPop ()
- '
- SUB WindowsPop STATIC
- VideoState mode%, columns%, page%
- IF page% THEN
- SCREEN 0, , page% - 1, page% - 1
- END IF
- END SUB
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- WORDCOUN
-
- The WORDCOUN toolbox counts words in a file and contains a function that
- counts words in a string. Enter a filename on the command line when you
- run this program.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- WORDCOUN.BAS Demo module
- WordCount% Func Returns number of words in a string
- ──────────────────────────────────────────────────────────────────────────
-
-
- Demo Module: WORDCOUN
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: WORDCOUN **
- ' ** Type: Toolbox **
- ' ** Module: WORDCOUN.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: WORDCOUN filename
- ' .MAK FILE: (none)
- ' PARAMETERS: filename Name of file to be processed
- ' VARIABLES: fileName$ Name of file from the command line
- ' sep$ List of characters defined as word separ
- ' a$ Each line from the file
- ' totalCount& Total count of words
-
- DECLARE FUNCTION WordCount% (a$, sep$)
-
- ' Assume a filename has been given on the command line
- fileName$ = COMMAND$
-
- ' Open the file
- OPEN fileName$ FOR INPUT AS #1
-
- ' Define the word-separating characters as space, tab, and comma
- sep$ = " " + CHR$(9) + ","
-
- ' Read in and process each line
- DO
- LINE INPUT #1, a$
- totalCount& = totalCount& + WordCount%(a$, sep$)
- LOOP UNTIL EOF(1)
-
- ' Print the results
- PRINT "There are"; totalCount&; "words in "; fileName$
-
- ' That's all
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: WordCount%
-
- Returns the number of words in a string. Words are defined as groups of
- characters separated by one or more of the characters in sep$. The
- WORDCOUN toolbox passes sep$ with a space, a tab, and a comma in it, but
- you can place any characters in sep$ that you want to use to define the
- separation of words.
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: Wordcount% **
- ' ** Type: Function **
- ' ** Module: WORDCOUN.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Returns the number of words in a string.
- '
- ' EXAMPLE OF USE: WordCount% a$, sep$
- ' PARAMETERS: a$ String containing words to be counted
- ' sep$ List of word separation characters
- ' VARIABLES: count% Count of words
- ' flag% Indicates if scanning is currently inside o
- ' word
- ' la% length of a$
- ' i% Index to each character of a$
- ' MODULE LEVEL
- ' DECLARATIONS: DECLARE FUNCTION WordCount% (a$, sep$)
- '
- FUNCTION WordCount% (a$, sep$) STATIC
- count% = 0
- flag% = 0
- la% = LEN(a$)
- IF la% > 0 AND sep$ <> "" THEN
- FOR i% = 1 TO la%
- IF INSTR(sep$, MID$(a$, i%, 1)) THEN
- IF flag% THEN
- flag% = 0
- count% = count% + 1
- END IF
- ELSE
- flag% = 1
- END IF
- NEXT i%
- END IF
- WordCount% = count% + flag%
-
- END FUNCTION
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PART 3 MIXED-LANGUAGE TOOLBOXES
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter Four Using Mixed-Language Toolboxes
-
- Although Microsoft QuickBASIC is a sophisticated and powerful
- software-development tool, other languages, such as C, FORTRAN, Pascal,
- and assembly language, have unique strengths. The ability to mix
- subprograms and functions written in any of these languages lets you use
- the best features of each. FORTRAN, for example, has extensive mathematics
- and engineering libraries, and C is a powerful development language. For
- the fastest running programs, assembly language can't be beat. Once you
- understand a few concepts, you'll be able to easily combine routines from
- these languages.
-
-
- Near and Far Addressing
-
- MS-DOS runs on the 8088, 8086, 80286, and 80386 family of microprocessors
- found at the heart of IBM Personal Computers and compatibles. These chips
- use special hardware registers that allow quicker access and shorter
- instruction when referring to data or procedures located in the same block
- of 65536 (64 KB) bytes of memory.
-
- From a software point of view, microprocessor instructions can address
- memory locations by referring to either locations in a currently defined,
- single block of 64 KB memory addresses or to any possible locations in
- memory space. These references are called "near" and "far," respectively.
- Near references require one word, and far references require two words.
- Normally, high-level languages such as QuickBASIC take care of all these
- details for you, but when you link subprograms from other languages with
- QuickBASIC, you need to be sure that references to variables and calls to
- subprograms and functions all use the same type of near or far addressing.
-
- You can adjust Microsoft QuickC and Microsoft Macro Assembler 5.0 to
- create programs using a variety of memory models that indicate whether
- memory locations are referred to by near or far addressing. To be
- compatible with QuickBASIC's method, you should use Medium Model settings
- for both compilers. In fact, this is the default setting for QuickC,
- making it easy for you to write QuickC routines to be called from
- QuickBASIC.
-
-
- Passing Variables
-
- Most programming languages, including QuickBASIC and QuickC, let you pass
- variables to called subprograms, functions, and subroutines by listing
- them in parentheses as part of the calling statement. This list matches
- one for one the parameters defined and used in the called routine.
-
- You can pass these parameters to and from a subprogram or function by
- reference or by value. Some languages pass the address of the referenced
- variable, and changes made to the variable by the routine modify the
- contents of memory that this address points to. Other languages pass
- copies of the values of the variables. Changes to the passed variables
- don't affect the originals because the changes are made only to the
- copies.
-
- The important concept is that both the calling routine and the called
- routine must agree as to how they pass parameters back and forth. For
- example, QuickBASIC usually passes parameters by reference, and QuickC by
- value. Fortunately, both languages let you control whether parameters are
- passed by value or by reference. See the CDECL modifier of the QuickBASIC
- DECLARE statement for an example of how you can control parameter passing.
-
- Parameter passing can also vary from language to language in the order in
- which the parameters are pushed onto the stack as well as in the method
- used to remove these parameters from the stack when the called routine is
- finished. For example, consider a QuickBASIC program that passes
- parameters (A, B, C) to a QuickC subprogram. The QuickC routine processes
- the parameters as (C, B, A). The CDECL modifier in the QuickBASIC DECLARE
- statement can tell QuickBASIC to reverse the normal order of parameter
- pushing to be compatible with QuickC.
-
- In most languages, when a subprogram or function is finished, the
- parameters are removed from the stack before the routine returns to the
- calling program. QuickC routines expect the calling program to clean up
- the stack after the return. (This allows passing a variable number of
- parameters in C.) The CDECL modifier instructs QuickBASIC to clean up the
- stack after calling a subprogram or function.
-
- By using standard parameter-passing techniques and by following the
- examples in this book and in your Microsoft QuickBASIC and Microsoft Macro
- Assembler manuals, you'll find mixed-language programming easy and
- convenient.
-
- The routines in Part III of this book demonstrate passing integers, arrays
- of integers, and string variables. The Microsoft Macro Assembler was used
- to develop the mouse interface subprogram, and Microsoft QuickC was used
- to create some bit manipulation and byte-movement routines.
-
-
- Creating Mixed-Language Toolboxes
-
- In the section "Using QuickBASIC Toolboxes," you will find the steps to
- follow for using the QuickC and Macro Assembler routines presented in Part
- III of this book. Please see "Creating MIXED.QLB," beginning on page 22.
-
- In addition to compiling from the system prompt, you can also compile each
- QuickC toolbox, CTOOLS1.C and CTOOLS2.C, from within the QuickC
- environment. Run QuickC by typing QC, and notice that the environment is
- very similar in appearance and feel to that of QuickBASIC. Pull down the
- Files menu and choose Open. Select CTOOLS1.C to load the first toolbox
- into QuickC. Then pull down the Run menu and choose Compile. A dialog box
- opens, providing several compiling options. In the Output Options section,
- select Obj, rather than the default Memory, and then select Compile File,
- rather than the default Build Program option. You can experiment with the
- options listed under Miscellaneous, but selecting Optimizations and
- deselecting the Stack Checking and Debug options generally results in a
- smaller .OBJ file. QuickC then compiles the CTOOLS1.C source code
- currently in memory and writes the resulting CTOOLS1.OBJ file to disk.
- Repeat the process for the CTOOLS2.C file.
-
- Once you have created the object-code files and the MIXED.QLB Quick
- Library and have loaded MIXED.QLB with QuickBASIC, you can then call any
- or all of the QuickC and Macro Assembler functions and subprograms from
- within programs running in the QuickBASIC environment. Be sure to declare
- the subprogram or function in the module-level code, and then call the
- routines freely, as though they were part of the standard set of
- QuickBASIC functions and commands.
-
- Once a program is running as desired in the QuickBASIC environment you may
- want to compile it into a stand-alone .EXE format file. Simply compile the
- program from within QuickBASIC and the appropriate .LIB file will be
- searched. The MIXED.LIB file will automatically pull in the necessary code
- during the LINK process.
-
- NOTE: You must have QuickC installed to compile CDEMO1 and CDEMO2 into
- executable files.
-
- Assembly Source-Code Files
-
- The CASEMAP.ASM and MOUSE.ASM source-code files are listed here for your
- convenience in building both the MIXED.QLB and MIXED.LIB libraries.
-
- The CASEMAP.ASM subprogram is called by TranslateCountry$, a function
- found in the DOSCALLS module, to translate each character, one at a time.
-
- This routine demonstrates how you can use QuickBASIC's DECLARE statement
- to pass parameters by value rather than by reference. In this case, the
- segment- and offset-address parameters for the MS-DOS translation routine
- are passed by value, resulting in a very efficient branch to the MS-DOS
- character-translation routine from CaseMap.
-
- ──────────────────────────────────────────────────────────────────────────
- ; **********************************************
- ; ** CASEMAP.ASM MASM 5.0 **
- ; ** **
- ; ** Assembly subprogram for translating **
- ; ** some characters according to the **
- ; ** currently loaded MS-DOS country- **
- ; ** dependent information. **
- ; ** **
- ; ** Use: CALL CASEMAP (CHAR%, SEG%, OFS%) **
- ; ** Note: CHAR% is passed by reference **
- ; ** SEG% and OFS% are passed by value **
- ; **********************************************
- ;
- ; EXAMPLE OF USE: CALL CaseMap (char%, seg%, ofs%)
- ; PARAMETERS: char% Character byte to be translated
- ; seg% Segment of address of MS-DOS translate routi
- ; ofs% Offset of address of MS-DOS translate routin
- ; VARIABLES: (none)
- ; MODULE LEVEL
- ; DECLARATIONS: DECLARE SUB GetCountry (country AS CountryType)
- ; DECLARE SUB CaseMap (character%, BYVAL Segment%,
- ; BYVAL Offset%)
- ; DECLARE FUNCTION TranslateCountry$ (a$, country AS Coun
-
-
- .MODEL MEDIUM
- .CODE
- public casemap
-
- casemap proc
-
- ; Standard entry
- push bp
- mov bp,sp
-
- ; Get CHAR% into AX register
- mov bx,[bp+10]
- mov ax,[bx]
-
- ; Call the translate function in MS-DOS
- call dword ptr [bp+6]
-
- ; Return translated character to CHAR%
- mov bx,[bp+10]
- mov [bx],ax
-
- ; Standard exit, assumes three variables passed
- pop bp
- ret 6
-
- ; End of the procedure
- casemap endp
- end
- ──────────────────────────────────────────────────────────────────────────
-
- The MOUSE.ASM subprogram provides a fast and efficient method of
- interfacing QuickBASIC with the memory-resident mouse-driver software.
- (See your mouse documentation for information on loading this driver into
- memory.)
-
- ──────────────────────────────────────────────────────────────────────────
- ; **********************************************
- ; ** MOUSE.ASM Macro Assembler **
- ; ** **
- ; ** Assembly subprogram for accessing the **
- ; ** Microsoft Mouse from QuickBASIC 4.00 **
- ; ** **
- ; ** Use: CALL MOUSE (M1%, M2%, M3%, M4%) **
- ; **********************************************
- ;
- ; EXAMPLE OF USE: CALL Mouse (m1%, m2%, m3%, m4%)
- ; PARAMETERS: m1% Passed in AX to the mouse driver
- ; m2% Passed in BX to the mouse driver
- ; m3% Passed in CX to the mouse driver
- ; m4% Passed in DX to the mouse driver
- ; VARIABLES: (none)
- ; MODULE LEVEL
- ; DECLARATIONS: DECLARE SUB Mouse (m1%, m2%, m3%, m4%)
-
- .MODEL MEDIUM
- .CODE
- public mouse
-
- mouse proc
-
- ; Standard entry
- push bp
- mov bp,sp
-
- ; Get M1% and store it on the stack
- mov bx,[bp+12]
- mov ax,[bx]
- push ax
-
- ; Get M2% and store it on the stack
- mov bx,[bp+10]
- mov ax,[bx]
- push ax
-
- ; Get M3% into CX register
- mov bx,[bp+8]
- mov cx,[bx]
-
- ; Get M4% into DX register
- mov bx,[bp+6]
- mov dx,[bx]
-
- ; Move M2% from stack into BX register
- pop bx
-
- ; Move M1% from stack into AX register
- pop ax
-
- ; Set ES to same as DS (for mouse function 9)
- push ds
- pop es
-
- ; Do the mouse interrupt
- int 33h
-
- ; Save BX (M2%) on stack to free register
- push bx
-
- ; Return M1% from AX
- mov bx,[bp+12]
- mov [bx],ax
-
- ; Return M2% from stack (was BX)
- pop ax
- mov bx,[bp+10]
- mov [bx],ax
-
- ; Return M3% from CX
- mov bx,[bp+8]
- mov [bx],cx
-
- ; Return M4% from DX
- mov bx,[bp+6]
- mov [bx],dx
-
- ; Standard exit, assumes four variables passed
- pop bp
- ret 8
-
- ; End of this procedure
- mouse endp
- end
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- CDEMO1.BAS AND CTOOLS1.C
-
- The CDEMO1.BAS program is a QuickBASIC program that demonstrates the
- proper declaration and calling of the QuickC routines presented in the
- CTOOLS1.C toolbox.
-
- The IsIt[Type]% functions can efficiently determine the classification of
- any character, given its ASCII numeric value. For example, given c% =
- ASC("A"), the IsItAlnum%, IsItAlpha%, IsItAscii%, IsItGraph%,
- IsItPrint%, IsItUpper%, and IsItXDigit% functions all return a true
- (non-zero) value, and all other functions return zero.
-
- The MovBytes and MovWords subprograms allow movement of bytes or words
- from any location in memory to any other, using the QuickC movedata
- function. You can use these subprograms to copy the contents of variables
- into variables of a different type. The eight bytes of a double-precision
- number, for example, can be easily extracted from an eight-character
- string after the data has been moved from the number into the string.
- Large arrays of data can efficiently be moved into arrays of a different
- type, and video memory can be stored in a string, as demonstrated by the
- module-level code of CDEMO1.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- CDEMO1.BAS QuickBASIC program module
- CTOOLS1.C C-language toolbox containing
- functions/subprograms
- IsItAlnum% Func Alphanumeric character determination
- IsItAlpha% Func Alphabetic character determination
- IsItAscii% Func Standard ASCII character determination
- IsItCntrl% Func Control character determination
- IsItDigit% Func Decimal digit (0─9) determination
- IsItGraph% Func Graphics character determination
- IsItLower% Func Lowercase character determination
- IsItPrint% Func Printable character determination
- IsItPunct% Func Punctuation character determination
- IsItSpace% Func Space character determination
- IsItUpper% Func Uppercase character determination
- IsItXDigit% Func Hexadecimal character determination
- MovBytes Sub Moves bytes from one location to another
- MovWords Sub Moves blocks of words in memory
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: CDEMO1
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CDEMO1 **
- ' ** Type: Program **
- ' ** Module: CDEMO1.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' Demonstrates the QuickC routines presented in
- ' the file CTOOLS1.C.
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' MIXED.QLB/.LIB
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: a%(0 TO 1999) Storage space for first text screen
- ' b%(0 TO 1999) Storage space for second text screen
- ' i% Looping index
- ' sseg% Word and byte move source segment
- ' part of address
- ' soff% Word and byte move source offset
- ' part of address
- ' dseg% Word and byte move destination segment
- ' part of address
- ' doff% Word and byte move destination offset
- ' part of address
- ' nwords% Number of words to move
- ' nbytes% Number of bytes to move
- ' t$ Copy of TIME$
- ' quitflag% Signal to end first demonstration
-
- ' Functions
- DECLARE FUNCTION IsItAlnum% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItAlpha% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItAscii% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItCntrl% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItDigit% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItGraph% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItLower% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItPrint% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItPunct% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItSpace% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItUpper% CDECL (BYVAL c AS INTEGER)
- DECLARE FUNCTION IsItXDigit% CDECL (BYVAL c AS INTEGER)
-
- ' Subprograms
- DECLARE SUB MovBytes CDECL (sseg%, soff%, dseg%, doff%, nbytes%)
- DECLARE SUB MovWords CDECL (sseg%, soff%, dseg%, doff%, nwords%)
-
- ' Make two buffers for the first page of video memory
- DIM a%(0 TO 1999), b%(0 TO 1999)
-
- ' Prevent scrolling when printing in row 25, column 80
- VIEW PRINT 1 TO 25
-
- ' Create the first page of text
- CLS
- COLOR 14, 4
- FOR i% = 1 TO 25
- PRINT STRING$(80, 179);
- NEXT i%
- COLOR 15, 1
- LOCATE 11, 25
- PRINT STRING$(30, 32);
- LOCATE 12, 25
- PRINT " - Calling MovWords - "
- LOCATE 13, 25
- PRINT STRING$(30, 32);
-
- ' Move the screen memory into the first array
- sseg% = &HB800
- soff% = 0
- dseg% = VARSEG(a%(0))
- doff% = VARPTR(a%(0))
- nwords% = 2000
- MovWords sseg%, soff%, dseg%, doff%, nwords%
-
- ' Create the second page of text
- CLS
- COLOR 14, 4
- FOR i% = 1 TO 25
- PRINT STRING$(80, 196);
- NEXT i%
- COLOR 15, 1
- LOCATE 11, 25
- PRINT STRING$(30, 32);
- LOCATE 12, 25
- PRINT " - Calling MovBytes - "
- LOCATE 13, 25
- PRINT STRING$(30, 32);
-
- ' Move the screen memory into the second array
- sseg% = &HB800
- soff% = 0
- dseg% = VARSEG(b%(0))
- doff% = VARPTR(b%(0))
- nwords% = 2000
- MovWords sseg%, soff%, dseg%, doff%, nwords%
-
- ' Set destination to the video screen memory
- dseg% = &HB800
- doff% = 0
-
- ' Do the following until a key is pressed
- DO
-
- ' Move 2000 words from first array to screen memory
- sseg% = VARSEG(a%(0))
- soff% = VARPTR(a%(0))
- nwords% = 2000
- MovWords sseg%, soff%, dseg%, doff%, nwords%
-
- ' Wait one second
- t$ = TIME$
- DO
- IF INKEY$ <> "" THEN
- t$ = ""
- quitFlag% = 1
- END IF
- LOOP UNTIL TIME$ <> t$
-
- ' Move 4000 bytes from second array to screen memory
- sseg% = VARSEG(b%(0))
- soff% = VARPTR(b%(0))
- nbytes% = 4000
- MovBytes sseg%, soff%, dseg%, doff%, nbytes%
-
- ' Wait one second
- t$ = TIME$
- DO
- IF INKEY$ <> "" THEN
- t$ = ""
- quitFlag% = 1
- END IF
- LOOP UNTIL TIME$ <> t$
-
- LOOP UNTIL quitFlag%
-
- ' Create a table of all 256 characters and their type designations
- FOR i% = 0 TO 255
-
- ' After each screenful, display a heading
- IF i% MOD 19 = 0 THEN
-
- ' If not the first heading, prompt user before continuing
- IF i% THEN
- PRINT
- PRINT "Press any key to continue"
- DO WHILE INKEY$ = ""
- LOOP
- END IF
-
- ' Print the heading
- CLS
- PRINT "Char Alnum Alpha Ascii Cntrl Digit Graph ";
- PRINT "Lower Print Punct Space Upper XDigit"
- PRINT
- END IF
-
- ' Some characters we don't want to display
- SELECT CASE i%
- CASE 7, 8, 9, 10, 11, 12, 13, 29, 30, 31
- PRINT USING "### "; i%;
- CASE ELSE
- PRINT USING "### \ \"; i%, CHR$(i%);
- END SELECT
-
- ' Display "1" if test is true, "0" otherwise
- PRINT USING " # "; 1 + (0 = IsItAlnum%(i%));
- PRINT USING " # "; 1 + (0 = IsItAlpha%(i%));
- PRINT USING " # "; 1 + (0 = IsItAscii%(i%));
- PRINT USING " # "; 1 + (0 = IsItCntrl%(i%));
- PRINT USING " # "; 1 + (0 = IsItDigit%(i%));
- PRINT USING " # "; 1 + (0 = IsItGraph%(i%));
- PRINT USING " # "; 1 + (0 = IsItLower%(i%));
- PRINT USING " # "; 1 + (0 = IsItPrint%(i%));
- PRINT USING " # "; 1 + (0 = IsItPunct%(i%));
- PRINT USING " # "; 1 + (0 = IsItSpace%(i%));
- PRINT USING " # "; 1 + (0 = IsItUpper%(i%));
- PRINT USING " # "; 1 + (0 = IsItXDigit%(i%))
-
- NEXT i%
- END
- ──────────────────────────────────────────────────────────────────────────
-
-
- Toolbox: CTOOLS1.C
-
- The CTOOLS1.C toolbox provides access to the efficient QuickC functions
- for classifying characters and to QuickC's fast memory move functions for
- copying blocks of bytes or words from any location in memory to any other.
-
- You can determine character types using QuickBASIC code, but the QuickC
- routines are optimized for speed. Also, adhering to the definitions
- provided by QuickC guarantees that character classifications will be the
- same for both languages.
-
- You must add both of the following #include statements at the top of the
- CTOOLS1.C source-code file, before the function definitions are given.
- These two statements pull in the contents of header files necessary for
- correct compilation by QuickC:
-
-
- #include <ctype.h>
- #include <memory.h>
-
-
- Function: IsItAlnum%
-
- Determines whether a character is alphanumeric. This function returns a
- non-zero value if the integer value represents an alphanumeric ASCII
- character or a zero if the value does not. Alphanumeric characters are in
- the ranges A through Z, a through z, and 0 through 9.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItAlnum% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItAlnum%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitalnum (c)
- int c;
- {
- return (isalnum(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItAlpha%
-
- Determines whether a character is alphabetic. This function returns a
- non-zero value if the integer value represents an alphabetic ASCII
- character or a zero if the value does not. The alphabetic characters are
- in the ranges A through Z and a through z.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItAlpha% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItAlpha%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitalpha (c)
- int c;
- {
- return (isalpha(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItAscii%
-
- Determines whether a character is standard ASCII. This function returns a
- non-zero value if the integer value represents an ASCII character or a
- zero if the value does not. The ASCII character values are in the range 0
- through 127.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItAscii% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItAscii%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitascii (c)
- int c;
- {
- return (isascii(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItCntrl%
-
- Determines whether a character is a control character. This function
- returns a non-zero value if the integer value represents a control
- character or a zero if the value does not. The control characters are in
- the range 0 through 31, and 127.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItCntrl% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItCntrl%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitcntrl (c)
- int c;
- {
- return (iscntrl(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItDigit%
-
- Determines whether a character is a numeric digit. This function returns a
- non-zero value if the integer value represents a decimal digit or a zero
- if the value does not. The digit characters are in the range 0 through 9.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItDigit% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- ──────────────────────────────────────────────────────────────────────────
-
- * EXAMPLE OF USE: result% = IsItDigit%(c%)
-
- * PARAMETERS: c% ASCII character code
-
- * VARIABLES: (none)
-
- * MODULE LEVEL
-
- * DECLARATIONS: #include <ctype.h> */
-
-
-
-
-
- int isitdigit (c)
-
- int c;
-
- {
-
- return (isdigit(c));
-
- }
-
-
- Function: IsItGraph%
-
- Determines whether a character is graphic. This function returns a
- non-zero value if the integer value represents a printable character, not
- including the space character. These character values are in the range 33
- through 126.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItGraph% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItGraph%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitgraph (c)
- int c;
- {
- return (isgraph(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItLower%
-
- Determines whether a character is lowercase. This function returns a
- non-zero value if the integer value represents a lowercase character or a
- zero if the value does not. The lowercase characters are in the range a
- through z.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItLower% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItLower%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitlower (c)
- int c;
- {
- return (islower(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItPrint%
-
- Determines whether a character is printable. This function returns a
- non-zero value if the integer value represents a printable character or a
- zero if the value does not. The printable characters are in the range 32
- through 126.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItPrint% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItPrint%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitprint (c)
- int c;
- {
- return (isprint(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItPunct%
-
- Determines whether a character is punctuation. This function returns a
- non-zero value if the integer value represents a punctuation character or
- a zero if the value does not. The punctuation characters are in the ranges
- 33 through 47, 59 through 64, 91 through 96, or 123 through 126.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItPunct% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItPunct%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitpunct (c)
- int c;
- {
- return (ispunct(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItSpace%
-
- Determines whether a character is white space. This function returns a
- non-zero value if the integer value represents a white-space character or
- a zero if the value does not. The white-space character values are in the
- range 9 through 13, and 32.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItSpace% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItSpace%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitspace (c)
- int c;
- {
- return (isspace(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItUpper%
-
- Determines whether a character is uppercase. This function returns a
- non-zero value if the integer value represents an uppercase character or a
- zero if the value does not. The uppercase characters are in the range A
- through Z.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItUpper% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItUpper%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
- int isitupper (c)
- int c;
- {
- return (isupper(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: IsItXDigit%
-
- Determines whether a character is a hexadecimal digit. This function
- returns a non-zero value if the integer value represents a hexadecimal
- character or a zero if the value does not. The hexadecimal characters are
- in the ranges 0 through 9, a through f, or A through F.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: IsItXDigit% **
- ** Type: Function **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * EXAMPLE OF USE: result% = IsItXDigit%(c%)
- * PARAMETERS: c% ASCII character code
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <ctype.h> */
-
-
- int isitxdigit (c)
- int c;
- {
- return (isxdigit(c));
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MovBytes
-
- Calls the QuickC movedata function to quickly copy a block of bytes from
- any address in memory to any other.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: MovBytes **
- ** Type: Subprogram **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Moves bytes from a source segment and offset
- * location in memory to a destination segment and
- * offset location.
- *
- * EXAMPLE OF USE: MovBytes sseg%, soff%, dseg%, doff%, nbytes%
- * PARAMETERS: sseg% Source segment address of bytes to be moved
- * soff% Source offset address of bytes to be moved
- * dseg% Destination segment address of bytes to be m
- * doff% Destination offset address of bytes to be mo
- * nbytes% Number of bytes to be moved
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <memory.h> */
-
-
- void movbytes (srcseg, srcoff, destseg, destoff, nbytes)
- unsigned int *srcseg, *srcoff, *destseg, *destoff, *nbytes;
- {
- movedata(*srcseg, *srcoff, *destseg, *destoff, *nbytes);
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: MovWords
-
- Moves a block of words from any memory location to any other. This
- subprogram calls the QuickC movedata function to quickly copy a block of
- words from any address in memory to any other.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: MovWords **
- ** Type: Subprogram **
- ** Module: CTOOLS1.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Moves words from a source segment and offset
- * location in memory to a destination segment and
- * offset location.
- *
- * EXAMPLE OF USE: MovWords sseg%, soff%, dseg%, doff%, nbytes%
- * PARAMETERS: sseg% Source segment address of words to be moved
- * soff% Source offset address of words to be moved
- * dseg% Destination segment address of words to be mo
- * doff% Destination offset address of words to be mov
- * nwords% Number of words to be moved
- * VARIABLES: (none)
- * MODULE LEVEL
- * DECLARATIONS: #include <memory.h> */
-
-
- void movwords (srcseg, srcoff, destseg, destoff, nwords)
- unsigned int *srcseg, *srcoff, *destseg, *destoff, *nwords;
- {
- unsigned int nbytes;
-
- nbytes = *nwords + *nwords;
- movedata(*srcseg, *srcoff, *destseg, *destoff, nbytes);
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- CDEMO2.BAS AND CTOOLS2.C
-
- The CDEMO2.BAS program is a QuickBASIC program that demonstrates the
- proper declaration and calling of the QuickC routines presented in the
- CTOOLS2.C toolbox.
-
- The MenuString% function creates a horizontal bar menu, similar to the
- menu line at the top of the display in the QuickBASIC environment. The
- function call returns the number of the word selected. You can place the
- menu bar anywhere on the screen, and it can contain any number of one-word
- choices. The first letter of each word must be uppercase, and no more than
- two words can have the same first letter.
-
- The BitShiftLeft% and BitShiftRight% functions let you shift all the
- bits in a string of bytes one position to the left or right. Each function
- returns the bit shifted off the end of the string and shifts in a zero at
- the other end.
-
- The NumberOfBits& function returns the number of bits in all the bytes of
- a string. You could do this by using the bit-shifting functions and adding
- up the returned values, but the NumberOfBits& function is much faster.
- The string contents are unchanged by the function.
-
- The PackWord and UnPackWord subprograms let you pack and unpack two byte
- values (integers in the range 0 through 255) into an integer variable.
- This can be accomplished using the QuickBASIC math functions (although it
- gets complicated when dealing with negative numbers), but QuickC has
- features ideal for performing these types of data manipulations. By
- declaring a union of a two-byte structure with an integer, the bytes can
- simply be moved into place instead of calculated.
-
- The TextGet and TextPut subprograms let you quickly save and restore
- rectangular areas of the text-mode screen. These routines are similar in
- concept to the QuickBASIC GET and PUT statements that save and restore
- rectangular areas of graphics-mode screens. Unlike the GET and PUT
- statements, though, the rectangular area restored can be of a different
- shape than the area that was saved. The total number of bytes must be
- identical, but the width and height of the area can differ. The program
- module first prints a line of text that is saved into a string using
- TextGet and is then restored in a vertical (one column wide) rectangular
- area.
-
- Name Type Description
- ──────────────────────────────────────────────────────────────────────────
- CDEMO2.BAS QuickBASIC program module
- CTOOLS2.C C-language toolbox containing
- functions/subprograms
- BitShiftLeft% Func Shifts all bits in a string left one bit
- BitShiftRight% Func Shifts all bits in a string right one bit
- MenuString% Func Bar menu and user response function
- NumberOfBits& Func Determines number of 1 bits in a string
- PackWord Sub Packs two bytes into an integer value
- TextGet Sub Saves characters and attributes from area
- of screen
- TextPut Sub Restores text from TextGet to screen
- UnPackWord Sub Unpacks values from high and low bytes
- ──────────────────────────────────────────────────────────────────────────
-
-
- Program Module: CDEMO2
-
- ──────────────────────────────────────────────────────────────────────────
- ' ************************************************
- ' ** Name: CDEMO2 **
- ' ** Type: Program **
- ' ** Module: CDEMO2.BAS **
- ' ** Language: Microsoft QuickBASIC 4.00 **
- ' ************************************************
- '
- ' USAGE: No command line parameters
- ' REQUIREMENTS: CGA
- ' MIXED.QLB/.LIB
- ' .MAK FILE: (none)
- ' PARAMETERS: (none)
- ' VARIABLES: m$ Menu string
- ' word% Integer to be packed with two bytes
- ' hi% Most significant byte unpacked from an
- ' integer
- ' lo% Least significant byte unpacked from an
- ' integer
- ' a$ Workspace for TextGet and TextPut
- ' b$ Workspace for TextGet and TextPut
- ' n% Timing constant for TextPut demonstratio
- ' row% Row location to put small "window" using
- ' TextPut
- ' col% Column location to put small "window" us
- ' TextPut
- ' t0 Timer variable
- ' x$ String variable for bit shifting
- ' i% Looping index
-
- ' Functions
- DECLARE FUNCTION MenuString% CDECL (row%, col%, a$)
- DECLARE FUNCTION BitShiftleft% CDECL (a$)
- DECLARE FUNCTION BitShiftRight% CDECL (a$)
- DECLARE FUNCTION NumberOfBits& CDECL (a$)
-
- ' Subprograms
- DECLARE SUB PackWord CDECL (word%, hi%, lo%)
- DECLARE SUB UnPackWord CDECL (word%, hi%, lo%)
- DECLARE SUB TextGet CDECL (r1%, c1%, r2%, c2%, a$)
- DECLARE SUB TextPut CDECL (r1%, c1%, r2%, c2%, a$)
-
- ' Build menu string
- m$ = "Packword Unpackword Textget Textput "
- m$ = m$ + "Bitshiftleft Bitshiftright Numberofbits Quit"
-
- ' Let user repeatedly select the demonstrations
- DO
- COLOR 15, 1
- CLS
- PRINT
- PRINT
- PRINT "MenuString function..."
- PRINT
- PRINT "Select one of the CTOOLS2 demonstrations by ";
- PRINT "pressing the Left arrow,"
- PRINT "Right arrow, first letter of the choice, or Enter keys."
-
- ' Use MenuString to choose demonstrations
- SELECT CASE MenuString%(1, 1, m$)
-
- ' PackWord demonstration
- CASE 1
-
- CLS
- PRINT "PackWord word%, 255, 255 ... word% = ";
- PackWord word%, 255, 255
- PRINT word%
- PRINT "PackWord word%, 0, 1 ... word% = ";
- PackWord word%, 0, 1
- PRINT word%
- PRINT "PackWord word%, 1, 0 ... word% = ";
- PackWord word%, 1, 0
- PRINT word%
-
- PRINT
- PRINT "Press any key to continue..."
-
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' UnPackWord demonstration
- CASE 2
-
- CLS
- PRINT "UnPackWord -1, hi%, lo% ... hi%, lo% =";
- UnPackWord -1, hi%, lo%
- PRINT hi%; lo%
- PRINT "UnPackWord 1, hi%, lo% ... hi%, lo% =";
- UnPackWord 1, hi%, lo%
- PRINT hi%; lo%
- PRINT "UnPackWord 256, hi%, lo% ... hi%, lo% =";
- UnPackWord 256, hi%, lo%
- PRINT hi%; lo%
-
- PRINT
- PRINT "Press any key to continue..."
-
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' TextGet and TextPut demonstration
- CASE 3, 4
-
- ' TextGet a line of text
- CLS
- PRINT "A Vertical Message"
- a$ = SPACE$(36)
- TextGet 1, 1, 1, 18, a$
-
- ' TextPut it back, but stretch it vertically
- TextPut 6, 1, 23, 1, a$
-
- ' Now just a normal line of text at top
- LOCATE 1, 1
- PRINT "TextGet and TextPut - Press any key to stop"
-
- ' Create first of two colorful text patterns
- COLOR 14, 4
- LOCATE 13, 13, 0
- PRINT CHR$(201); CHR$(205); CHR$(209); CHR$(205); CHR$(187)
- LOCATE 14, 13, 0
- PRINT CHR$(199); CHR$(196); CHR$(197); CHR$(196); CHR$(182)
- LOCATE 15, 13, 0
- PRINT CHR$(200); CHR$(205); CHR$(207); CHR$(205); CHR$(188)
- a$ = SPACE$(30)
- TextGet 13, 13, 15, 17, a$
-
- ' Create second of two colorful text patterns
- COLOR 10, 1
- LOCATE 13, 13, 0
- PRINT CHR$(218); CHR$(196); CHR$(210); CHR$(196); CHR$(191)
- LOCATE 14, 13, 0
- PRINT CHR$(198); CHR$(205); CHR$(206); CHR$(205); CHR$(181)
- LOCATE 15, 13, 0
- PRINT CHR$(192); CHR$(196); CHR$(208); CHR$(196); CHR$(217)
- b$ = SPACE$(30)
- TextGet 13, 13, 15, 17, b$
-
- ' Randomly pop up little "windows"
- n% = 0
- DO
- row% = INT(RND * 21 + 3)
- col% = INT(RND * 73 + 4)
- TextPut row%, col%, row% + 2, col% + 4, a$
- row% = INT(RND * 21 + 3)
- col% = INT(RND * 73 + 4)
- TextPut row%, col%, row% + 2, col% + 4, b$
- IF n% < 10 THEN
- n% = n% + 1
- t0 = TIMER
- DO
- LOOP UNTIL TIMER > t0 + (10 - n%) / 10
- END IF
- LOOP UNTIL INKEY$ <> ""
-
- ' BitShiftLeft demonstration
- CASE 5
-
- CLS
- x$ = "This string will be shifted left 8 bits"
- PRINT x$
- FOR i% = 1 TO 8
- PRINT "bit ="; BitShiftleft%(x$)
- NEXT i%
- PRINT x$
-
- PRINT
- PRINT "Press any key to continue..."
-
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' BitShiftRight demonstration
- CASE 6
-
- CLS
- x$ = "This string will be shifted right 8 bits"
- PRINT x$
- FOR i% = 1 TO 8
- PRINT "bit ="; BitShiftRight%(x$)
- NEXT i%
- PRINT x$
-
- PRINT
- PRINT "Press any key to continue..."
-
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' BitShiftRight demonstration
- CASE 7
-
- CLS
- x$ = "The number of bits in this string is ..."
- PRINT x$
- PRINT NumberOfBits&(x$)
-
- PRINT
- PRINT "Press any key to continue..."
-
- DO
- LOOP UNTIL INKEY$ <> ""
-
- ' Must be time to quit
- CASE ELSE
- COLOR 7, 0
- CLS
- END
- END SELECT
- LOOP
- ──────────────────────────────────────────────────────────────────────────
-
-
- Toolbox: CTOOLS2.C
-
- The CTOOLS2.C toolbox provides a collection of functions and subprograms
- that perform tasks that QuickC is well suited for.
-
- You must enter the following block of lines into the first lines of the
- CTOOLS2.C source-code file, immediately before the functions and
- subprograms. Note that the definition for VIDEO_START should be changed to
- 0xb0000000 for monochrome operation.
-
-
- #include <ctype.h>
- #include <conio.h>
-
- #define VIDEO_START 0xb8000000
-
- #define BLACK_ON_CYAN 48
- #define RED_ON_CYAN 52
- #define BRIGHT_WHITE_ON_RED 79
-
- #define ENTER 13
- #define RIGHT_ARROW 77
- #define LEFT_ARROW 75
-
- /* Definition of the QuickBASIC string descriptor structure */
- struct bas_str
- {
- int sd_len;
- char *sd_addr;
- };
-
-
- Function: BitShiftLeft%
-
- Shifts all bits in a QuickBASIC string variable to the left one bit
- position. The number of bits in a string is eight times the length of the
- string. The function returns the leftmost bit of the first character of
- the string.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: BitShiftLeft% **
- ** Type: Function **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Shifts all bits in a QuickBASIC string one bit
- * to the left. The leftmost bit is returned, and
- * the rightmost bit is set to zero.
- *
- * EXAMPLE OF USE: bit% = BitShiftLeft%(bit$)
- * PARAMETERS: bit$ String containing a bit pattern
- * VARIABLES: len Length of the string (number of bytes)
- * str Pointer to string contents
- * i Looping index to each byte of the string
- * carry Bit carried over from byte to byte
- * the_byte Working copy of each byte of the string
- *
- * Definition of the QuickBASIC string descriptor structure
- * struct bas_str
- * {
- * int sd_len;
- * char *sd_addr;
- * }; */
-
-
- int bitshiftleft (basic_string)
- struct bas_str *basic_string;
- {
- int len = basic_string->sd_len;
- unsigned char *str = basic_string->sd_addr;
- int i, carry;
- unsigned int the_byte;
-
- for (i=len-1, carry=0; i>=0; i--)
- {
- the_byte = *(str + i);
- *(str + i) = (the_byte << 1) + carry;
- carry = the_byte >> 7;
- }
-
- return (carry);
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: BitShiftRight%
-
- Shifts all bits in a QuickBASIC string variable to the right one bit
- position. The number of bits in a string is eight times the length of the
- string. The function returns the rightmost bit of the last character of
- the string.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: BitShiftRight% **
- ** Type: Function **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Shifts all bits in a QuickBASIC string one bit to
- * the right. The rightmost bit is returned, and the
- * leftmost bit is set to zero.
- *
- * EXAMPLE OF USE: bit% = BitShiftRight%(bit$)
- * PARAMETERS: bit$ String containing a bit pattern
- * VARIABLES: len Length of the string (number of bytes)
- * str Pointer to string contents
- * i Looping index to each byte of the string
- * carry Bit carried over from byte to byte
- * the_byte Working copy of each byte of the string
- *
- * Definition of the QuickBASIC string descriptor structure
- * struct bas_str
- * {
- * int sd_len;
- * char *sd_addr;
- * }; */
-
- int bitshiftright (basic_string)
- struct bas_str *basic_string;
- {
- int len = basic_string->sd_len;
- unsigned char *str = basic_string->sd_addr;
- int i, carry;
- unsigned int the_byte;
-
- for (i=0, carry=0; i<len; i++)
- {
- the_byte = *(str + i);
- *(str + i) = (the_byte >> 1) + carry;
- carry = (the_byte & 1) << 7;
- }
-
- if (carry)
- return(1);
- else
- return(0);
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: MenuString%
-
- Creates a horizontal menu bar, highlights the one-word choices, and
- returns the number of the choice selected when the Enter key is pressed.
- The menu is highlighted using the same color scheme as the main pull-down
- menu bars of both the QuickBASIC and QuickC environments.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: MenuString% **
- ** Type: Function **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Displays a horizontal bar menu and waits for a
- * response from the user. Returns the number of
- * the word selected from the string.
- * EXAMPLE OF USE: choice% = MenuString%(row%, col%, menu$)
- * PARAMETERS: row% Row location to display the menu string
- * col% Column location to display the menu string
- * menu$ String containing list of words representing
- * choices
- * VARIABLES: len Length of the menu string
- * str Pointer to string contents
- * vidptr Pointer to video memory
- * attribute Index into string
- * character Character from keyboard press
- * both Combination of a character and its attribute
- * i Looping index
- * j Looping index
- * k Looping index
- * c Looping index
- * choice Menu selection number
- * wordnum Sequential count of each word in the menu str
- * refresh Signals to redraw the menu string
- * #include <ctype.h>
- * #include <conio.h>
- * #define VIDEO_START 0xb8000000
- * #define BLACK_ON_CYAN 48
- * #define RED_ON_CYAN 52
- * #define BRIGHT_WHITE_ON_RED 79
- * #define ENTER 13
- * #define RIGHT_ARROW 77
- * #define LEFT_ARROW 75
- *
- * Definition of the QuickBASIC string descriptor structure
- * struct bas_str
- * {
- * int sd_len;
- * char *sd_addr;
- * }; */
-
-
- int menustring (row, col, basic_string)
- int *row, *col;
- struct bas_str *basic_string;
- {
- int len;
- char * str;
- int far * vidptr;
- int attribute, character, both;
- int i, j, k, c;
- int choice, wordnum;
- int refresh;
- void packword();
-
- /* Initialize variables */
- len = basic_string->sd_len;
- str = basic_string->sd_addr;
- vidptr = (int far *) VIDEO_START + (*row - 1) * 80 + (*col - 1);
- choice = 1;
- refresh = 1;
-
- /* Loop until return() statement */
- while (1)
- {
-
- /* Display the string only if refresh is non-zero */
- if (refresh)
- {
- refresh = 0;
-
- /* Loop through each character of the string */
- for (wordnum = 0, i=0; i<len; i++)
- {
-
- /* Set the character and default attribute */
- character = str[i];
- attribute = BLACK_ON_CYAN;
-
- /* Uppercase? */
- if (isupper(character))
- {
- wordnum++;
- attribute = RED_ON_CYAN;
- }
-
- /* In the middle of the current selection? */
- if (wordnum == choice && character != ' ')
- attribute = BRIGHT_WHITE_ON_RED;
-
- /* Move data to video */
- packword(&both, &attribute, &character);
- vidptr[i] = both;
- }
- }
-
- /* Check for any key presses */
- if (kbhit())
- {
-
- /* Get the key code and process it */
- switch (c = getch())
- {
-
- /* Return the choice when Enter is pressed */
- case ENTER:
- return (choice);
-
- /* Highlight next choice if Right arrow is pressed */
- case RIGHT_ARROW:
- if (choice < wordnum)
- {
- choice++;
- refresh = 1;
- }
- break;
-
- /* Highlight previous choice if Left arrow is pressed */
- case LEFT_ARROW:
- if (choice > 1)
- {
- choice--;
- refresh = 1;
- }
- break;
-
- /* Check for match on first character of each word */
- default:
- c = _toupper(c);
- for (k=0, j=0; j<len; j++)
- {
-
- /* Each choice starts at an uppercase char */
- if (isupper(str[j]))
- k++;
-
- /* Match if same char and not current choice */
- if (str[j] == c && k != choice)
- {
- choice = k;
- refresh = 1;
- break;
- }
- }
- break;
- }
- }
- }
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Function: NumberOfBits&
-
- Returns the number of bits in a string without altering its contents.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: NumberOfBits& **
- ** Type: Function **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Counts the 1 bits in a QuickBASIC string.
- *
- * EXAMPLE OF USE: count& = NumberOfBits&(a$)
- * PARAMETERS: a$ String containing bits to be counted
- * VARIABLES: len Length of the string
- * str Pointer to string contents
- * i Looping index to each byte
- * the_byte Working copy of each byte of the string
- * count Count of the bits
- *
- * Definition of the QuickBASIC string descriptor structure
- * struct bas_str
- * {
- * int sd_len;
- * char *sd_addr;
- * }; */
-
-
- long numberofbits (basic_string)
- struct bas_str *basic_string;
- {
- int len = basic_string->sd_len;
- unsigned char *str = basic_string->sd_addr;
- int i,the_byte;
- long count = 0;
-
- for (i=0; i<len; i++)
- {
- the_byte = *(str+i);
- while (the_byte)
- {
- count += (the_byte & 1);
- the_byte >>= 1;
- }
- }
- return (count);
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: PackWord
-
- Packs two bytes into an integer value. For example, the high and low (most
- significant and least significant) bytes of the integer value 258 are 1
- and 2. QuickBASIC can pack two values into an integer by multiplying the
- first value by 256 and adding the second. This works well for small byte
- values but becomes awkward when the high byte is 128 or greater. In such
- cases, the resulting integer is a negative number.
-
- PackWord uses the QuickC union and structure data definition features to
- pack the byte values using simple data moves in memory.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: PackWord **
- ** Type: Subprogram **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Packs two byte values into the high and low
- * bytes of an integer (word).
- *
- * EXAMPLE OF USE: PackWord hiloword%, hibyte%, lobyte%
- * PARAMETERS: hiloword% Integer word to pack the two bytes into
- * hibyte% Integer value of the most significant byte
- * lobyte% Integer value of the least significant byte
- * VARIABLES: both A union of a two-byte structure and an intege
- * variable */
-
-
- void packword (hiloword, hibyte, lobyte)
- int *hiloword, *hibyte, *lobyte;
- {
- union
- {
- struct
- {
- unsigned char lo;
- unsigned char hi;
- } bytes;
- int hilo;
- } both;
-
- both.bytes.hi = *hibyte;
- both.bytes.lo = *lobyte;
- *hiloword = both.hilo;
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: TextGet
-
- Copies a rectangular area of the text screen into a string variable. This
- is similar in concept to the graphics-oriented GET statement, except that
- this subprogram copies text-mode screen data. To redisplay the text
- anywhere on the screen, use the TextPut subprogram.
-
- The string variable must be exactly the right length for the amount of
- data to be copied, or the call will be ignored. There are two bytes of
- screen memory for each character displayed (the character and its color
- attribute), so the string must contain width * height * 2 bytes. For
- example, to save the area from row 3, column 4, to row 5, column 9, the
- string length must be 3 * 6 * 2, or 36 characters. The SPACE$ statement is
- ideal for preparing strings for this call. For example, a$ = SPACE$(36)
- makes the previous string the correct length.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: TextGet **
- ** Type: Subprogram **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Saves characters and attributes from a rectangular
- * area of the screen.
- *
- * EXAMPLE OF USE: TextGet r1%, c1%, r2%, c2%, a$
- * PARAMETERS: r1% Pointer to row at upper left corner
- * c1% Pointer to column at upper left corner
- * r2% Pointer to row at lower right corner
- * c2% Pointer to column at lower right corner
- * a$ String descriptor, where screen contents
- * will be stored
- * VARIABLES: len Length of string
- * str Pointer to string contents
- * video Pointer to video memory
- * i Index into string
- * row Looping index
- * col Looping index
- * #define VIDEO_START 0xb8000000
- *
- * Definition of the QuickBASIC string descriptor structure
- *
- * struct bas_str
- * {
- * int sd_len;
- * char *sd_addr;
- * }; */
-
-
- void textget (r1,c1,r2,c2,basic_string)
- int *r1,*c1,*r2,*c2;
- struct bas_str *basic_string;
- {
- int len;
- int * str;
- int far * video;
- int i,row,col;
-
- len = basic_string->sd_len;
- str = (int *) basic_string->sd_addr;
- video = (int far *) VIDEO_START;
-
- if (len == (*r2 - *r1 + 1) * (*c2 - *c1 + 1) * 2)
- for (row = *r1 - 1, i = 0; row < *r2; row++)
- for (col = *c1 - 1; col < *c2; col++)
- str[i++] = video[row * 80 + col];
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: TextPut
-
- Restores a rectangular area of a text screen from a string variable
- previously used to copy screen contents via the TextGet subprogram. This
- is similar to the graphics-oriented PUT statement, except that this
- subprogram copies text-mode screen data.
-
- The string variable must be exactly the right length for the amount of
- data to be copied onto the screen, or the call will be ignored. There are
- two bytes of screen memory for each character displayed (the character and
- its color attribute), so the string must contain width * height * 2 bytes.
- See the TextGet subprogram for more details on string length
- requirements.
-
- The shape of the restored area can differ from the original area as long
- as the total number of bytes is the same. For example, an area three
- characters wide by four characters high can be copied using TextGet and
- then placed back on the screen in an area two wide by six high. As long as
- the width times the height remains constant, TextPut will move the data
- onto the screen.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: TextPut **
- ** Type: Subprogram **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Restores characters and attributes to a rectangular
- * area of the screen.
- *
- * EXAMPLE OF USE: TextPut r1%, c1%, r2%, c2%, a$
- * PARAMETERS: r1% Pointer to row at upper left corner
- * c1% Pointer to column at upper left corner
- * r2% Pointer to row at lower right corner
- * c2% Pointer to column at lower right corner
- * a$ String descriptor where screen contents are s
- * VARIABLES: len Length of string
- * str Pointer to string contents
- * video Pointer to video memory
- * i Index into string
- * row Looping index
- * col Looping index
- * #define VIDEO_START 0xb8000000
- *
- * Definition of the QuickBASIC string descriptor structure
- * struct bas_str
- * {
- * int sd_len;
- * char *sd_addr;
- * }; */
-
-
- void textput (r1,c1,r2,c2,basic_string)
- int *r1,*c1,*r2,*c2;
- struct bas_str *basic_string;
- {
- int len;
- int * str;
- int far * video;
- int i,row,col;
-
- len = basic_string->sd_len;
- str = (int *) basic_string->sd_addr;
- video = (int far *) VIDEO_START;
-
- if (len == (*r2 - *r1 + 1) * (*c2 - *c1 + 1) * 2)
- for (row = *r1 - 1, i = 0; row < *r2; row++)
- for (col = *c1 - 1; col < *c2; col++)
- video[row * 80 + col] = str[i++];
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
- Subprogram: UnPackWord
-
- Extracts two bytes from a QuickBASIC integer value. For example, the high
- and low (most significant and least significant) bytes of the integer
- value 258 are 1 and 2, and the two bytes of -1 are 255 and 255.
-
- CDEMO2.BAS AND CTOOLS2.C
-
- This subprogram uses the QuickC union and structure data definition
- features to unpack the byte values using simple data moves in memory.
-
- ──────────────────────────────────────────────────────────────────────────
- /***********************************************
- ** Name: UnPackWord **
- ** Type: Subprogram **
- ** Module: CTOOLS2.C **
- ** Language: Microsoft QuickC/QuickBASIC **
- ************************************************
- *
- * Unpacks two byte values from the high and low
- * bytes of an integer (word).
- *
- * EXAMPLE OF USE: UnPackWord hiloword%, hibyte%, lobyte%
- * PARAMETERS: hiloword% Integer word containing the two bytes
- * hibyte% Integer value of the most significant byte
- * lobyte% Integer value of the least significant byte
- * VARIABLES: both A union of a two-byte structure and an intege
- * variable */
-
-
- void unpackword (hiloword, hibyte, lobyte)
- int *hiloword, *hibyte, *lobyte;
- {
- union
- {
- struct
- {
- unsigned char lo;
- unsigned char hi;
- } bytes;
- int hilo;
- } both;
-
- both.hilo = *hiloword;
- *hibyte = both.bytes.hi;
- *lobyte = both.bytes.lo;
- }
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PART 4 APPENDIXES
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix A Requirements for Running Toolboxes/Programs
-
- In the following table, the Usage line assumes execution from the system
- prompt after you compile the .BAS program. From QuickBASIC, modify
- COMMAND$ and enter any parameters before selecting Run and Start.
-
- CGA─Color Graphics Adapter/Monitor
-
- EGA─Enhanced Graphics Adapter/Monitor
-
- VGA─Video Graphics Adapter/Monitor
-
- Sub─Subprogram
-
- Func─Function
-
- ╓┌─┌────────────────────┌────────────────────────────────────────────────────╖
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- ATTRIB.BAS Screen/Text Attribute Display
- Utility Program: 1 Sub
- Usage: ATTRIB
- Requirements: CGA
- BIN2HEX.BAS Binary-to-Hex Conversion
- Utility Program
- Usage: BIN2HEX inFileName.ext outFileName.ext
- .MAK File: BIN2HEX.BAS
- PARSE.BAS
- BIOSCALL.BAS ROM BIOS Interrupt Calls
- Toolbox: 6 Sub with Demo Module
- Usage: BIOSCALL
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- Usage: BIOSCALL
- Requirements: MIXED.QLB/.LIB
- BITS.BAS Bit Manipulation
- Toolbox: 2 Func/2 Sub with Demo Module
- Usage: BITS
- CALENDAR.BAS Calendar and Time Routines
- Toolbox: 19 Func/1 Sub with Demo Module
- Usage: CALENDAR
- CARTESIA.BAS Cartesian Coordinate Routines
- Toolbox: 2 Func/2 Sub with Demo Module
- Usage: CARTESIA
- CDEMO1.BAS Demo 1 of C-Language Routines
- Program
- Usage: CDEMO1
- Requirements: CGA
- MIXED.QLB/.LIB
- Microsoft QuickC
- CDEMO2.BAS Demo 2 of C-Language Routines
- Program
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- Program
- Usage: CDEMO2
- Requirements: CGA
- MIXED.QLB/.LIB
- Microsoft QuickC
- CIPHER.BAS Cipher File Security
- Utility Program: 1 Func/1 Sub
- Usage: CIPHER filename.ext key or CIPHER /NEWKEY
- .MAK File: CIPHER.BAS
- RANDOMS.BAS
- COLORS.BAS VGA Color Selection
- Utility Program: 1 Func
- Usage: COLORS
- Requirements: VGA or MCGA
- MIXED.QLB/.LIB
- Mouse
- .MAK File: COLORS.BAS
- BITS.BAS
- MOUSSUBS.BAS
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- MOUSSUBS.BAS
- COMPLEX.BAS Complex Numbers
- Toolbox: 12 Sub with Demo Module
- Usage: COMPLEX
- .MAK File: COMPLEX.BAS
- CARTESIA.BAS
- CTOOLS1.C C Functions──Characters
- C-Language Toolbox: 12 Func/2 Sub
- Usage: Place in MIXED.QLB and MIXED.LIB
- after compiling into object files and then run
- CDEMO1.BAS from QuickBASIC
- CTOOLS2.C C Functions──Text
- C-Language Toolbox: 4 Func/4 Sub
- Usage: Place in MIXED.QLB and MIXED.LIB
- after compiling into object files and then run
- CDEMO2.BAS from QuickBASIC
- DOLLARS.BAS Dollar Formatting
- Toolbox: 3 Func with Demo Module
- Usage: DOLLARS
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- Usage: DOLLARS
- DOSCALLS.BAS MS-DOS System Calls
- Toolbox: 6 Func/9 Sub with Demo Module
- Usage: DOSCALLS
- Requirements: MIXED.QLB/.LIB
- MS-DOS 3.3 or later
- EDIT.BAS Editing
- Toolbox: 5 Sub with Demo Module
- Usage: EDIT
- .MAK File: EDIT.BAS
- KEYS.BAS
- ERROR.BAS Error Message
- Toolbox: 1 Sub with Demo Module
- Usage: ERROR
- FIGETPUT.BAS FILEGET and FILEPUT Routines
- Toolbox: 1 Func/1 Sub with Demo Module
- Usage: FIGETPUT
- FILEINFO.BAS Directory/File Listing Information
- Toolbox: 3 Sub with Demo Module
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- Toolbox: 3 Sub with Demo Module
- Usage: FILEINFO
- Requirements: MIXED.QLB/.LIB
- FRACTION.BAS Fractions
- Toolbox: 3 Func/7 Sub with Demo Module
- Usage: FRACTION
- GAMES.BAS Games
- Toolbox: 4 Func/2 Sub with Demo Module
- Usage: GAMES
- Requirements: CGA
- HEX2BIN.BAS Hex-to-Binary Conversion
- Utility Program
- Usage: HEX2BIN inFileName.ext outFileName.ext
- .MAK File: HEX2BIN.BAS
- PARSE.BAS
- STRINGS.BAS
- JUSTIFY.BAS Paragraph Justification
- Toolbox: 1 Sub with Demo Module
- Usage: JUSTIFY
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- Usage: JUSTIFY
- .MAK File: JUSTIFY.BAS
- EDIT.BAS
- KEYS.BAS
- PARSE.BAS
- KEYS.BAS Enhanced Keyboard Input Functions
- Toolbox: 2 Func with Demo Module
- Usage: KEYS
- LOOK.BAS Text File Display Utility
- Utility Program
- Usage: LOOK filename.ext
- .MAK File: LOOK.BAS
- KEYS.BAS
- MONTH.BAS Three-Month Calendar
- Utility Program
- Usage: MONTH
- .MAK File: MONTH.BAS
- CALENDAR.BAS
- MOUSGCRS.BAS Custom Graphics Mouse Cursors
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- MOUSGCRS.BAS Custom Graphics Mouse Cursors
- Utility Program
- Usage: MOUSGCRS
- Requirements: CGA
- MIXED.QLB/.LIB
- Mouse
- .MAK File: MOUSGCRS.BAS
- BITS.BAS
- MOUSSUBS.BAS
- MOUSSUBS.BAS Mouse Subroutines
- Toolbox: 26 Subs with Demo Module
- Usage: MOUSSUBS
- Requirements: CGA
- MIXED.QLB/.LIB
- Mouse
- .MAK File: MOUSSUBS.BAS
- BITS.BAS
- MOUSTCRS.BAS Text-Mode Mouse Cursor
- Utility Program
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- Utility Program
- Usage: MOUSTCRS
- Requirements: MIXED.QLB/.LIB
- Mouse
- .MAK File: MOUSTCRS.BAS
- MOUSSUBS.BAS
- BITS.BAS
- ATTRIB.BAS
- OBJECT.BAS Interactive Graphics Creation
- Toolbox and Utility Program: 1 Sub
- Usage: OBJECT
- Requirements: CGA
- .MAK File: OBJECT.BAS
- KEYS.BAS
- EDIT.BAS
- PARSE.BAS Command Line Parsing
- Toolbox: 2 Subs with Demo Module
- Usage: PARSE
- PROBSTAT.BAS Probability and Statistical Routines
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- PROBSTAT.BAS Probability and Statistical Routines
- Toolbox: 7 Func with Demo Module
- Usage: PROBSTAT
- QBFMT.BAS Formatting Utility
- Utility Program: 3 Subs
- Usage: QBFMT filename [indention]
- .MAK File: QBFMT.BAS
- PARSE.BAS
- STRINGS.BAS
- QBTREE.BAS Directory/Subdirectory/Files Listing
- Utility Program
- Usage: QBTREE [path]
- Requirements: MIXED.QLB/.LIB
- .MAK File: QBTREE.BAS
- FILEINFO.BAS
- QCAL.BAS Command Line Scientific Calculator
- Utility Program: 1 Func/3 Subs
- Usage: QCAL [number] [function] [...]
- .MAK File: QCAL.BAS
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- .MAK File: QCAL.BAS
- QCALMATH.BAS
- QCALMATH.BAS Math Functions
- Toolbox: 31 Func/2 Sub
- Usage: loaded by the QCAL program
- RANDOMS.BAS Pseudorandom Numbers
- Toolbox: 6 Func/1 Sub with Demo Module
- Usage: RANDOMS
- STDOUT.BAS MS-DOS Standard (ANSI) Output
- Toolbox: 12 Sub with Demo Module
- Usage: STDOUT
- Requirements: MIXED.QLB/.LIB
- ANSI.SYS
- STRINGS.BAS String Manipulation
- Toolbox: 18 Func/1 Sub with Demo Module
- Usage: STRINGS
- TRIANGLE.BAS Triangles
- Toolbox: 3 Func/1 Sub with Demo Module
- Usage: TRIANGLE
- Name Description
- ──────────────────────────────────────────────────────────────────────────
- Usage: TRIANGLE
- Requirements: CGA
- .MAK File: TRIANGLE.BAS
- QCALMATH.BAS
- WINDOWS.BAS Windows
- Toolbox: 2 Sub with Demo Module
- Usage: WINDOWS
- Requirements: MIXED.QLB/.LIB
- Mouse (optional)
- .MAK File: WINDOWS.BAS
- BIOSCALL.BAS
- BITS.BAS
- KEYS.BAS
- MOUSSUBS.BAS
- WORDCOUN.BAS Word Counting
- Toolbox: 1 Func with Demo Module
- Usage: WORDCOUN filename
- ──────────────────────────────────────────────────────────────────────────
-
- Name Description
- ──────────────────────────────────────────────────────────────────────────
-
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix B Functions-to-Modules Cross Reference
-
- ╓┌─┌───────────────────┌─────────────┌───────────────────────────────────────╖
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- AbsoluteX# QCALMATH Absolute value of a number
- Add# QCALMATH Sum of two numbers
- Angle! CARTESIA Angle between X axis and line to x, y
- point
- ArcCosine# QCALMATH Arc cosine function of a number
- ArcHypCosine# QCALMATH Inverse hyperbolic cosine of a number
- ArcHypSine# QCALMATH Inverse hyperbolic sine of a number
- ArcHypTangent# QCALMATH Inverse hyperbolic tangent of a number
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- ArcHypTangent# QCALMATH Inverse hyperbolic tangent of a number
- ArcSine# QCALMATH Inverse sine of a number
- ArcTangent# QCALMATH Inverse tangent of a number
- ArithmeticMean# PROBSTAT Arithmetic mean of an array of numbers
- Ascii2Ebcdic$ STRINGS Converts string from ASCII to EBCDIC
- BestMatch$ STRINGS Returns best match to input string
- Bin2BinStr$ BITS Integer to 16-character binary string
- BinStr2Bin% BITS 16-character binary string to integer
- BitShiftLeft% CTOOLS2 Shifts all bits in a string left one bit
- BitShiftRight% CTOOLS2 Shifts all bits in a string right one
- 1 through 52
- BufferedKeyInput$ DOSCALLS numberstring of specified length
- Card$ GAMES Returns name of card given a number from
- Ceil# QCALMATH Smallest whole number greater than a
- Center$ STRINGS Centers string by padding with spaces
- ChangeSign# QCALMATH Reverses sign of a number
- CheckDate% CALENDAR Validates date with return of TRUE/FALSE
- Collision% GAMES Returns TRUE or FALSE collision
- condition
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- condition
- Combinations# PROBSTAT Combinations of n items, r at a time
- Comma$ DOLLARS Double-precision with commas inserted
- Cosine# QCALMATH Cosine of a number
- Date2Day% CALENDAR Day of month number from date string
- Date2Julian& CALENDAR Julian day number for a given date
- Date2Month% CALENDAR Month number from date string
- Date2Year% CALENDAR Year number from date string
- DayOfTheCentury& CALENDAR Day of the given century
- DayOfTheWeek$ CALENDAR Name of day of the week for given date
- DayOfTheYear% CALENDAR Day of the year (1 through 366) for
- given date
- DaysBetweenDates& CALENDAR Number of days between two dates
- Deg2Rad# TRIANGLE Converts degree angular units to radians
- Detab$ STRINGS Replaces tab characters with spaces
- Dice% GAMES Returns total showing for throwing n
- dice
- Divide# QCALMATH Result of dividing two numbers
- DollarString$ DOLLARS Dollar representation rounded with
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- DollarString$ DOLLARS Dollar representation rounded with
- commas
- DOSVersion! DOSCALLS Version number of MS-DOS returned
- Ebcdic2Ascii$ STRINGS Converts a string from EBCDIC to ASCII
- Entab$ STRINGS Replaces spaces with tab characters
- Exponential# QCALMATH Exponential function of a number
- Factorial# PROBSTAT Factorial of a number
- FileGet$ FIGETPUT Returns a string with contents of file
- FilterIn$ STRINGS Retains only specified characters in
- string
- FilterOut$ STRINGS Deletes specified characters from string
- Fraction2String$ FRACTION Converts type Fraction variable to a
- string
- FractionalPart# QCALMATH Fractional part of a number
- GeometricMean# PROBSTAT Geometric mean of an array of numbers
- GetDirectory$ DOSCALLS Path to disk directory specified
- GetDrive$ DOSCALLS Current drive string
- GetVerifyState% DOSCALLS Verify setting (state)
- GreatestComDiv& FRACTION seconds greatest common divisor
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- GreatestComDiv& FRACTION seconds greatest common divisor
- HarmonicMean# PROBSTAT Harmonic mean of an array of numbers
- HMS2Time$ CALENDAR Time string for given hour, minute, and
- HypCosine# QCALMATH Hyperbolic cosine of a number
- HypSine# QCALMATH Hyperbolic sine of a number
- HypTangent# QCALMATH Hyperbolic tangent of a number
- InKeyCode% KEYS Returns unique integer for any key
- pressed
- IntegerPart# QCALMATH Integer part of a number
- IsItAlnum% CTOOLS1 Alphanumeric character determination
- IsItAlpha% CTOOLS1 Alphabetic character determination
- IsItAscii% CTOOLS1 Standard ASCII character determination
- IsItCntrl% CTOOLS1 Control character determination
- IsItDigit% CTOOLS1 Decimal digit (0─9) determination
- IsItGraph% CTOOLS1 Graphics character determination
- IsItLower% CTOOLS1 Lowercase character determination
- IsItPrint% CTOOLS1 Printable character determination
- IsItPunct% CTOOLS1 Punctuation character determination
- IsItSpace% CTOOLS1 Space character determination
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- IsItSpace% CTOOLS1 Space character determination
- IsItUpper% CTOOLS1 Uppercase character determination
- IsItXDigit% CTOOLS1 Hexadecimal character determination
- Julian2Date$ CALENDAR Date string from given Julian day number
- KeyCode% KEYS Waits and returns integer value for key
- LeastComMul& FRACTION Returns least common multiple
- LogBase10# QCALMATH Log base 10 of a number
- LogBaseN# QCALMATH Log base N of a number
- LogE# QCALMATH Natural logarithm of a number
- Lpad$ STRINGS Returns left-justified input string
- LtrimSet$ STRINGS Deletes specified characters from left
- Magnitude! CARTESIA Distance from origin to x, y point
- MDY2Date$ CALENDAR Date string from given month, day, and
- year
- MenuString% CTOOLS2 Bar menu and user response function
- Modulus# QCALMATH Remainder of the division of two numbers
- MonthName$ CALENDAR Name of month for a given date
- Multiply# QCALMATH COMMAND$of two numbers
- NewWord$ CIPHER Creates pseudorandom new word
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- NewWord$ CIPHER Creates pseudorandom new word
- NextParameter$ QCAL Extracts number or command from
- NumberOfBits& CTOOLS2 Determines number of 1 bits in a string
- OneOverX# QCALMATH Result of dividing 1 by a number
- Ord% STRINGS Returns byte number for ANSI mnemonic
- Permutations# PROBSTAT Permutations of n items, r at a time
- QuadraticMean# PROBSTAT Quadratic mean of an array of numbers
- Rad2Deg# TRIANGLE from meanradian angular units to degrees
- Rand& RANDOMS Long integers
- RandExponential! RANDOMS Real value with exponential distribution
- RandFrac! RANDOMS deviationecision positive value < 1.0
- RandInteger% RANDOMS Integers within desired range
- RandNormal! RANDOMS Single-precision from mean and standard
- RandReal! RANDOMS Single-precision value in desired range
- Repeat$ STRINGS Combines multiple copies into one string
- Replace$ STRINGS Replaces specified characters in string
- Reverse$ STRINGS Reverses order of characters in a string
- ReverseCase$ STRINGS Reverses case for each charater in a
- string
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- string
- Round# DOLLARS Rounding at specified decimal place
- Rpad$ STRINGS Returns right-justified input string
- RtrimSet$ STRINGS Deletes specified characters from right
- Second2Date$ CALENDAR Seconds from last of 1979 to date given
- Second2Time$ CALENDAR Time of day from seconds since last of
- 1979
- Shade& COLORS Color value from given red, green, and
- blue
- Shuffle$ GAMES Randomizes character bytes in string
- Sign# QCALMATH Sign of a number
- Sine# QCALMATH Sine of a number
- SquareRoot# QCALMATH Square root of a number
- Subtract# QCALMATH Difference between two numbers
- Tangent# QCALMATH Tangent of a number
- Time2Hour% CALENDAR Hour number from time string
- Time2Minute% CALENDAR Minute number from time string
- Time2Second% CALENDAR Seconds number from time string
- TimeDate2Second& CALENDAR Seconds from last of 1979 from date/time
- Function Module Description
- ──────────────────────────────────────────────────────────────────────────
- TimeDate2Second& CALENDAR Seconds from last of 1979 from date/time
- Translate$ STRINGS Exchanges characters in string from
- table
- TranslateCountry$ DOSCALLS Translates string──current country
- setting
- TriangleArea# TRIANGLE Calculates area of triangle from three
- sides
- WordCount% WORDCOUN Returns number of words in a string
- Xsquared# QCALMATH Square of a number
- YRaisedToX# QCALMATH Number raised to the power of a second
- ──────────────────────────────────────────────────────────────────────────
-
-
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix C Subprograms-to-Modules Cross Reference
-
- ╓┌─┌────────────────────────┌───────────┌────────────────────────────────────╖
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- AssignKey STDOUT Reassigns a string to a key
- Attrib ATTRIB Table of color attributes (text mode)
- Attribute STDOUT Sets screen color (ANSI driver
- definition)
- BitGet BITS Value from any bit position in a
- string
- BitPut BITS translation tables at location in a
- string
- BuildAEStrings STRINGS Builds ASCII and EBCDIC character
- ClearLine STDOUT Clears line from cursor to end of
- line
- ClearScreen STDOUT Clears screen
- Complex2String COMPLEX String representation of a complex
- number
- ComplexAdd COMPLEX Adds two complex numbers
- ComplexDiv COMPLEX Divides two complex numbers
- ComplexExp COMPLEX Exponential function of a complex
- number
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- number
- ComplexLog COMPLEX numberl log of a complex number
- ComplexMul COMPLEX Multiplies two complex numbers
- ComplexPower COMPLEX Complex number raised to a complex
- ComplexReciprocal COMPLEX Reciprocal of a complex number
- ComplexRoot COMPLEX Complex root of a complex number
- ComplexSqr COMPLEX Square root of a complex number
- ComplexSub COMPLEX Subtracts two complex numbers
- CrLf STDOUT Sends carriage return and line feed
- Curschek MOUSSUBS Check-mark mouse cursor pattern mask
- Cursdflt MOUSSUBS Arrow mouse cursor pointing up and
- left
- Curshand MOUSSUBS Pointing hand mouse cursor
- Curshour MOUSSUBS Hourglass mouse cursor
- Cursjet MOUSSUBS Jet-shaped mouse cursor
- Cursleft MOUSSUBS Left arrow mouse cursor
- CursorDown STDOUT Moves cursor down specified number of
- lines
- CursorHome STDOUT Moves cursor to upper left corner of
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- CursorHome STDOUT Moves cursor to upper left corner of
- screen
- CursorLeft STDOUT Moves cursor left specified number of
- spaces
- CursorPosition STDOUT Moves cursor to specified row and
- column
- CursorRight STDOUT Moves cursor right specified number
- of spaces
- CursorUp STDOUT Moves cursor up specified number of
- lines
- Cursplus MOUSSUBS Plus sign mouse cursor
- Cursup MOUSSUBS Up arrow mouse cursor
- Cursx MOUSSUBS X-mark mouse cursor
- DisplayStack QCAL Displays final results of the program
- DrawBox EDIT Creates a double-lined box on the
- display
- Dup QCALMATH Duplicates top entry on the stack
- EditBox EDIT Allows editing in a boxed area of the
- screen
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- screen
- EditLine EDIT Allows editing of string at cursor
- position
- Equipment BIOSCALL Equipment/hardware information
- ErrorMessage ERROR Error message display
- FilePut FIGETPUT Writes contents of string into binary
- file
- FileRead LOOK Reads lines of ASCII files into an
- array
- FileTreeSearch QBTREE numbers defined by the boundsutine
- FillArray GAMES Fills an integer array with a
- FindFirstFile FILEINFO Finds first file that matches
- parameter
- FindNextFile FILEINFO Finds next file that matches
- parameter
- FormatTwo EDIT Splits string into two strings
- FractionAdd FRACTION Adds two fractions and reduces
- FractionDiv FRACTION Divides two fractions and reduces
- FractionMul FRACTION Multiplies two fractions and reduces
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- FractionMul FRACTION Multiplies two fractions and reduces
- FractionReduce FRACTION Reduces fraction to lowest terms
- FractionSub FRACTION Subtracts two fractions and reduces
- GetCountry DOSCALLS Current country setting
- GetDiskFreeSpace DOSCALLS Disk space format and usage for input
- drive
- GetFileAttributes DOSCALLS Attribute bits for given file
- GetFileData FILEINFO Extracts file directory information
- GetMediaDescriptor DOSCALLS Drive information for system
- GetShiftStates BIOSCALL Shift key states
- Indent QBFMT Performs line indention
- InsertCharacter EDIT Inserts a character
- Justify JUSTIFY Adjusts strings to specified widths
- MouseHide MOUSSUBS Turns off mouse visibility
- MouseInches MOUSSUBS parameters-to-cursor motion ratio
- MouseInstall MOUSSUBS Checks mouse availability; resets
- MouseLightPen MOUSSUBS Mouse emulation of a lightpen
- MouseMaskTranslate MOUSSUBS Translates pattern/hot spot to binary
- MouseMickey MOUSSUBS Returns motion increments since last
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- MouseMickey MOUSSUBS Returns motion increments since last
- call
- MouseNow MOUSSUBS Current state/location of the mouse
- MousePressLeft MOUSSUBS Location of mouse──left button press
- MousePressRight MOUSSUBS Location of mouse──right button press
- MousePut MOUSSUBS Moves cursor to the given position
- MouseRange MOUSSUBS Limits mouse cursor motion to
- rectangle
- MouseReleaseLeft MOUSSUBS Location of mouse──left button
- release
- MouseReleaseRight MOUSSUBS Location of mouse──right button
- release
- MouseSetGcursor MOUSSUBS Sets graphics-mode mouse cursor
- MouseShow MOUSSUBS Activates and displays mouse cursor
- MouseSoftCursor MOUSSUBS Sets text-mode attributes (mouse
- cursor)
- MouseWarp MOUSSUBS Sets mouse double-speed threshold
- MovBytes CTOOLS1 Moves bytes from one location to
- another
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- another
- MovWords CTOOLS1 Moves blocks of words in memory
- OneMonthCalendar CALENDAR One-month calendar for given date
- PackWord CTOOLS2 Packs two bytes into an integer value
- ParseLine PARSE Breaks a string into individual words
- ParseWord PARSE Parses and removes first word from
- string
- Pol2Rec CARTESIA Polar to Cartesian conversion
- PrintScreen BIOSCALL Screen dump
- Process QCAL Controls action for command line
- parameters
- ProcesX CIPHER Enciphers string by XORing bytes
- QcalHelp QCAL Provides a "Help" display for program
- RandShuffle RANDOMS Initializes random number generator
- ReBoot BIOSCALL System reboot
- Rec2Pol CARTESIA Cartesian to polar conversion
- SaveObject OBJECT Creates graphics "PUT" file source
- code
- Scroll BIOSCALL Moves text in designated area of
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- Scroll BIOSCALL Moves text in designated area of
- screen
- SetCode QBFMT Determines indention code by keyword
- SetDirectory DOSCALLS Sets current directory
- SetDrive DOSCALLS Sets current disk drive
- SetFileAttributes DOSCALLS Sets the attribute bits for a given
- file
- SetVerifyState DOSCALLS Sets or clears verify state (writing
- to file)
- ShuffleArray GAMES Randomizes integers in an array
- SplitFractions FRACTION Parses fraction problem string
- SplitUp QBFMT Splits line into major components
- StdOut STDOUT Sends a string to standard output
- channel
- String2Complex COMPLEX Converts string to complex variable
- String2Fraction FRACTION Converts a string to Fraction
- variable
- SwapXY QCALMATH of screen two entries on the stack
- TextGet CTOOLS2 Saves characters and attributes from
- Subprogram Module Description
- ──────────────────────────────────────────────────────────────────────────
- TextGet CTOOLS2 Saves characters and attributes from
- TextPut CTOOLS2 Restores text from TextGet to screen
- Triangle TRIANGLE Calculates sides and angles of
- triangle
- UnPackWord CTOOLS2 Unpacks values from high and low
- state
- VideoState BIOSCALL Mode, column, and page display of
- Windows WINDOWS Creates a pop-up window
- WindowsPop WINDOWS Removes last displayed window
- WriteToDevice DOSCALLS Outputs a string to a device
- ──────────────────────────────────────────────────────────────────────────
-
-
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix D Hexadecimal Format (.obj) Files
-
- Three assembly-language modules are discussed in this book. The suggested
- method for creating object-code files is to use the Microsoft Macro
- Assembler 5.0 on the source-code files. If necessary, however, you can
- process these files using the HEX2BIN.BAS program to create the desired
- object-code files. (See the HEX2BIN.BAS program for information about how
- to make the conversions.)
-
-
- MOUSE.HEX (MOUSE.OBJ)
- 80 0B 00 09 4D 4F 55 53 - 45 2E 41 53 4D D4 96 24
- 00 00 06 44 47 52 4F 55 - 50 04 44 41 54 41 04 43
- 4F 44 45 0A 4D 4F 55 53 - 45 5F 54 45 58 54 05 5F
- 44 41 54 41 7D 98 07 00 - 48 39 00 05 04 01 D6 98
- 07 00 48 00 00 06 03 01 - 0F 9A 04 00 02 FF 02 5F
- 90 0C 00 00 01 05 4D 4F - 55 53 45 00 00 00 D5 88
- 04 00 00 A2 01 D1 A0 3D - 00 01 00 00 55 8B EC 8B
- 5E 0C 8B 07 50 8B 5E 0A - 8B 07 50 8B 5E 08 8B 0F
- 8B 5E 06 8B 17 5B 58 1E - 07 CD 33 53 8B 5E 0C 89
- 07 58 8B 5E 0A 89 07 8B - 5E 08 89 0F 8B 5E 06 89
- 17 5D CA 08 00 BC 8A 02 - 00 00 74
-
- INTRPT.HEX (INTRPT.OBJ)
- 80 0C 00 0A 49 4E 54 52 - 50 54 2E 41 53 4D 7A 88
- 03 00 80 9E 57 96 25 00 - 00 06 44 47 52 4F 55 50
- 04 44 41 54 41 04 43 4F - 44 45 05 5F 44 41 54 41
- 0B 49 4E 54 52 50 54 5F - 54 45 58 54 23 98 07 00
- 48 07 01 06 04 01 06 98 - 07 00 48 00 00 05 03 01
- 10 9A 04 00 02 FF 02 5F - 90 1E 00 00 01 09 49 4E
- 54 45 52 52 55 50 54 00 - 00 00 0A 49 4E 54 45 52
- 52 55 50 54 58 0D 00 00 - 3F 88 04 00 00 A2 01 D1
- A0 0B 01 01 00 00 55 8B - EC 83 C4 E2 C7 46 FA 08
- 00 EB 0B 55 8B EC 83 C4 - E2 C7 46 FA 0A 00 89 76
- E4 89 7E E2 8C 5E FC 9C - 8F 46 FE 8B 76 08 8D 7E
- E6 8B 4E FA FC 16 07 F3 - A5 55 8B 76 0A 8B 1C 0A
- FF 74 03 E9 00 00 80 FB - 25 74 05 80 FB 26 75 0E
- B8 08 00 50 B8 02 CA 50 - B8 83 C4 50 EB 07 33 C0
- 50 B8 CA 06 50 8A E3 B0 - CD 50 0E B8 00 00 50 16
- 8B C4 05 06 00 50 8B 46 - F4 25 D5 0F 50 8B 46 E6
- 8B 5E E8 8B 4E EA 8B 56 - EC 8B 76 F0 8B 7E E2 83
- 7E FA 08 74 14 81 7E F6 - FF FF 74 03 8E 5E F6 81
- 7E F8 FF FF 74 03 8E 46 - F8 8B 6E EE 9D CB 55 8B
- EC 8B 6E 02 9C 8F 46 F4 - FF 76 FE 9D 89 46 E6 89
- 5E E8 89 4E EA 89 56 EC - 8B 46 DE 89 46 EE 89 76
- F0 89 7E E2 8C 5E F6 8C - 46 F8 8E 5E FC 8D 76 E6
- 1E 07 8B 7E 06 8B 4E FA - FC F3 A5 8B 76 E4 8B 7E
- E2 8B E5 5D CA 06 00 8B - 76 0A C7 04 FF FF 8B 76
- E4 8B 7E E2 8E 5E FC 8B - E5 5D CA 06 00 0B 9C 0F
- 00 84 3E 00 01 01 F1 00 - C4 66 00 01 01 A8 00 CC
- 8A 02 00 00 74
-
- CASEMAP.HEX (CASEMAP.OBJ)
- 80 0D 00 0B 43 41 53 45 - 4D 41 50 2E 41 53 4D 5F
- 96 26 00 00 06 44 47 52 - 4F 55 50 0C 43 41 53 45
- 4D 41 50 5F 54 45 58 54 - 04 44 41 54 41 04 43 4F
- 44 45 05 5F 44 41 54 41 - 08 98 07 00 48 14 00 03
- 05 01 FC 98 07 00 48 00 - 00 06 04 01 0E 9A 04 00
- 02 FF 02 5F 90 0E 00 00 - 01 07 43 41 53 45 4D 41
- 50 00 00 00 60 88 04 00 - 00 A2 01 D1 A0 18 00 01
- 00 00 55 8B EC 8B 5E 0A - 8B 07 FF 5E 06 8B 5E 0A
- 89 07 5D CA 06 00 E3 8A - 02 00 00 74
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix E Line-Drawing Characters
-
- You can enter line-drawing characters into QuickBASIC programs by pressing
- and holding the Alt key while typing up to three decimal digits on the
- numeric keypad. You can then use QuickBASIC strings to outline screen
- areas or to draw boxes around text. This chart organizes the line-drawing
- characters by type rather than by ASCII value.
-
- 201 203 187 218 194 191
- ╔ ╦ ╗ ┌ ┬ ┐
-
- 204 ╠ ╣ 185 195 ├ ┤ 180
-
- ╚ ╩ ╝ └ ┴ ┘
- 200 202 188 192 193 217
-
-
- 206 205 197
- ╬ ═ ┼
-
- 186 ║ │ 179
-
- ╪ ─ ╫
- 216 196 215
-
-
- 213 209 184 214 210 183
- ╒ ╤ ╕ ╓ ╥ ╖
-
- 198 ╞ ╡ 181 199 ╟ ╢ 182
-
- ╘ ╧ ╛ ╙ ╨ ╜
- 212 207 190 211 208 189
-
-
-
-
-
- John Clark Craig has written several books on computer programming since
- 1980, including True BASIC Programs and Subroutines. He lives with his
- family in Eagle River, Alaska, where he is a programmer for ARCO Alaska,
- Inc.
-
-