home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-23 | 108.1 KB | 2,657 lines |
- Volume 1, Number 3 May 22, 1990
-
-
-
-
-
-
-
-
-
-
-
-
- **************************************************
- * *
- * QBNews *
- * *
- * International QuickBASIC Electronic *
- * Newsleter *
- * *
- * Dedicated to promoting QuickBASIC around *
- * the world *
- * *
- **************************************************
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews is an electronic newsletter published by Clearware
- Computing. It can be freely distributed providing NO CHARGE is charged
- for distribution. The QBNews is copyrighted in full by Clearware
- Computing. The authors hold the copyright to their individual
- articles. All program code appearing in QBNews is released into the
- public domain. You may do what you wish with the code except
- copyright it. QBNews must be distributed whole and unmodified.
-
- You can write The QBNews at:
-
- The QBNews
- P.O. Box 507
- Sandy Hook, CT 06482
-
- Copyright (c) 1989 by Clearware Computing.
-
-
-
- The QBNews Page i
- Volume 1, Number 3 May 22, 1990
-
-
-
-
- ----------------------------------------------------------------------
-
- T A B L E O F C O N T E N T S
-
-
- 1. From the Editors Desk
- From the Editor .............................................. 1
-
- 2. Mail Bag
- QBNews in Europe ............................................. 2
-
- 3. Beginners Corner
- BASIC Menuing and Graphics by Ryan Snodgrass ................. 4
-
- 4. Who ya gonna call? CALL INTERRUPT
- Directory Swapping by Hector Plasmic ......................... 6
-
- 5. The Tool Shed
- P-Screen+ and P-Screen Professional by David Cleary .......... 8
- Index Manager - B-Tree indexing for QB by David Cleary ....... 10
-
- 6. Product Announcements
- P-Screen, P-Screen Professional, P~F Presents ................ 12
-
- 7. Under The Hood
- Fast File I/O in QuickBASIC by Ethan Winer ................... 16
-
- 8. Power Programming
- How to Make a Self-Cloning Exe in QuickBASIC by Larry Stone .. 19
- Programming UEVENT by Jim Mack ............................... 23
-
- 9. Some Assembly Required
- Assembler Programming for QuickBASIC by Tom Hanlin ........... 26
-
- 10. And I Heard it Through the Grapevine
- Exerpts from the QUIK_BAS echo ............................... 29
-
- 11. Swap Shop
- Screen Scrolling with Call Interrupt ........................ 33
- Getting the Day of the Week with Call Interrupt ............. 35
- Yes/No Response DEF FN ...................................... 37
- A Replacement for INPUT with MUCH MORE programmer control. .. 39
- Windowing Routines with Shading ............................. 41
-
- 12. Input Past End
- Get the QBNews on Disk ...................................... 42
- Contacting the QBNews ....................................... 43
-
- The QBNews Page ii
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- F r o m t h e E d i t o r s D e s k
- ----------------------------------------------------------------------
-
- From the Editor
-
- Welcome to the third issue of The QBNews. I know it has been a
- while coming but I hope it was worth the wait. There are some big
- changes in store for the news. I have realized that putting out an
- issue every 2 months is impractical. Therefore, The QBNews will be
- published quarterly. Expect issues around these dates:
-
- May 30
- August 30
- November 30
- February 28
-
- I have also received alot of requests for the news on disk. You
- can now receive the QBNews on disk. Information on this service is
- available in the back of this issue.
-
- The QBNews is distributed through SDS on Fidonet. It seems that
- SDS is not as far reaching as I had thought. In order that everybody
- knows that the can get the news reasonably close to them, I would like
- to set up distribution hubs around the country. I am looking for BBS's
- in these areas who would like to be QBNews hubs: Baltimore/Washington,
- Charlotte NC, Atlanta, Orlando, Memphis, New Orleans, Chicago,
- Cincinnati, Minneapolis, Kansas City MO, Dallas, Denver, Phoenix, Los
- Angeles, San Francisco, and Portland. I do require a few things in
- order to be a hub. First, first time callers must be granted limited
- download privledges. Second, you must accept file requests from Point
- systems. Last, you must be willing to send the news down the line to
- the next hub. If you meet these conditions and are interested in being
- a hub, write me.
-
- I want to hear from you. After the first issue, I received quite
- a bit of feedback. I wasn't too happy with that issue. I thought the
- second issue was really good. I didn't receive as much feedback on it
- as the first though. It was kind of disappointing. Let me hear your
- complaints, suggestions, coding tips, or whatever. It always helps to
- know people are interested.
-
- Thanks and enjoy.
- David Cleary
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 1
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- M a i l B a g
- ----------------------------------------------------------------------
-
-
- Hello David,
-
- Today I've picked up 2 QBNews files and I've read them both. Most
- interesting stuff! Just the electronic magazine I need! Coming from
- the TRS80 Model I computer on which I've learned basic and wrote my
- own BBS and videotext systems in basic (the system is still online)
- I've entered the PC community and started with RBBS-PC which is, as
- you would know, almost completely written in QuickBasic. I've
- purchased the package a few years ago and developed a few
- administrative applications in it for a friend his firm. At the
- moment, due to lack of time, I'm only do a little debugging and
- modifying RBBS-PC. I recently discovered a bug (well, I think it is a
- bug) which I will give you here:
-
- DEFINT A-Z :' so every variable is by default integer
- Single precision! = 3600 * Hour
-
- The maximum value of an integer is 32767 and when you expect
- "Hour" can have a maximum value of 24, then the receiving variable
- must be a single precision variable 'cause by example 20 * 3600 =
- 72000. So the construction above looks good but isn't. QuickBasic will
- evaluate "3600 * Hour" as an integer expression 'cause both variables
- are integers. The result will be an overflow error. I've tested the
- same construction on my TRS80 and on the PC in GWBASIC and they both
- work fine!!
-
- The solution for this problem is very simple. The technique is called
- typecasting.
-
- Single precision! = 3600.0 * Hour :' 3600.0 is of type single
- precision
-
- When you enter this in the QB environment, QB will change 3600.0 in
- 3600! which is the same.
-
- Some undocumented META statements, nice to know:
- ' $LINESIZE:132
- ' $PAGE
- ' $TITLE: 'put the main title here'
- ' $SUBTITLE: 'put the sub-title here'
-
- Anyway, I hope this is some contribution to the magazine. From
- now on I will put the QBNews files in my two BBS systems and will
- upload them to some other systems here in Holland. I hope more QBNews
- will come from the other side of the ocean. Please respond through
- Fidonet if you receive this message. Where I living, well, in a city
- called Amsterdam, that's in Holland or The Netherlands and that is in
- Europe ('cause many Americans don't know what's on the other side of
- the ocean ;-)
-
-
- The QBNews Page 2
- Volume 1, Number 3 May 22, 1990
-
- Cu, Kim Kodde (2:500/41.1433) Holland
-
-
-
- Hello David,
-
- A very good initiative! I give my full support for whit it's
- worth. I am not a professional programmer and I have no education in
- this area, but I have been programming in BASIC for some years for fun
- and during that time gone from an VIC64 to an AMSTRAD 6128 to an
- Artech 286/AT (and IBM ps 20). I started out with QB 2.00 a couple of
- years ago but recently upgraded to 4.50. It is a marvelous difference.
-
- I have also included an extract from a program I have written for
- my work. I am a journalist and the program is used to store things we
- are to check or cover in the future. Certain things come back
- regularly on certain weekdays no matter which date it is. I therefore
- needed a simple routine to check which weekday a certain date is so
- when the agenda for that date is printed out the correct items
- depending on the weekday is included. I found my answer in interrupt
- 33, function 2a00. The low part of register AX returns a number for
- the weekday. 0 for Sunday to 6 for Saturday. This is very good for
- the future. If you are interested in checking which day you were born
- for example you need something else because the computer only covers
- dates from the early 80-ies. I have seen programs in genealogy-
- packages which covers this part.
-
- Johan Lindgren
- Sundsvall, Sweden
-
-
- I would be interested in hearing from you. Please write with
- comments, suggestions, complaints, or whatever you feel like talking
- about. Send it to:
-
- The QBNews
- P.O. Box 507
- Sandy Hook, CT 06482
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 3
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- B e g i n n e r s C o r n e r
- ----------------------------------------------------------------------
-
- BASIC Menuing and Graphics by Ryan Snodgrass
-
- This section of QB News is dedicated to the readers who are
- novices to Quick BASIC. In this issue we will talk about creating and
- editing simple menu programs and about some of the elementary commands
- used in making computerized graphics. The first thing we talk about
- is making simple menus. The first step you take in making a menu is
- to plan what selections you will have. In our example we will use the
- following selections: DIR, make the computer beep, and quit. The next
- step is to plan whether to use numbers, letters, or both. In our
- example we will use both numbers and letters. The following is an
- example program; you may edit it as much as you like.
-
- Menu:
- PRINT "(1) - DIR" 'Shows the first selection (DIR)
- PRINT "(2) - BEEP" 'Shows the second selection (BEEP)
- PRINT "(Q) - QUIT" 'Shows the third selection (QUIT)
- MenuInput:
- A$=INPUT$(1) 'Waits for the input from the keyboard
- IF A$="1" THEN GOTO Selection1 'See if one was pressed
- IF A$="2" THEN GOTO Selection2 'See if two was pressed
- IF A$="Q" OR A$="q" THEN CLS:END 'See if Q was pressed
- GOTO MenuInput 'Go back and wait for another key
-
- Selection1:
- SHELL"DIR" 'Do a DIR of the current directory
- GOTO Menu 'Redisplay the menu
- Selection2:
- BEEP 'Produce a beep
- GOTO Menu 'Redisplay the menu
-
- -+* To edit selections on this menu do the following: *+-
-
- 1) Change the menu listing by replacing one of the selections by
- another (i.e. PRINT "(1) - DIR" replace with the following:
- PRINT "(1) - DIR/P")
-
- 2) Change the selection commands (i.e. change the Selection1 commands
- to:
- Selection2:
- SHELL"DIR/P"
- GOTO Menu
-
- -+* To add selections to the menu do the following: *+-
-
- 1) After the PRINT "(2) - BEEP" add PRINT "(3) - Your Selection"
-
- 2) After IF A$="2" THEN... add IF A$="3" THEN GOTO Selection3
-
- 3) After the GOTO Menu on Selection2 add:
- Selection3:
-
- The QBNews Page 4
- Volume 1, Number 3 May 22, 1990
-
- 'Your command
- GOTO Menu
-
-
- The next subject we will discuss is elementary commands for
- creating graphics screens. A graphics screen is represented by
- a number of pixels or points on the screen, which is referred to as
- the resolution of your screen. The first step we must do is select a
- screen number which corresponds to your resolution or any other
- resolution you can use. The following is a list of screen number and
- their attributes:
-
- +-----------+------------------+-------------+------------------+
- |Screen #: | # of colors: | Resolution: | Width of Screen:|
- +-----------+------------------+-------------+------------------+
- | 1 (CGA) | 4 out of 16 | 320x200 | 40 Characters |
- | 2 (CGA) | 2 out of 2 | 640x200 | 80 Characters |
- | 7 (EGA) | 16 out of 64 | 320x200 | 40 Characters |
- | 8 (EGA) | 16 out of 64 | 640x200 | 80 Characters |
- | 9 (EGA) | 16 out of 64 | 640x350 | 80 Characters |
- | 10 (MONO) | 9 grays | 640x350 | 80 Characters |
- | 11 (VGA) | 2 out of 2 | 640x480 | 80 Characters |
- | 12 (VGA) | 16 out of 256000| 640x480 | 80 Characters |
- +-----------+------------------+-------------+------------------+
-
- The next step is to type: SCREEN (and then the type of graphics
- you want). The first and easiest command is LINE. The usage is LINE
- (X,Y)-(X,Y),Color (i.e. LINE (100,100)-(200,200),1 would draw a line
- from 100,100 to 200,200 using the color 1). Using that in an example
- program would be as follows:
-
- SCREEN 1
- LINE(100,100)-(200,200),1
- END
-
- You can also draw an open rectangle by using LINE (X,Y)-
- (X,Y),Color,B or a solid rectangle by using LINE (X,Y)-(X,Y),Color,BF.
- The next command we will go into is the DRAW command. The usage is
- DRAW "(Attributes)" (i.e. DRAW "U4 R4 D4L4"). The attributes are as
- follows: C#=Color Number, U#=Up a number of pixels, D#=Down a number
- of pixels, L#=Left a number of pixels, R#=Right a number of pixels,
- E#=Up and to the right a number of pixels, F#=Down and to the right a
- number of pixels, G#=Down and left a number of pixels, H#=Up and left
- a number of pixels, M X,Y=Moves to a certain pixel (i.e. DRAW "M
- 100,100"). Our example program draws a 3-D box:
-
- SCREEN 1
- DRAW "M 100,100 C1 U10 R10 D10 L10 H10 U10 F10 R10 H10 L10"
- END
-
- If you have any suggestions as to what you would like to see in
- this column, please send them to the QBNews at the address in the
- back.
-
-
- The QBNews Page 5
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- W h o y a g o n n a c a l l ? C A L L I N T E R R U P T
- ----------------------------------------------------------------------
-
- Directory Swapping by Hector Plasmic
-
- You've all seen professional programs that let you Shell to DOS
- and always return you to the proper drive and subdirectory when you
- Exit. It's not too hard to implement something similar for your own
- QuickBASIC programs. QB doesn't have all the functions you need to do
- it, but DOS can lend a hand via Interrupt.
-
- What we need to do is handle all SHELL calls from a common point
- (Sub). In this Sub, we'll determine the current drive and
- subdirectory, perform the SHELL, then restore the old drive and
- subdirectory before Exitting the Sub.
-
- Interrupt 21h function 19h returns the number of the current disk
- drive in register .al as a number (0=A, 1=B, etc.).
-
- Interrupt 21h function 47h copies the current directory of the
- drive # in .dl (0=default, 1=A, 2=B, etc.) as an ASCIIZ (null
- terminated) string into a buffer pointed to by .ds:.si. The pathname
- does not include the drive identifier or a leading backslash. An
- error can occur if you use an invalid drive specification; this is not
- likely since we are using the default drive, but if you are using this
- function to attempt to read the default directory on a drive that may
- not exist, check the carry flag (IF OutReg.FLAGS AND 1
- THEN...oops!). .ax will contain 0Fh (invalid drive spec) if the error
- occurs.
-
- Finally, Interrupt 21h function 0Eh sets the default drive to the
- drive number passed in register .dx (0=A, 1=B, etc.).This completes
- the list of DOS functions we'll need to perform our switching. What
- follows is some sample code to show a practical application of these
- interrupt functions:
-
- DEFINT A-Z
-
- TYPE RegType2
- 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
-
- 'You must link with QB.LIB (QB.QLB) to use Interrupt functions
-
- DECLARE SUB InterruptX (Intr%, InReg AS RegType2, OutReg AS RegType2)
-
- The QBNews Page 6
- Volume 1, Number 3 May 22, 1990
-
- DECLARE SUB DoShell (Before$, Args$, After$)
-
- DoShell "Type EXIT to return", "", "Welcome back" 'Just to test it
- END
-
- SUB DoShell (Before$, Args$, After$)'Declare some stuff to use
-
- DIM InReg AS RegType2
- DIM OutReg AS RegType2
- DIM CurrentDrive AS INTEGER
- DIM CurrentDir AS STRING * 64
-
- 'Get current disk drive
-
- InReg.AX = &H19 * 256
- InterruptX &H21, InReg, OutReg
- CurrentDrive = OutReg.AX MOD 256
-
- 'Get current directory
-
- InReg.AX = &H47 * 256
- InReg.DX = CurrentDrive + 1 'Note adding one to drive for this, or
- 'could use 0 for default drive
- InReg.DS = VARSEG(CurrentDir)
- InReg.SI = VARPTR(CurrentDir)
- InterruptX &H21, InReg, OutReg
-
- 'Do the shell
- IF Before$ <> "" THEN CLS : PRINT Before$ 'Optional
- SHELL Args$
- IF After$ <> "" THEN CLS : PRINT After$ 'Optional
-
- 'Change to old disk drive
- InReg.AX = &HE * 256
- InReg.DX = CurrentDrive
- InterruptX &H21, InReg, OutReg
- '(InReg.AX MOD 256 is the # of logical drives in the
- 'system if anyone is interested)
-
- 'Change to old subdirectory (Could use Int &H21 func &H3B instead)
- ToDir$ = CHR$(ASC("A") + CurrentDrive) + ":\" + LEFT$(CurrentDir,_
- INSTR(CurrentDir, CHR$(0)))
- CHDIR ToDir$
-
- END SUB
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 7
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- T h e T o o l S h e d
- ----------------------------------------------------------------------
-
- P-Screen+ and P-Screen Professional by David Cleary
-
- *** IMPORTANT ***
- It took me a while to write this review. As you read it, you will
- see I have two major complaints concerning these programs. They are
- lack of mouse support and an easier user interface. These problems
- have been corrected in the latest release. Please see the product
- announcement for the new version in this issue.
-
- A program's user interface can be the difference between success
- and failure. You could have the best program in the world but if
- people don't like using it, it won't succeed. The user interface is
- also the part of a program I hate doing the most. I know what I like
- in a user interface but I have a hard time translating it into my
- programs. I also find the coding of user interfaces very tedious. So,
- in this issue, I will review a tool that helps you design user
- interfaces quickly and easily.
-
- The product is called P-Screen and is from Pro~Formance. P-
- Screen+ is a shareware program while P-Screen Professional is
- commercial. This program combines a screen drawing utility, a screen
- storage and display utility, and the Professional version adds a
- QuickBASIC 3 and 4 code generator and a variety of user input
- routines. These programs allows you to create screens and forms, store
- them in libraries, and access them from your QuickBASIC programs. We
- will examine these features individually.
-
- As a screen generator, I feel that P-Screen has one major flaw.
- It lacks mouse support. Personally, I like mice and I don't like
- having to navigate the screen with the cursor keys. When you start up
- P-Screen Professional, you get a nice title screen that tells you your
- options and waits for you to press a key. After you press a key, you
- are left with a blank screen and a "What do I do now?" look on your
- face. Pressing F1 for help shows you 2 screens of commands but that is
- all. To learn how to use P-Screen, you will need a copy of the printed
- documentation next to you.
-
- After you start using the commands and learn what they do, P-
- Screen is a pleasure to use. It allows you to draw your screens and
- store them in either ASCII or a compressed format. P-Screen also
- allows you to load screens saved in QB's BSAVE format but won't let
- you save them that way. If P-Screen had mouse support and better on
- line help, it would be one of the best screen designers available.
- Without it though, it still is very good.
-
- Next comes the screen storage and display utility. P-Screen
- stores screens on disk in a compressed screen format. The savings in
- size is very noticeable the more screens you have in a library. P-
- Screen then has two routines that load the screens into an array and
- display them. They are written in Assembler and are very fast. These
- routines allow you to display full or partial screens anywhere you
-
- The QBNews Page 8
- Volume 1, Number 3 May 22, 1990
-
- want. I couldn't find anything to complain about. They are nicely done
- and will add a professional look to your programs.
-
- Now to what I think is the best part of P-Screen. The
- Professional version comes with a form generator. P-Screen
- Professional comes with the ability to create forms and it generates
- code that handles user input on these forms. See the program Index.Bas
- for an example of the code P-Screen Professional generated for a small
- index card screen I created. The user input routine is nicely done in
- Assembler and includes a variety of formatting options and masks. Some
- of these include Date, Phone Number, Zip Code, Social Sec. Number, and
- Currency. With these options, your program makes sure that the user
- types in only valid keys and in the format you want. The code that P-
- Screen Professional generates is then inserted into your program. This
- allows you to create professional looking documents with very little
- effort. I am very impressed with these capabilities in P-Screen
- Professional.
-
- Two shareware programs you should be aware of are P-Screen and
- P~F Presents. P-Screen is the screen drawing and library utility
- portion of P-Screen Professional. Gone are the code generator and form
- utilities and the ability to display partial screens. My advice to you
- is to get the shareware version and try out the screen generator. If
- you like using it to create your screens, then you should certainly
- buy the professional version. You won't be disappointed.
-
- P~F Presents is a screen presentation system. It lets you take
- screens created with P-Screen and create slide shows out of them. This
- is great for presentations or prototyping applications before you get
- down to writing code. With it, you can create your whole user
- interface and let the users give you there comments on it BEFORE you
- write any code. This saves a lot of headaches from having to rewrite
- your programs when your views on how the program should operate are
- different from the intended users.
-
- P-Screen Professional is available from:
-
- Pro~Formance
- 132 Alpine Terrace
- San Francisco, CA 94117
- (415) 863-0530
-
- The cost is $49 plus $3 shipping and handling. You also can
- download the shareware version of P-Screen and P~F Presents from Peter
- Tiffany's BBS, (415) 458-6404 or on CompuServe in the IBMPro and
- IBMApp areas. The filenames are PSCRN35.ZIP and PFPRES35.ZIP.
-
-
-
-
-
-
-
-
-
- The QBNews Page 9
- Volume 1, Number 3 May 22, 1990
-
- Index Manager - B-Tree indexing for QB by David Cleary
-
- Databases are an important part of computers and computer
- programming. QuickBASIC has built in capabilities that make it easy to
- write a simple database. The problem is, as your database gets larger
- and larger, it takes longer to find the information you need. That is
- where Index Manager helps out.
-
- Index Manager allows you to build single user ISAM (Indexed
- Sequential Access Method) databases using a B+ Tree index. A B+ Tree
- is a data structure that allows you to find information quickly
- without searching something from start to finish. All Index Manager
- does is handle the index of your database allowing you to handle your
- datafile as you please. All you do is to associate a unique "Key" with
- each record and Index Manager does the rest. This key could be a name
- or customer number or what have you. The only thing you have to be
- sure of is that each record in your database has it's own unique key.
-
- The specifics of Index Manager are as follows:
-
- 1. Create an indexed-access file using the key of your choice.
-
- 2. Read any record on you indexed-access files by specifying it's
- key.
-
- 3. Browse through your indexed-access file by specifying a partial
- key.
-
- 4. Read your indexed-access file sequentially sorted by key either
- forward or backward.
-
- 5. Work with up to ten indexed-access files at the same time.
-
- All of Index Manager's functions are incorporated into one call
- making it very easy to use. It is also written in assembly language
- making it extremely fast and small. It only adds 5k of code size to
- your QB programs. It utilizes a large cache buffer to cut down on disk
- accesses when searching for a key. This makes it very fast but also
- introduces one of it's drawbacks. It uses 24k of string space for it's
- buffers. This makes string space kind of tight on large applications.
- I would like to see some sort of variable buffer allocation so you
- could reclaim the string space while sacrificing some speed.
-
- Although Index Manager is very easy to use and comes with
- examples showing how to use every function, it doesn't teach you
- database principles. If you know nothing of how to set up good
- databases, you could find yourself making errors that could cause your
- program to not be as useful as it can. The example programs show you
- how the functions work but they are not real world applications. I
- would like to see some examples of things like a small phone
- directory, ect. that will help someone not familiar with database
- programming go in the right direction.
-
- Aside from the string space problem and the lack of good database
- examples, I love this program. I received my copy of Index Manager
-
- The QBNews Page 10
- Volume 1, Number 3 May 22, 1990
-
- free for the purpose of doing this review. At the time, I had never
- written a database program before. As luck would have it, a database
- programming application had just come up where I work. I decided that
- I would give Index Manager a try in helping me with this project. The
- project turned out so well that my company decided to pay for this
- copy.
-
- Index Manager is for those people who just want to add fast
- indexing to their QB programs. It is an alternative to going out and
- spending more money on products like DB-Lib or B-Trieve when you don't
- need all the functions of these products. Index Manager is also alot
- easier to use than those products and allows you to handle your
- datafiles anyway you choose.
-
- Index Manager costs $59 and is compatible with QB 2 to 4.5 and
- Bascom 6. A Basic 7 PDS version that supports far strings is in the
- works. You can get Index Manager by contacting:
-
- CDP Consultants
- 1700 Circo del Cielo Drive
- El Cajon, CA 90202
-
- 619-440-6482
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 11
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- P r o d u c t A n n o u n c e m e n t s
- ----------------------------------------------------------------------
-
- P-Screen, P-Screen Professional, P~F Presents
-
- Rob W. Smetana (415) 863 - 0530
- Pro~Formance 132 Alpine Terrace San Francisco Ca 94117
-
- Program Name Cost Summary
- --------------------- ---- -----------------------------------
- P-Screen "Plus" $ 29 Screen Design, Display, Library
- system for QuickBASIC 3.0 - 4.x.
-
- P-Screen "Professional" $ 49 PS Pro writes programs for you! and
- includes other CALLable routines.
-
- P~F Presents $ 49/$ 79 Presentation system to display
- P-Screen's "text" screens -or-
- BSAVEd "graphics." See below for
- many "uses" for presentations.
-
- P-Screen "Pro" AND Enhanced versions of BOTH.
- P~F Presents ($79 ver.) $110
-
- NOTE: P-Screen and P~F Presents are "shareware." Registered
- versions cost 1/2 to 2/3 LESS than commercial examples.
- Yet they're finely tuned, professional quality programs
- that'll save you enormous amounts of time, and give your
- programs a professional appearance -- f-a-s-t, easily.
-
- P-Screen and P-Screen Professional are among the most sophisti-
- cated "screen management systems" available. They were written
- BY Quick- BASIC programmers FOR QuickBASIC programmers (we
- support QB 3.0-4.x). P-Screen "+" and P-Screen Pro share most
- features. These are described immediately below. Later we'll
- explain features that PS Pro adds.
-
- DESIGNING help screens, menus, data entry screens, etc. is a snap.
- * Use a mouse or fast keyboard "hot keys" (eg., alt-B = Box).
- * Choose options using hot keys or pull down menus.
- * Many design options: Boxes, lines, "auto-joining" of lines
- and boxes, text, Big! Font text (tm), clipboard, paint,
- center, copy, move, erase, WalkAbout, re-color, repeat, add
- any Ascii character, view in Monochrome, UnDo, and much more.
-
- LOAD screens for editing from Screen Libraries, ASCII or BSAVE files.
- * A RAM-resident program is included letting you: 1) "Capture"
- screens from other applications (to later load and edit); and
- 2) Save ANY text screen in BSAVE format when you need them.
-
- SAVE screens to Screen Libraries, ASCII or "Com" files.
- * Screens saved to libraries or Com files are COMPRESSED,
- saving disk space and RAM. Libraries store 1-100 screens;
- libraries "index" screens, letting us display or edit them fast.
-
- The QBNews Page 12
- Volume 1, Number 3 May 22, 1990
-
- * Com screens are "executable!" Run them from batch files or DOS
- for instant screens -- complete with color, lines, shading, etc.
-
- DISPLAY screens from your programs fast and easily -- just CALL
- two routines we include.
-
- OTHER FEATURES
- * Blazing speed! Assembler language routines plus "indexed"
- screen libraries mean your programs display screens f-a-s-t!
- 10-20 screens per second is typical. We've seen 75 per second!
- - We've eliminated the disadvantages of storing screens on disk.
- - Screen libraries let you keep "screen text" OUT of your
- programs, preserving string space and memory. And you can
- edit screens WITHOUT changing your programs.
- - And there are NO RAM-resident screen loaders to worry about!
-
- * Big! Font (tm) lets you easily add large-character messages.
- We include several Big! Fonts. You can create your own Big!
- Fonts, or customize them "on the fly."
-
- * Supports 25, 43 or 50 line screen modes.
-
- =================================================================
- P-Screen Professional ($ 49)
- =================================================================
-
- P-Screen Professional (PS Pro) has all the features of P-Screen
- described above, but also saves you enormous amounts of time by:
-
- * Writing your QuickBASIC 4.x programs for you!
-
- * Including several other subprograms you can use in ANY Quick-
- BASIC 4.x program you write (most also work with QB 3.0).
-
- In short, you focus on what your programs "look like." Once
- you have your screen designed, PS Pro can write your BASIC code.
- Just add any routines you need for printing or database manage-
- ment. Then compile your programs and away you go.
-
-
- PS Pro writes your data entry programs for you! Just "mark" a
- "field" on your screen and tell PS Pro what "type" of field it is.
- * You can create fields with are "editable," and fields which
- are "calculated." For calculated fields, enter ANY Quick-
- BASIC formula, and PS Pro will handle the calculations for
- you and print their results.
-
- * And you can link "help screens" to each field if you like.
-
- * Once you've "formatted" each field on your screen just press
- a key. PS Pro writes your program in about 2-3 seconds!
-
-
- PS Pro lets you choose from among 13 field types.
- * Choose a field type and PS Pro formats editing, printing,
-
- The QBNews Page 13
- Volume 1, Number 3 May 22, 1990
-
- and displaying the results of "calculated fields" for you.
-
- * Choose field types from among: string, upper case, proper
- name, date, phone number, Zip Code, Social Security number,
- numeric string, integer, long integer, single precision,
- currency and double precision.
-
- PS Pro comes with several subroutines you can use in any program.
- These include: rsMinput, OneKey, Mask/StripMask, FormatUsing,
- ProperName, rsQprint, Exists, and StripTail. Use them to:
- * Handle ALL user input (text, extended keys, printer codes).
- Get a single key, or a full line of text. rsMinput offers
- the full array of editing features, includes UnDo, AND
- offers "masked" input for easy, accurate editing of fields
- like Phone Numbers [(...) ...-....] or Zip Codes [.....-....].
-
- * Format text and numbers for easy editing or printing
-
- * Print with assembler speed
-
- * Convert all lower case text to "proper name" format
-
- * Determine if files exist (before you try to open them)
-
- =================================================================
- Product Announcement: P~F PRESENTS
- =================================================================
-
- P~F Presents (PFP) is our desktop presentation system. It dis-
- plays screens from P-Screen's screen libraries. It also displays
- BSAVED "graphics" screens. Text, graphics or both; it's your call.
-
- Presentations (or slide shows) can include, among other things:
- * Full- or Sub- screen displays.
- * Menus, in 3 different styles.
- * Display and sound effects.
- * Special options including: "If x Goto," "Gosub", "Loop,"
- "Pause," "MakeMono" (to display colored screens on
- monochrome monitors).
- * Timed slides (which pause as long as you want between slides),
- -or- slides which wait for the viewer to press a key.
-
- And you can create self-running presentations, or run 'em yourself.
-
- Why would a programmer be interested in a presentation system?
- For many of the same reasons programmers like Dan Bricklin's DEMO
- program (at about 1/4 the cost)! Plus, P~F Presents offers
- many other opportunities as well. Consider these:
-
- PROGRAM PROTOTYPES
- * You can create "working prototypes" of programs in minutes or
- just a few hours.
- * Since presentations can include menus (3 types), display effects,
- sound effects, etc. your prototypes can have the "look and feel"
- of your actual program.
-
- The QBNews Page 14
- Volume 1, Number 3 May 22, 1990
-
- * Letting your clients, customers or potential users see how your
- program will look and feel (BEFORE you've written a line of code):
- 1) Helps you "beta test" your ideas; 2) Helps eliminate time-
- consuming re-writes; and, 3) Speeds up program development.
- * And creating "mock ups" helps you think through a program's
- logic before you write any code.
-
- PROGRAM: DEMOS, MARKETING TOOLS, TUTORIALS
- * You can easily and quickly create demos, marketing tools or
- program tutorials -- using many of the SAME SCREENS your
- programs will display.
-
- As an example, we recently used PFP to create, in 2 hours, a
- working prototype of a new program. We had it back to a
- prospective client the day after we first talked to him. It
- had the complete "look & feel" of the program he wanted. And
- creating it helped us think through our program design.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 15
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- U n d e r T h e H o o d
- ----------------------------------------------------------------------
-
- Fast File I/O in QuickBASIC by Ethan Winer
-
- [EDITOR'S NOTE] This article first appeared in the March 1990 issue of
- Programmer's Journal. Back issues can be ordered by calling
- 1-800-234-0386.
-
- Without doubt, one of the slowest operations a program can
- perform is saving and loading disk data files. In many cases, this is
- dictated by the physical access delay of the disk device, and the time
- required to transfer data based on its rotation speed. One exception,
- however, is when many reads or writes must be performed on small
- pieces of data. For example, it is quite common to save or load an
- entire numeric array. In the case of an integer array that contains,
- say, ten thousand elements, that many individual calls to the DOS file
- I/O services will be needed. Even though DOS is written in assembly
- language, it still takes a fair amount of time to process each read or
- write request.
-
- One obvious solution is to process the file operation as a single
- large read or write. Indeed, I have written assembly language
- routines to do just that for use in company's QuickPak Professional
- add-on library product. But it is also possible to call QuickBASIC's
- internal PUT and GET routines directly. By bypassing the QuickBASIC
- compiler and its syntax checking, you can coerce it to read and write
- up to 64K of data in a single operation. Larger files can be
- accommodated by processing the file in pieces. The trick is to
- determine the names of these routines, and the number and type of
- parameters they expect to receive.
-
- QuickBASIC versions 4.0 and later contain four different internal
- routines for reading and writing binary data. Two of these are meant
- for reading data from a file, with one using the current DOS SEEK
- location and the other accepting a long integer SEEK argument.
- Similarly, there are two separate routines for writing data to disk.
-
- Most of QuickBASIC's internal routines begin with the characters
- "B$", which are illegal in a subroutine name. Fortunately, the ALIAS
- keyword allows you to declare a procedure with two different names --
- the name you will use when calling it from the program, and the actual
- name that is made public for the linker. When Microsoft introduced
- inter-language calling capabilities in QuickBASIC version 4.00, it
- needed a way to allow access to routines written in C. These routines
- always start with an underscore character, which is also illegal as a
- QuickBASIC procedure name.
-
- The example program shown in Figure 1 declares the four internal
- routines as follows: BigSave writes data using the current DOS file
- pointer position, and BigSaveS expects a SEEK argument. Likewise,
- BigLoad reads from the current file position, and BigLoadS requires an
- offset to SEEK to before reading. All four of these routines require
- the parameters to be passed "by value", as opposed to "by address"
-
- The QBNews Page 16
- Volume 1, Number 3 May 22, 1990
-
- which is BASIC's usual method of passing parameters. This results in
- code that is both faster and smaller, because an extra level of
- indirection is avoided. That is, the routines can obtain the values
- directly from the stack, rather than having to first determine an
- address, and then go to that address for the actual value. Even
- though BYVAL and SEG *look* like they would result in additional code
- being added to a program, they are really just directives to the
- compiler.
-
- Before any of these routines may be called, you must open the
- file to be read or written for BINARY operation. Then, the first
- parameter that each routine expects is the BASIC file number that was
- used to open the file. The address parameter is passed as a SEG
- value, which means that both a segment and offset are required.
- Notice that a file may be loaded to or saved from any area of memory,
- by replacing [SEG Address] with [BYVAL Segment, BYVAL Address]. When
- SEG is used as part of a CALL statement, the "value" of the variable's
- segment is pushed on the stack, followed by the value of its address.
- Substituting two separate arguments "by value" is functionally the
- same thing as far as the routines are concerned. Also notice that the
- internal routine names are not available within the QuickBASIC editing
- environment. Therefore, this example program must be compiled to disk
- before it may be tested.
-
- In my own informal tests, I have found this technique to be as
- much as ten times faster than reading or writing individual array
- elements using a BASIC FOR/NEXT loop. The actual savings will of
- course depend on the number of elements being processed and their
- length in bytes. Unfortunately, this method cannot be used with
- QuickBASIC string arrays, because they are not kept in consecutive
- memory locations. However, numeric arrays may be accommodated, as
- well as any fixed-length or user-defined TYPE array.
-
- It is important to understand that when manipulating a fixed-
- length string array, the SEG operator must not be used. Whenever a
- fixed-length string or array element is used as an argument to an
- external routine, QuickBASIC first makes a copy of it into a regular
- string variable. Then, the address of the copy is passed instead.
- Since the address of a copy of an array element has no relevance to
- the address of the actual array, we must use a different approach. In
- fact, there are two possible solutions.
-
- One is to create a TYPE definition that is comprised solely of a
- fixed-length string portion. Although the example below assumes a
- string length of twenty characters, you would of course use whatever
- is appropriate for your program.
-
- TYPE FLen
- S AS STRING * 20
- END TYPE
-
- DIM Array(1 TO 10000) AS FLen
-
- The second solution is to use a combination of BYVAL VARSEG and
- BYVAL VARPTR, to pass the segment and address of the starting array
-
- The QBNews Page 17
- Volume 1, Number 3 May 22, 1990
-
- element directly. When QuickBASIC sees VARSEG or VARPTR, it realizes
- that you do in fact want the actual segment and address of the
- specified array element. Thus, you would use the following syntax
- when calling BigSave to save a fixed-length string array:
-
- CALL BigSave(FileNumber, BYVAL VARSEG(Array(First)), BYVAL _
- VARPTR(Array(First)), NumBytes)
-
- One final note concerns saving or loading more than 32767 bytes.
- QuickBASIC does not support unsigned integers, so you must instead use
- an equivalent negative value. This is quite easy to determine, by
- simply subtracting 65536 from the required number of bytes. It is a
- common trick to avoid negative numbers when calling assembly language
- routines by instead substituting a long integer number or variable.
- However, that will not work in this case, because two extra bytes will
- be pushed onto the stack by the use of BYVAL. Therefore, it is
- essential that you specify the correct type of parameters when calling
- these routines.
-
- **********************************************************************
- Ethan Winer is the president of Crescent Software, and the author
- of QuickPak Professional and P.D.Q. He can be reached by calling
- Cresent Software at (203) 846-2500.
- **********************************************************************
-
- [EDITOR'S NOTE] Source code for this article is contained in
- FASTFILE.ZIP.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 18
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- P o w e r P r o g r a m m i n g
- ----------------------------------------------------------------------
-
- How to Make a Self-Cloning Exe in QuickBASIC by Larry Stone
-
- [EDITOR'S NOTE]
- All extended ASCII codes have been replaced in the following
- article.
-
- Have you ever had the need to create a program that holds a
- password away from prying eyes of others? Or, maybe you have
- discovered that writing shareware rewards your ego by making your name
- familiar to the PC world, but doesn't reward your pocket-book because
- most people will register their programs when they get around to it,
- which, often-times, is never. Or, maybe you just wish to write a
- program that holds it's configuration without having to create a
- configuration file.
-
- One of the easiest methods to accomplish the above listed tasks
- is to create an EXE file that "clones" information to itself. The
- trick is to create a "recognizable" area inside of the EXE itself that
- can be quickly read and modified.
-
- What makes this such an easy trick? Well, have you ever used
- Vernon D. Buerg's LIST utility to list your EXE's? If you do, you
- will notice that towards the end of the program, every string that you
- have defined within your program is CLEARLY VISIBLE! What you are
- viewing is the EXE's token definition area. When you compile and link
- your programs, a token is defined for every string used. For example,
- your program might have the code, Strike$ = "Strike any key". When
- you list the EXE, it may show something like, 0TStrike any key. The
- symbols 0T would be the programs marker to the definition, "Strike any
- key". Under no circumstance do you want to change this marker because
- really weird results could ensue. However, you can create a string
- that contains a marker that is exclusive to your use, i.e.,
-
- Special$ = "<*!@#%>This is my special string"
-
- In the above example, <*!@#%> then becomes your special marker to
- the data that immediately follows. Then, all your program has to do
- is to look for your special marker and modify the next 25 characters
- as needed!
-
- CAUTION! Never, never, never try to reserve a data area for
- cloning by defining a string as:
-
- Special$ = "<*!@#%>" + SPACE$(25)
- Special$ = "<*!@#%> "
-
- Both of the above examples will *NOT* create the 25 character
- data area desired because BC will optimize the SPACE$(25) as a two
- byte token!
-
- Let's assume that we need to build a program that needs to hold a
-
- The QBNews Page 19
- Volume 1, Number 3 May 22, 1990
-
- user-defined, sixteen character password and a token that determines
- whether the EXE is shareware (limited in scope) or registered. Let's
- further say that when a registration is received by you, the author,
- you then mail that person a key which redefines the definition of a
- token so that features not available to the shareware user now become
- available. Let's further state that your program is going to hold
- configuration information within a 13 byte string.
-
- The first thing to do is to create a unique string inside of the
- program itself, as well as, two or three variables shared within the
- program. At the top of the program, do something like the following:
-
- DIM SHARED StoredData$, BytesToData&
-
- Now, if your program does not "clone" configuration information
- or passwords, then BytesToData& does not need to be SHARED. Rather,
- in this case, only the information itself (Shareware/registration key)
- needs to be shared. However, for this discussion, we're going for the
- entire pie.
-
- Next, someplace within your initialization subprogram (or in your
- main module), you should place code such as the following:
-
- SpotForKey$ = "<%*@#!>123456789012345678901234567890"
-
- Now, because your program needs to read itself, modify itself
- and, at the same time, hold part of the original string as your
- special marker, we need to do the following:
-
- tempKey$ = LEFT$(SpotForKey$, 6)
-
- In this way, no matter what we do to the following 30 character
- spaces, <%*@#!> will always remain our special marker that the program
- looks for.
-
- Let's build the routine that reads in this data.
-
- '--------------------- Get Special Data Routine ---------------------
-
- DIM SHARED StoredData$, BytesToData&
-
- SpotForKey$ = "<%*@#!>123456789012345678901234567890"
-
- tempKey$ = LEFT$(SpotForKey$, 6) 'Our special marker.
-
- 'The Bytes% variable is the number of bytes to read.If your program is
- 'less than 16000 bytes then this routine adjusts accordingly. Also, if
- 'a 16K byte "GET" cuts the marker field in two then you need to change
- 'it to another value, such as 15550.
-
- Bytes% = 16000
- BytesToData& = 0
- portion& = 1
- countToKey% = 0
- StoredDataLen% = 30
-
- The QBNews Page 20
- Volume 1, Number 3 May 22, 1990
-
-
- OPEN MyProg$ FOR BINARY AS #1 FiSize& = LOF(1)
- 'Get the size of the file
- DO WHILE NOT EOF(1)
- IF Bytes% > FiSize& THEN Bytes% = FiSize&
- IF Bytes% + portion& > FiSize& THEN Bytes% = FiSize& - portion&
- A$ = INPUT$(Bytes%, 1) 'Read Bytes% number of characters.
- countToKey% = INSTR(A$, tempKey$) 'Look for our special marker.
- IF countToKey% THEN 'If we found it then process it.
- BytesToData& = portion& + countToKey% + 5 'Get past our marker.
- SEEK #1, BytesToData& 'Get the data from the file.
- StoredData$ = INPUT$(StoredDataLen%, 1)
- EXIT DO 'We found it so out of the DO LOOP
- END IF
-
- portion& = Bytes% + portion& 'Determine where the next SEEK is.
-
- 'If we're within 800 bytes of the end of the EXE then we are past the
- 'token definition area of the QB program. In this case, we're done.
-
- IF portion& >= FiSize& - 800 THEN EXIT DO
-
- 'Move pointer to the next 16000 byte block to read from the file.
-
- SEEK #1, portion&
-
- LOOP
- CLOSE #1
-
- '--------------------- End Special Data Routine ---------------------
-
- Now, whenever our program needs to look for a password, a
- registration key value, or it's configuration information, it need
- only do the following:
-
- Password$ = LEFT$(StoredData$, 16)
- RegisValue = VAL(MID$(StoredData$, 17, 1))
-
- IF RegisValue = 7 THEN
- PRINT "Shareware Edition"
- ELSE
- PRINT "Registered Edition"
- END IF
-
- ConfigData$ = MID$(StoredData$, 18)
-
- To prove this works, snip out the special routine and add the
- following statement at the end of the routine: PRINT StoredData$
- Next, compile and link it, then run it. You will see the above string
- printed (you will also notice just how fast QB's INSTR function really
- is! - It's blazingly fast! - Couple this with BINARY access and you'll
- discover that load time is not appreciably degredated). Don't forget
- to define MyProg$ as something or you'll get a nasty error message!
-
- Okay, okay, so how do we write new information to our special
-
- The QBNews Page 21
- Volume 1, Number 3 May 22, 1990
-
- data area? Simple - just do the following:
-
- Password$ = "Lawrence Stone "
- RegisValue$ = "0"
- ConfigData$ = "Config Area 1"
-
- OPEN MyProg$ FOR BINARY AS #1
- PUT #1, BytesToData&, Password$ 'To write the new password.
- RegisValue$ = "0"
- PUT #1, BytesToData& + 16, RegisValue$'To create a registered version.
- PUT #1, BytesToData& + 17, ConfigData$ 'To clone configuration data.
- CLOSE #1
-
- Now, re-run your compiled program and have these values print to
- the monitor. Notice how easy it was to change the data?
-
- If you are going to have an external "key" program that "turns
- on" the registered version then it needs to simply read in the data
- using the same special marker that we created as a marker to search
- for. Also, you might wish to make another small program that converts
- your pre- defined password and configuration space to spaces.
- Otherwise, you need to run your program before you distribute it so
- that you can change the password (which is equal to
- "1234567890123456") to something like SPACE$(16). In other words,
- nullify the temporary string used by our program that forced BC to
- give us the data space we needed in the first place.
-
- Now, for demonstration purposes, we have used the default "7" for
- indicating that the program is shareware and "0" for registered. I
- would recommend that you reserve at least 8 character spaces for this
- field because then you can create unique codes for every key and every
- user. In this way, your program can look for the key in both itself
- and within the key program as well. This would also offer one more
- level of safeguards for you.
-
- One final word: Any casual hacker can use LIST to find your
- password if you leave it in it's native ASCII. You should consider a
- routine that converts the appearance of your data so that it looks
- like the rest of the binary code. Routines can be as simple as taking
- each character in the strings and adding 100 to their ASCII value for
- writing, then, subtracting 100 from their ASCII value for reading, to
- some truely cryptive procedure, depending on how sensitive you want
- the information contained therein to remain.
-
- **********************************************************************
- Larry Stone is President of LSRGroup and is involved in writing
- software for marine and aquatic research. He can be reached at
- LSRGroup, P.O. Box 5715, Charleston, OR 97420, or in care of this
- newsletter.
- **********************************************************************
-
- [EDITOR'S NOTE] The file CLONE.BAS contains a slightly modified
- version of Larry's code above. I have modified it to make it easier to
- add to your program. It is contained in CLONE.ZIP.
-
- The QBNews Page 22
- Volume 1, Number 3 May 22, 1990
-
- In Search of the Elusive UEVENT by Jim Mack
-
- QB allows you to trap a number of different "events", such as the
- TIMER tick, the arrival of a byte in a COM buffer, the press of a
- specific KEY, and so on. It does so by adding extra code after
- each statement (/V) or each line (/W) which checks the state of flags
- associated with enabled events. Special handlers deal with the
- actual interrupt and set these internal flags as appropriate.
-
- This is a three-stage process: first, an interrupt (an event)
- occurs and is handled quickly by the QB runtime, which sets the flag
- and variables associated with the event. This happens behind your
- program's back, as it were. Second, when the current line or
- statement completes, QB checks the flags to see if any active events
- (those for which you have executed "ON xxx GOSUB" and "xxx ON"
- commands) have occurred. Third, on discovering such a condition QB
- executes the GOSUB code you wrote to deal with it.
-
- The only area where UEVENT differs from events like KEY is in the
- first part of the first step. In defining a UEVENT, _you_ take
- responsibility for dealing with the interrupt, and for notifying the
- QB runtime that such an event has occurred. From that point on, the
- action is exactly the same.
-
- The difference between invoking a GOSUB via SetUEvent (or any
- trap) and calling it directly is that when you invoke it, it's
- executed only when QB gets around to it, and only if UEVENT ON is
- currently in effect. A side effect of this is that you may "lose"
- events if more than one occurs between occasions when QB checks its
- internal flags.
-
- This whole business of interrupts can be broken down in several
- ways: shared vs. exclusive vs. chained, or software vs. hardware, and
- so on. The code packages included here give examples of two common
- combinations.
-
- You can trigger a UEvent in QB with no interrupt at all, by just
- saying "CALL SetUEvent". In MASM, declaring SetUEvent as an EXTRN far
- procedure lets you do the same thing: CALL SetUEvent. In C, you'd
- declare "setuevent" as a void far external function and then reference
- "setuevent()" to cause your QB handler to be invoked. Simple... and
- practically useless by itself. You need to combine this with a
- software or hardware interrupt.
-
- >> "Software interrupts" are really misnamed: they have more in
- >> common with a subroutine call than with a hardware interrupt.
- >> Since they occur under direct program control, there's nothing
- >> unexpected or asynchronous about them. They do however use
- >> the same table of vectors that the hardware interrupts use.
-
- A small step up is the exclusive "true" software interrupt. This
- involves taking over an unused interrupt vector, writing a tiny MASM
- routine which intercepts INTs directed at this vector and performs a
- CALL SetUEvent. There's no reason to take this extra step unless
- you're working with a canned other-language program which must use a
-
- The QBNews Page 23
- Volume 1, Number 3 May 22, 1990
-
- pre-defined INT to access your code. If you're using DOS 3.x, this
- can be done in exactly the same manner as the "chained" software
- interrupt described below, since what you're chaining onto is a
- pre-defined Dismiss This Interrupt routine.
-
- >> A "vector" in this context is a memory location reserved by
- >> the computer as a pointer: it contains the address of a routine
- >> intended to service an interrupt. There are 255 such vectors in
- >> the PC, occupying the memory from 0000:0000 through 0000:03FF.
- >> Eight of these (sixteen in the AT) are reserved for use by the
- >> hardware Interrupt ReQuest lines, or IRQs. When an enabled
- >> interrupt occurs, the PC stops what it's doing and executes the
- >> routine whose address is stored in the appropriate vector.
-
- Next most complicated is the chained software interrupt. One
- example of an existing software interrupt is the BIOS disk service,
- which uses INT 13H. If you wanted your handler to be invoked whenever
- disk activity occurred, you'd chain onto this interrupt vector and
- monitor the registers using MASM. When an event of interest occurred,
- you'd "CALL SetUEvent" to notify QB. In any case, you'd pass the
- interrupt along to the original INT 13H handler. Closely related to
- this is the chained hardware interrupt. The setup is exactly the
- same: hook the interrupt vector, monitor the registers, etc. All
- other details are taken care of by an existing handler.
-
- The code in CHNEVENT.BAS is an example of a chained handler which
- will work for any hardware or software interrupt. The assumption is
- that you're just monitoring existing events (and sometimes activating
- SetUEvent), but not touching any hardware. In the example we monitor
- INT 9, the keyboard interrupt, but you can monitor almost any of
- the256 vectors by replacing "9" with the appropriate number. Try an
- experiment: replace the INKEY loop with a LINE INPUT statement. If
- you can explain what happens, you've grasped the essentials of QBevent
- handling.
-
- >> "Hooking" a vector means only that you store the address of your
- >> own service routine in the vector. To facilitate cleanup, it's
- >> usual to first retrieve and store the existing contents of the
- >> vector so that they can be replaced on exit. If you're "chaining"
- >> onto this vector, then you'll also use that original address when
- >> your routine is finished, by performing a JMP directly to it.
- >> Since this can happen to several routines in sequence, it's easy
- >> to see why it's known as chaining.
-
- The next step up in complexity (and it's a pretty big step) is
- the exclusive hardware interrupt. Here, you're responsible for all of
- the nitty-gritty of the PC hardware, in addition to any details
- associated with the hardware device. You must program the 8259A
- Programmable Interrupt Controller to allow interrupts on your IRQ
- level, then issue a command to clear the PIC when you service an
- interrupt. These must be done in MASM, as your QB event handler will
- not be executed in a timely fashion and so cannot be relied on to take
- care of these high-speed events. The code in EVENTHDW.ASM shows how
- to deal with an event occurring on an arbitrary IRQ line (determined
- at install time), but because we aren't dealing with a real device
-
- The QBNews Page 24
- Volume 1, Number 3 May 22, 1990
-
- here, the specific instructions for the interrupting hardware can only
- be hinted at.
-
- >> Each hardware IRQ line is intimately tied to a vector: in the
- >> case of the lower IRQs (0-7) the INT number (the vector number) is
- >> simply the IRQ number plus 8. That's why the KB interrupt, which
- >> uses IRQ 1, is vectored through INT 9.
-
- Slightly more complicated is the shared hardware interrupt. In
- order for two hardware devices to share an IRQ line, there must be
- away to determine which device requested service by interrupting. An
- example of sharing an interrupt might be COM1 and COM3, which both use
- IRQ4 and hence INT 0CH. When an interrupt occurs on IRQ4, the COM3
- service routine gains control and examines a register in the UART it's
- responsible for to see if that UART caused the interrupt. If it
- didn't, control is passed to the COM1 service routine. I haven't
- included a specific example of adding a shared handler, but if you
- need one and can't figure it out from the code shown, you can contact
- me and I'll try to help.
-
- In addition to the above, whenever you take over an interrupt
- vector you must somehow put things back in order when your program
- terminates. At a minimum this means restoring the original contents
- of the vector; for hardware interrupts, you must also restore the
- 8259A Interrupt Mask Register bit to the state in which you found it.
-
- To make this process a bit more automatic, QB includes the
- B_OnExit routine. Any running BC program takes over a number of
- interrupt vectors for its own use (for example, BC math functions
- invoke INT 04H whenever an overflow occurs) which must be restored on
- any exit, normal or abnormal. BC and QB provide B_OnExit as an
- extension of this internal cleanup. You still must write the code to
- do the actual restoring of vectors, etc., but BC can call that code
- automatically on *any* exit, even an error crash, if you "register
- "your routine via B_OnExit. Each of the included code packages uses
- B_OnExit in this way.
-
- **********************************************************************
- Jim Mack is a programmer specializing in real-time systems for the
- entertainment industry. He can be reached via CIS ID 76630,2012 on
- the MSSYS forum in the BASIC or MASM sections, or at Editing Services
- Co., PO Box 599, Plymouth MI 48170, (313) 459-4618
- **********************************************************************
-
- [EDITORS NOTE]
- For some reason, the program CHNEVENT.BAS will cause my computer
- to crash when run in the QB 4.5 enviroment. This is not the case when
- run in the QBX (BC7) enviroment. Caution is advised if you try to run
- this in the enviroment. Source code for this article is contained in
- UEVENT.ZIP.
-
-
-
-
-
- The QBNews Page 25
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- S o m e A s s e m b l y R e q u i r e d
- ----------------------------------------------------------------------
-
- Assembler Programming for QuickBASIC by Tom Hanlin
-
- Perhaps you already know a little bit about programming in
- assembly language, or perhaps you've never given it much thought.
- After all, it's supposed to be frighteningly difficult to write
- assembler programs, and you've already got QuickBASIC anyway.
-
- Well, it's true that there's a lot of work involved in writing
- large programs in assembly language. If you keep to the small stuff,
- however, there's actually very little to it. One of the easiest and
- most rewarding uses for assembly language lies in writing routines
- that can be called from a higher-level language like QuickBASIC. This
- can give you entirely new capabilities or make your existing programs
- smaller and faster. By mixing the capabilities of a low-level
- language like assembler with a high-level language like QuickBASIC,
- you can gain a lot of flexibility when you need it, without
- sacrificing the ease of use of good ol' BASIC.
-
- Microsoft's documentation on mixed-language programming is rather
- daunting. It's not exactly clear and the examples never seem to cover
- quite what you had in mind. Once you understand a few simple rules,
- though, you'll see that adding assembler routines to your QuickBASIC
- programs can be readily accomplished.
-
- I'm going to assume you have some notion of how to program in
- both QuickBASIC and assembly language, since explaining an entire
- language would be a bit more than a single article could cover! With
- that in mind, let's take a look at the basic rules of writing assembly
- routines for QuickBASIC and follow that up with the code for a working
- routine.
-
- The first thing you need to know is which registers you can use.
- The answer is, "all of them." However, certain registers must be
- preserved for BASIC, so if you use them, you must restore their
- original values before returning to the main BASIC program. The
- registers that must be preserved are SI, DI, BP, and DS. You also
- need to preserve the stack (SS and SP) and direction flag. The
- direction flag must always be "forward" when you exit, so if you
- change it using the "STD" instruction, be sure to restore it using the
- "CLD" instruction.
-
- Believe it or not, that's most of what you need to know right
- there. The other important thing to know is how to pass parameters to
- or from the assembler routine. I'll keep it simple by assuming you
- use the standard convention, which is "pass by reference", rather than
- "pass by value", which has to be explicitly declared.
-
- What do I mean by "pass by reference?" I mean that, instead of
- getting the actual value of a parameter, your routine gets the address
- of that parameter and has to look up the value. It's useful to have
- the address of the parameter, since that means you can return a value
-
- The QBNews Page 26
- Volume 1, Number 3 May 22, 1990
-
- by storing it in the parameter's address.
-
- Integral numbers are stored simply. For integers, the address
- you are given points directly to the integer (a word). If you use
- long integers, the address points to the long integer (a doubleword).
-
- Strings are stored in a slightly more complex fashion. The
- address you are given points to a "string descriptor". This
- descriptor is composed of two words, with the first giving the length
- of the string and the second the address of the string. You are not
- allowed to change the length or address of the string in your
- assembler routine, although you may change the string itself.
-
- I won't go into single precision or double precision numbers,
- because they are rather tricky to handle in assembler. I won't go
- into arrays, TYPEd values, or fixed-length strings here either, to
- keep it reasonably brief. Perhaps in a later article...
-
- Parameters are passed on the stack, starting at offset 6 (six)
- for the -last- parameter and going up by two as you move towards the
- first parameter.
-
- Finally, you need to end your routine with a special "RET" opcode
- that will clean the parameters off the stack for QuickBASIC. The RET
- must have a number after it which is twice the number of parameters
- passed to the routine.
-
- Clear as mud? Well, perhaps the example routine will help show
- what I'm talking about. The DOSVER.ASM file contains the source code.
- To assemble it just type: ASM DOSVER; (where "ASM" is the name of your
- assembler: MASM, TASM, or OPTASM)
-
- Convert the resulting DOSVER.OBJ file to a library so you can
- easily use it both from the command line and QB environment:
- LIB DOSVER; (this creates DOSVER.LIB)
- LINK DOSVER/Q,,NUL,BQLB45; (this creates DOSVER.QLB)
-
- If you are using QuickBASIC 4.0, change the BQLB45 to BQLB40. If
- you are using QuickBASIC 4.0a or 4.0b, change it to BQLB41.
-
- You can now use the DOSVER routine from the QB environment by
- specifying the library name when you start QuickBASIC: QB /L DOSVER
-
- Use of the DECLARE statement is optional, but it will help catch
- any errors you might make when calling DOSVER. Use this: DECLARE SUB
- DOSVER(VERSION$, MAJORV%, MINORV%)
-
- Before calling the routine, you must set the VERSION$ string to
- at least four characters, since the routine is not allowed to change
- the length of the string. Call the routine like this:
- VERSION$ = SPACE$(4)
- CALL DOSVER(VERSION$, MAJORV%, MINORV%)
-
- Typical results will be "3.11" for VERSION$, 3 for MAJORV%, and
- 11 for MINORV%.
-
- The QBNews Page 27
- Volume 1, Number 3 May 22, 1990
-
-
- In later articles, if there is any interest in it, I'll explain
- how to handle arrays, TYPEd variables, and fixed-length strings, and
- also how to pass values back from functions rather than using
- subprograms.
-
- **********************************************************************
- Tom Hanlin is the author of the very popular ADVBAS library for
- QuickBASIC. His new shareware library is called BASWIZ. He can be
- reached through the QUIK_BAS echo on Fidonet or in care of this
- newsletter.
- **********************************************************************
-
- [EDITOR'S NOTE]
- The archive ASMREQ.ZIP contains the assembler source code plus an
- assembled .OBJ file for the routine contained in the article.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 28
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- A n d I H e a r d i t T h r o u g h t h e G r a p e v i n e
- ----------------------------------------------------------------------
-
-
- From: Mike Sinak
- To: All
- Subj: PEEK & POKE
-
- I am just beginning to study DOS and BIOS calls and don't understand
- how to do it at all. Does anybody have any info on the PEEK and POKE
- usage? Like if you want to peek and poke to turn caps lock on and
- off, how in the world do you know what address to peek and poke? I'm
- lost! I would like to learn more about this stuff and get some kind
- of comprehensive list of peeks and pokes.
-
- Also I learned that at DEF SEG 0 you can turn on and off caps lock by
- POKE &H0417, PEEK &H0417 OR &H40 (to turn on)
-
- and
-
- POKE &H0417, PEEK &H0417 AND &HBF (to turn off)
-
- Now how in the world did they know that? The AND and OR statments are
- supposed to be turning on and off bit 6 of the &H0417 address. How
- did they know these particular numbers turn on and off bit 6? Better
- yet, how did they know that bit 6 had to be turned on and off at this
- particular address to turn caps lock on and off. Is there a pattern?
-
- Obviously my ignorance is being displayed. Go ahead and laugh <grin>
- but I would sure like to know more about this.
-
- ANY HELP?
-
-
- From: Robin Hunziker @ 965/1
- To: Mike Sinak
- Subj: Re: PEEK & POKE
-
- Perhaps your best bet for figuring out how DOS operates is by
- purchasing the following book:
-
- Advanced MSDOS Programming
- 2nd Edition
- Ray Duncan
- Microsoft Press
- ISBN 1-55615-157-8
-
- For example, on page 582 the book discusses exactly your area of
- question in easy-to-understand tabular format. It discusses how to
- call Int 16H Function 02H to "get keyboard flags". Although the front
- cover states that it is "The Microsoft guide for Assembly Language and
- C programmers", it is very relevant to much of the discussion in this
- echo.
-
-
- The QBNews Page 29
- Volume 1, Number 3 May 22, 1990
-
-
- From: David Martin
- To: Mike Sinak
- Subj: Peek & Poke
-
- A better way to set upper and lower case is the following:
- Lower Case: POKE 1047, PEEK(1047) AND 191
- Upper Case: POKE 1047, PEEK(1047) OR 64
- Lots of stuff can be done with poke such as disable the CTRL-BREAK,
- turn number lock key on and off, read hardware configurements, read
- size of RAM. The list goes on and on. If you want a list of the
- commands let me know. These commands must be preceded by: DEF SEG =
- 0. Let me know what kind of stuff you are working with so I can give
- you the commands.
-
-
- From: Tom Hanlin
- To: Mike Sinak
- Subj: Re: PEEK & POKE
-
- In order to understand bit numbering, you need to convert the
- number to binary. Bits are numbered from right to left, with the
- lowest bit being number zero. So:
- &H40 = 64 = 0100,0000b (note that bit 6 is turned on)
- &HBF =191 = 1011,1111b (note that all bits except 6 are turned on)
- when you OR a number with another number, the result contains all of
- the bits that were turned on in the first number OR in the second
- number. When you AND two numbers, the result contains all of the bits
- that were turned on in the first number AND in the second number. So,
- to turn on a specific bit, you OR with a number that has only that bit
- turned on (which leaves the other bits in the original number alone).
- To turn a specific bit off, you AND with a number that has only that
- bit turned off (which leaves the other bits in the original number
- alone). See?
-
- Knowing which memory locations have special purposes, such as
- keeping track of Caps Lock and Num Lock, comes from (mostly) IBM's
- listing of the system BIOS. Many reference books contain the
- information in a decoded format, so you can use it without having to
- understand the BIOS at all. If you can find a copy, COMPUTE!'s
- "Mapping the IBM PC and PCjr" is an excellent guide to this sort of
- thing, although there are many others.
-
- You may also want something like Norton's guide to assembly
- language, to give you some idea about converting numbers between hex,
- decimal and binary, and how PC memory mapping works. Things like...
- DEF SEG=0:PRINT PEEK(&H417)
- is the same as
- DEF SEG=&H40:PRINT PEEK(&H17)
-
-
- From: David Martin
- To: Mike Sinak
- Subj: Peek & Poke
-
-
- The QBNews Page 30
- Volume 1, Number 3 May 22, 1990
-
- The following list is some things that can be done with peek & poke.
- KEYBOARD KEYS:
- PEEK (1047) AND 8: value 8 if ALT is pressed.
- 4: CTRL
- 2: 2 LEFT SHIFT.
- 1: 1 RIGHT SHIFT.
- 3: 3 NIETHER SHIFT.
- PEEK (1048) AND 4: 4 PRINT SCREEN KEY.
- PEEK (1047) AND 64 0 if in LOWER CASE.
- 64 UPPER CASE.
- POKE 1047, PEEK(1047) AND 191 specify LOWER CASE.
- OR 64 specify UPPER CASE.
- FOR J=0 TO 3:POKE (108+J),PEEK(112+J):NEXT: DISABLE CTRL-BREAK
- CONFIGURATION OF COMPUTER:
- (PEEK(1041) AND 192)/64: number of PRINTER ADAPTERS.
- (PEEK(1040) AND 1)*(1+PEEK(1040)/64 number of DISK DRIVES.
- (PEEK(1041) AND 14)/2 number of RS232 ports.
- PEEK(1043)+256*PEEK(1044) size of RAM.
- NUMBER LOCK KEY:
- PEEK(1047) AND 32 0 if OFF, 32 if ON.
- POKE 1047,PEEK(1047) AND 223: turn NUM LOCK key OFF.
- 32: turn NUM LOCK key ON.
- Alot of these commands are abreviated. If nothing appears below a
- line just type in the line on top of what you want along with what is
- changed. Got it? Let me know if you have any questions. Glad to help!
- All lines must be preceded by: DEF SEG =0 (Only one DEF SEG = 0 at
- the beginning of the program)
-
-
- From: Ronny Ong
- To: Mike Sinak
- Subj: Re: PEEK & POKE
-
- Mike, I also have Duncan's book and find it useful, but I do happen to
- use a number of languages including assembler, C, and QuickBASIC.
-
- Let me suggest "DOS Programmer's Reference" (2nd Edition), by Terry
- Dettmann, Revised by Jim Kyle. It is published by Que
- ISBN 0-88022-458-4. List price is $27.95 U.S. This book contains
- roughly the same type of information as Duncan's, but it has specific
- QuickBASIC 4.xx examples, so it's probably easier to use for the
- QuickBASIC programmer with less experience in assembler and C.
-
-
-
- From: Ronny Ong
- To: Mike Sinak
- Subj: Re: Peek & Poke
-
- Hi, Mike. You might try getting a general intro/computers type of
- book and brushing up on binary numbers. All digital computers of
- today do everything in binary, or base 2. In others words, computers
- are simply made up of billions of tiny on/off switches. "On"
- represents the binary digit (or "bit" for short) of "1" and "off"
- represents "0."
-
- The QBNews Page 31
- Volume 1, Number 3 May 22, 1990
-
-
- When you see "POKE xxx, PEEK(xxx) AND 64," here's what happens (I've
- simplified this slightly):
- Let's say that PEEK(xxx) currently contains the byte value 98. In
- binary, that's 01100010. The decimal number 64 is 01000000 in binary.
- The "AND" operator means to produce a result which has a "1" in every
- position which is "1" in both of the operands and has a "0" for all
- other positions.
-
- 01100010 <--- 98
- 01000000 <--- 64
- --------
- 01000000 <--- Result of 64, to be POKE'd back into memory location xxx
-
- The end result is that all bits were turned "off" (set to 0) except
- that one bit which corresponded to 64. So, essentially, the AND 64
- "stuff" you see is manipulating individual on/off switches inside the
- computer.
-
- A good book will walk you through conversion between binary and
- decimal. Also, you'll see that hexadecimal ("hex") numbers which
- you've probably come across, are shorthand forms of binary. Good
- luck!
-
-
- [EDITOR'S NOTE]
- The purpose of this conference is to discuss Microsoft QuickBASIC
- and related applications and utilities. SysOps looking for a Group
- Mail or EchoMail link into QUIK_BAS should contact the Alliance node
- known as 520/323, the FidoNet node known as 107/323, or the Good Egg
- Net Node known as 9230/323, or simply 1-201-247-8252 for information
- on local feeds.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 32
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- S w a p S h o p
- ----------------------------------------------------------------------
-
- ***** Screen Scrolling with Call Interrupt
-
- DECLARE SUB scroll.ner (rader!, left!, up!, right!, down!)
- DECLARE SUB scroll.up (rader!, left!, up!, right!, down!)
-
- 'To demonstrate the use of interrupt 10H ah=06
- 'To scroll any part of the screen up or down
- 'QB must be invoked with the /l switch. In QB.BI the RegType is
- 'defined and the INTERRUPT-Call set up.
- 'By Johan Lindgren (BBS:+46 60115371)
-
- '$INCLUDE: 'QB.BI'
-
- DIM SHARED inregs AS RegType, outregs AS RegType
-
- '---------------------------------------------------------------------
- ' Fill the screen with numbers to indicate where scrolling takes place
- '---------------------------------------------------------------------
-
- FOR i = 1 TO 24
- FOR j = 1 TO 40
-
- PRINT USING "##"; i;
-
- NEXT j
- NEXT i
-
- '----------------------------------------------------------
-
- ' Do one scroll up first. Give values and call the sub
- '----------------------------------------------------------
-
- rader = 2: up = 5: left = 5: down = 10: right = 20
-
- scroll.up rader, left, up, right, down
-
- '------------------------------------------------------------
-
- ' Do a scroll down. Give values and call the sub
- '------------------------------------------------------------
-
- rader = 3: up = 10: left = 35: down = 15: right = 70
-
- scroll.ner rader, left, up, right, down
-
-
- 'END of demo.
-
- SUB scroll.ner (rader, left, up, right, down)
-
- '-----------------------------------------------------------
-
- The QBNews Page 33
- Volume 1, Number 3 May 22, 1990
-
- 'First put up and down in right hexadecimal postion
- 'Then enter the values into the registers and call interrupt
- '------------------------------------------------------------
-
- up = up * 256
- down = down * 256
-
- inregs.ax = &H700 + rader
- inregs.cx = up + left
- inregs.dx = down + right
-
-
- CALL INTERRUPT(16, inregs, outregs)
-
-
- END SUB
-
- SUB scroll.up (rader, left, up, right, down)
-
- '-----------------------------------------------------------
- 'First put up and down in right hexadecimal postion
- 'Then enter the values into the registers and call interrupt
- '------------------------------------------------------------
-
-
- up = up * 256
- down = down * 256
-
- inregs.ax = &H600 + rader
- inregs.cx = up + left
- inregs.dx = down + right
-
-
- CALL INTERRUPT(16, inregs, outregs)
-
-
- END SUB
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 34
- Volume 1, Number 3 May 22, 1990
-
- ***** Getting the Day of the Week with Call Interrupt
-
- DECLARE FUNCTION dag$ (nr!)
-
- ' This is just an example to illustrate the use of an interrupt
- ' to get the day of any date.
- ' By Johan Lindgren (+46 60-121497 (BBS System))
-
- '$INCLUDE: 'QB.BI'
-
- DIM inregs AS RegType, outregs AS RegType
-
- inregs.ax = &H2A00
-
- spardat$ = DATE$
-
- CLS
- PRINT
- PRINT "This is just to show the function of interrupt 33,function 2a"
- PRINT "It works well for our time and the future."
- PRINT "If you need this function for old dates, you have to use"
- PRINT "something else."
-
- ON ERROR GOTO fel.datum 'In case you enter a bad date
-
- main:
-
- svar$ = " "
- DO UNTIL svar$ = ""
- INPUT "Input the date to check in the format MM-DD-YEAR"; svar$
- IF svar$ <> "" THEN
- DATE$ = svar$ 'Set the date we want to check
- 'Call the interrupt to get the day
- CALL Interrupt (33, inregs, outregs)
- dagnr = outregs.ax MOD 256 'Extract the daynumber returned
- DATE$ = spardat$ 'Restore proper date
-
- SELECT CASE dagnr
- CASE 0
- dag$ = "Sunday"
- CASE 1
- dag$ = "Monday"
- CASE 2
- dag$ = "Tuesday"
- CASE 3
- dag$ = "Wednesday"
- CASE 4
- dag$ = "Thursday"
- CASE 5
- dag$ = "Friday"
- CASE 6
- dag$ = "Saturday
- END SELECT
-
- PRINT "The day of the week for ";svar$;" is ";dag$
-
- The QBNews Page 35
- Volume 1, Number 3 May 22, 1990
-
- PRINT
- END IF
-
-
-
-
-
-
- LOOP
-
- CLS
- END
-
- fel.datum:
- RESUME main
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 36
- Volume 1, Number 3 May 22, 1990
-
- ***** A YES/NO response DEF FN
-
- ' TO: DAVID CLEARY 76510,1725
- ' FROM: BEN HARTLEY 70033,2612
- ' SUBJECT: For QBNews -- CHOOSE.BAS -- (FUNCTION)
- '===================================================================
- 'Dear David,
- '
- ' Liked your newsletter, which I downloaded from Exec-PC BBS.
- ' I'm not what you might call an experienced programmer, but the
- ' enclosed function might be of interest.
- ' There are LOTS of routines around that allow selection of
- ' a simple "Yes" or "No" response. There are times, however, when
- ' the flow of a program is improved if the choices are something
- ' other than "Y" or "N". That's where this one comes in. If there
- ' are no more than two choices, then they can be explicitly stated.
- ' Whether this is any faster, or, heaven save us all, more "elegant"
- ' than using SELECT CASE, I haven't the foggiest. I do know that it
- ' works!
- ' You can load this entire file into your QuickBASIC editor,
- ' and run it. It was originally written in QB 3.0, but seems to
- ' run fine in QB 4.5 --
- ' Hope this is something along the lines of what you're
- ' looking for.
- '
- ' Ben Hartley
- ' Jaffrey, NH
-
- '-------------------------------------------------------------------
- DEF FNChoose (prompt$, Response1$, Response2$)
- R1$ = UCASE$(LEFT$(Response1$, 1))
- R2$ = UCASE$(LEFT$(Response2$, 1))
- alpha$ = R1$ + R2$
-
- PRINT prompt$; " ("; R1$; " or "; R2$; ") "
- reply$ = ""
- charPos% = 0
- WHILE charPos% = 0
- reply$ = UCASE$(INKEY$)
- IF (reply$ <> "") THEN
- charPos% = INSTR(alpha$, reply$)
- IF (charPos% = 0) THEN BEEP
- END IF
- WEND
- reply$ = UCASE$(MID$(alpha$, charPos%, 1))
- FNChoose = (reply$ = R1$)
- END DEF
- '-------------------------------------------------------------------
- COLOR 15, 1
- beginhere:
- CLS
- LOCATE 10, 5
- PRINT "Which option do you wish..."
- LOCATE 12, 7
- IF FNChoose("...The First or the Second ?", "First", "Second") THEN
-
- The QBNews Page 37
- Volume 1, Number 3 May 22, 1990
-
- PRINT
- PRINT TAB(20); "You chose the First Option."
- ELSE
- PRINT
- PRINT TAB(20); "You chose the Second Option."
- END IF
- LOCATE 16, 7
- IF FNChoose("Do It Again or Quit ?", "Again", "Quit") THEN
- GOTO beginhere
- END IF
- PRINT
- PRINT TAB(30); "**** All done! ****"
- END
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 38
- Volume 1, Number 3 May 22, 1990
-
- ***** A Powerful Replacement for INPUT
-
- 'SYNTAX: Enput$(Row%,Col%,FLen%,Default$,Allow$,EndKeys$,ExitKey$)
- 'WHERE: Row% & Col% - where input to occur
- ' FLen% - Field Length - maximum allowable
- ' Default$ - Field's beginning default value
- ' Allow$ - Character Set allowable for input
- ' EndKeys$ - Keystrokes acceptable for finishing.
- ' SUCH: [Enter] is CHR$(13)
- ' [Esc] is CHR$(27)
- ' [F1] is CHR$(255)+CHR$(59)
- ' [Ctrl+PgUp] is CHR$(255)+CHR$(132)
- ' ... etc
- ' ExitKey$ - The keystroke (from above EndKeys$)
- ' which was struck at function end.
- 'SIMPLEST USE: A$ = Enput$(0,0,0,"",","",Any$)
- ' Will default to cursor's current row/col, length is
- ' autoset to right margin, allowable chars are ALL,
- ' only ending key is [Enter].
- '==========================================> Frederick Volking
-
- FUNCTION Enput$ (Row%, Col%, FieldLen%, Default$, AllowCharsMask$_
- ,EndingKeys$, ExitKey$) STATIC
-
- SHARED ScreenWidth%, BackSpaceKeyStrokes$, EmptySpaceChar$
-
- ' verify SHARED globals are set
-
- IF ScreenWidth% = 0 THEN ScreenWidth% = 40
- IF BackSpaceKeyStrokes$ = "" THEN BackSpaceKeyStrokes$ = _
- CHR$(8) + CHR$(255) + CHR$(75)
- IF EmptySpaceChar$ = "" THEN EmptySpaceChar$ = CHR$(254)
-
- ' If not specified then supply defaults to incomming vars
-
- IF AllowCharsMask$ = "" THEN AllowCharsMask$ = CHR$(34) +_
- " !#$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]_
- ^_abcdefghijklmnopqrstuvwxyz|~"
-
- IF EndingKeys$ = "" THEN EndingKeys$ = CHR$(13)
- IF Row% = 0 THEN Row% = CSRLIN
- IF Col% = 0 THEN Col% = POS(0)
- IF FieldLen% = 0 THEN FieldLen% = ScreenWidth% - Col%
- IF LEN(Default$) > FieldLen% THEN Default$ = LEFT$(Default$_
- , FieldLen%)
-
- ' define internal defaults
-
- CharsCollected% = 0
- ReturnVar$ = ""
- ' begin main loop
- DO
- NotDone% = 1
- IF CharsCollected% = 0 THEN
- LOCATE Row%, Col%, 0
-
- The QBNews Page 39
- Volume 1, Number 3 May 22, 1990
-
- PRINT Default$ + STRING$(FieldLen% - LEN(Default$), _
- EmptySpaceChar$);
- END IF
- IF CharsCollected% = FieldLen% THEN
- LOCATE Row%, Col% + CharsCollected% - 1, 1
- ELSE
- LOCATE Row%, Col% + CharsCollected%, 1
- END IF
- DO
- KeyStroke$ = INKEY$
- LOOP WHILE KeyStroke$ = ""
- IF LEN(KeyStroke$) = 2 THEN KeyStroke$ = CHR$(255) + _
- RIGHT$(KeyStroke$, 1)
- IF INSTR(AllowCharsMask$, KeyStroke$) > 0 THEN
- IF CharsCollected% < FieldLen% THEN
- IF CharsCollected% = 0 THEN
- PRINT STRING$(FieldLen%, EmptySpaceChar$);
- LOCATE Row%, Col%, 0
- END IF
- ReturnVar$ = ReturnVar$ + KeyStroke$
- CharsCollected% = CharsCollected% + 1
- PRINT KeyStroke$;
- END IF
- ELSE
- IF INSTR(BackSpaceKeyStrokes$, KeyStroke$) > 0 THEN
- IF CharsCollected% > 1 THEN
- CharsCollected% = CharsCollected% - 1
- LOCATE Row%, Col% + CharsCollected%, 0
- PRINT EmptySpaceChar$;
- LOCATE Row%, Col% + CharsCollected%, 1
- ReturnVar$ = LEFT$(ReturnVar$, CharsCollected%)
- ELSE
- CharsCollected% = 0
- ReturnVar$ = Default$
- END IF
- ELSE
- IF INSTR(EndingKeys$, KeyStroke$) > 0 THEN
- ExitKeys$ = KeyStroke$
- NotDone% = 0
- ELSE
- SOUND 500, 1
- END IF
- END IF
- END IF
- LOOP WHILE NotDone%
- Enput$ = ReturnVar$
- END FUNCTION
-
-
-
-
-
-
-
-
- The QBNews Page 40
- Volume 1, Number 3 May 22, 1990
-
- ***** Windowing Routines with Shading
-
- 'FRAME.BAS test program
- 'Lawrence Stone, 1990
- '
- 'Purpose: Demonstrate the versitility of the Frame subprogram.
- 'Note: I built this routine just for the fun of it. I designed it to
- 'be easy to use and versitile. This demonstration program simply makes
- 'six calls to the frame subprogram-the subprogram does the rest.
-
-
- DECLARE SUB Frame (TopRow%, leftCol%, botRow%, rightCol%, boxType%,_
- boxFg%, boxBg%, filFg%, filBg%, fillChar%, shadow%, header$)
-
- COLOR 12, 4 'Set a fancy color
- FOR A% = 1 TO 25
- LOCATE A%, 1
- PRINT STRING$(80, 206); 'Draw a complex background
- NEXT
-
- 'Test the Frame subprogram
- Frame 5, 20, 21, 75, 2, 15, 3, 9, 7, 178, -1, "This is a Test"
-
- 'Overlay the 1st box with a smaller 2nd box
- Frame 4, 3, 10, 36, 1, 15, 6, 6, 0, 219, -1, "This is Test 2"
-
- 'What the heck, let's draw another box
- Frame 13, 33, 22, 70, 3, 14, 2, 15, 3, 221, -1, "This is Test 3"
-
- 'What the heck, draw box #4 without a header
- Frame 15, 5, 19, 65, 4, 13, 0, 0, 7, 32, -1, ""
- LOCATE 17,14:PRINT "Box #4 has a shadow but doesn't have a Header."
-
- 'What the heck, draw box #5 without a shadow
- Frame 8, 40, 10, 73, 4, 11, 0, 11, 0, 32, 0, ""
- LOCATE 9, 43: PRINT "Box #5 doesn't have a Shadow!"
-
- 'What the heck, draw a frame around it all
- Frame 1, 1, 25, 80, 2, 15, 0, 0, 0, 32, 0, _
- "Box #6 Frames Without Clearing"
-
- COLOR 7, 0 'Restore color before ending
- A$ = INPUT$(1) 'Give a keystroke to end this test.
- END 'We're out of here!
-
- [EDITOR'S NOTE]
- Due to the formatting of the FRAME subprogram, it is not printed
- here. You can find the sub program in the file FRAME.BAS
-
-
-
-
-
-
-
- The QBNews Page 41
- Volume 1, Number 3 May 22, 1990
-
-
-
- ----------------------------------------------------------------------
- I n p u t P a s t E n d
- ----------------------------------------------------------------------
-
- Due to demand, you can now get the QBNews mailed to you on disk for a
- nominal charge. The rates are as follows:
-
- United States $3.00
-
- North America (outside US) $4.00
-
- Outside US $6.00
-
- Please add $1.00 if you want it on 3.5" media. Also, you can receive
- it in either ZIP, PAK, or LHZ format. If you don't specify, you will
- receive it in ZIP format.
-
- The first time you request the QBNews, you will receive all available
- issues. That way you won't miss any.
-
- And of course, you can always download it free from Treasure Island.
- First time callers are granted limited download privlidges so you can
- get it. Treasure Island is 9600 HST, is at FIDO address 1:141/730, and
- its phone is 203-791-8532. To request your copy on disk, send US funds
- to:
-
- The QBNews
- P.O. Box 507
- Sandy Hook, CT 06482
-
- Remember to specify which archive format you want.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 42
- Volume 1, Number 3 May 22, 1990
-
- WE NEED AUTHORS!
-
- If you are interested in writing for the QBNews, you can contact
- me at the address below. I can also be reached on Compuserve as
- 76510,1725 or on Prodigy as HSRW18A. If you are submitting articles, I
- ask that they be ASCII text with no more than 70 characters per line.
- As far as reviews go, I am pretty well set so what I really want is
- code.
-
-
- You can write me at:
-
- The QBNews
- P.O. Box 507
- Sandy Hook, CT 06482
-
- David Cleary
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 43
-
-