💾 Archived View for gemini.spam.works › mirrors › textfiles › magazines › MISC › qbnws103.nws captured on 2022-06-12 at 13:24:11.
-=-=-=-=-=-=-
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