home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-31 | 168.5 KB | 3,616 lines |
- Volume 2, Number 2 May 31, 1991
-
-
-
-
-
-
-
-
-
-
-
-
-
- **************************************************
- * *
- * 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) 1991 by Clearware Computing.
-
- The QBNews Page i
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
-
- T A B L E O F C O N T E N T S
-
-
- 1. From the Editor's Desk
- Exciting New Things Happening with BASIC ..................... 1
-
- 2. Ask The Doctor
- How to Copy Files with QuickBASIC ............................ 2
-
- 3. Advertisement
- PDQComm - Professional Communications for "Power Programmers" 5
-
- 4. View Print
- BASICZen by John Richard De Palma ............................ 6
-
- 5. Swap Shop
- Create Bar Charts in Text Mode with QB by David Rice ......... 12
- Create Pie Charts with QB by David Rice ...................... 16
- Add BASIC 7's DIR$ Routine to your QB Programs by Dave Cleary 20
-
- 6. The Tool Shed
- A Look at Crescent Software's PDQComm by Jim Harre ........... 22
-
- 7. Who ya gonna call? CALL INTERRUPT
- Working with the Rodent by Daniel R. Berry ................... 27
- A Graphics Mouse Cursor Design System by Warren G. Lieuallen . 32
-
- 8. The QBNews Professional Library
- Fast Screen Printing by Christy Gemmel ....................... 34
- ROM-BIOS Video Services ...................................... 48
- Using FastPrint with BASIC 7 ................................. 49
-
- 9. Power Programming
- An Improved Cloning Algorithm by Larry Stone ................. 51
-
- 10. New and Noteworthy
- Custom Control Factory for Microsoft Visual Basic by Desaware 53
-
- 11. Fun and Games
- ASCII Art -- A Piece of Computer History by Charles Graham ... 54
-
- 12. QBNews Special Report
- Special Preview of Visual Basic by Dave Cleary ............... 57
-
- 13. EOF
- Receiving The QBNews ......................................... 59
- Submitting Articles to The QBNews ............................ 60
-
-
-
-
-
- The QBNews Page ii
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- F r o m t h e E d i t o r ' s D e s k
- ----------------------------------------------------------------------
-
- Exciting New Things Happening with BASIC
-
- Since the last QBNews, quite a bunch of exciting new things has
- been happening with our favorite language. First and foremost,
- Microsoft has finally released Visual Basic, its Windows Basic
- programming environment. Also, BASICPro, a new magazine devoted to
- BASIC programmers has been started. Finally, Microsoft is holding
- a big developers conference for BASIC programmers in Washington at
- the end of August. We will be able to meet the developers of
- Microsoft's BASIC products and even Mr. Bill himself. I hope to see
- some of you readers up there.
-
- This newsletter will be remain devoted to QuickBASIC programming.
- However, the next two issues will be covering Visual Basic as this
- is a very exciting new product. There is a VB preview in this issue
- and I hope for more in depth stuff for VB and other Windows BASIC
- environments for the next issue.
-
- BASICPro magazine is now two issues old. Although a bit pricey,
- the magazine holds much promise to become the Dr. Dobbs of QuickBASIC.
- If you haven't seen BASICPro, give them a call at 415-688-1808 to
- order a trial subscription. Don't forget to tell them you heard of
- BASICPro through The QBNews.
-
- Finally, I am kicking off a new series of articles for The QBNews.
- It is called The QBNews Professional Library. I am putting together
- an assembly language library written by the industries top
- programmers. Not only will you get ASM source code of the routines
- contained in the library, but you will get an in depth article
- explaining what is going on. This series should help people understand
- the bits and bytes that make our computers tick and help make them
- into better programmers.
-
- Dave Cleary - Publisher of The QBNews
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 1
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- A s k T h e D o c t o r
- ----------------------------------------------------------------------
-
- Ask The Doctor
-
- Ask The Doctor is a new question and answer area for The QBNews.
- You send in your questions and I will try my best to either answer
- them myself or get one of the many QB experts I know to answer them
- for me. If your question is used, I will send you that issue of The
- QBNews on disk as soon as it is published. Because I am not superman,
- I will not be able to answer every ones questions so if you don't see
- your question in the QBNews, don't expect a reply. Of course, you can
- always call the Crescent Software Support BBS to leave me questions
- that I will try to answer. That number is 203-426-5958.
-
-
- Dear Dave:
-
- Keep the QBNews coming. I have been doing simple programming in
- QuickBasic for over a year now but have not been able to progress very
- far. Your electronic magazine has been extremely helpful. Here is a
- question you or one of your contributors might be able to help me
- with. I am wanting to copy or move files around on my hard drive. I
- do not want to shell to dos and use the copy command. How can I do
- this using QB? I have been reading the disk I/O section of my QB
- manual but it is not very clear about how I might go about copying or
- moving files. I have look at some dos interrupt functions in a book
- call, "Programmer's Guide to the IBM PC". But again I am not sure how
- to go about using interrupts to copy or move files around.
-
- Is there any help out there for a novice like me?
-
- Thanks,
- Steven E. Walker
- Wilkinson, IN
-
- Steven,
-
- QuickBASIC has many different ways to read an write files. This may
- have caused your confusion. Copying files is easily done in QuickBASIC
- and is quite fast also.
-
- Lets first look at the options QB gives us to read a file. The
- three major commands to read a file are LINE INPUT, INPUT$, and GET.
- LINE INPUT is only good for text files and is also one of the slowest
- QB commands as far as file IO goes. That leaves INPUT$ and GET.
-
- GET and PUT are by far the fastest IO commands QB has. This is
- because with GET, the area of memory where the data gets placed is
- already allocated. All QB has to do is set up some registers and then
- call DOS to read the file.
-
- INPUT$ is another command that works for both text and binary
-
- The QBNews Page 2
- Volume 2, Number 2 May 31, 1991
-
- files. INPUT$ is slightly slower than the GET command because it
- allocates memory to hold the data each time it is called. I have found
- this speed difference to be inconsequential though. INPUT$ does offer
- some advantages over GET in our CopyFile routine. When you are at the
- end of a file, INPUT$ will return a string with the exact number of
- bytes left in the file even if you asked for more. This relieves us of
- knowing the size of the file we are working with. GET, on the other
- hand, will pad your buffer with null characters, causing us to have to
- truncate the last read if we want to keep our file lengths the same.
- For this reason, I chose INPUT$ over GET to read in the file.
-
- So here is our copy file routine:
-
- DEFINT A-Z
-
- DECLARE FUNCTION DIR$ (FileSpec$) 'Comment out if using BASIC 7
- DECLARE FUNCTION CopyFile% (Source$, Dest$)
-
- '$INCLUDE: 'QB.BI' 'Required for CALL INTERRUPT
-
- CONST Block = 4096 'Set this to the length you
- 'want your buffer to be
-
- 'Example of how to call CopyFile
- 'Ercd = CopyFile("D:\PDQ\HISTORY.DOC", "C:\SCRAP\TEST1")
-
- FUNCTION CopyFile% (Source$, Dest$) STATIC
-
- DIM Regs AS RegType 'Needed for CALL INTERRUPT
-
- '----- See if source file exists
- IF LEN(DIR$(Source$)) = 0 THEN 'Use DIR$ function from this
- 'issues SwapShop if you are
- 'using QB 4.x.
- CopyFile% = 1 'Source doesn't exist
- EXIT FUNCTION 'Exit with error code
- END IF
-
- '----- See if destination exists
- IF LEN(DIR$(Dest$)) THEN
- CopyFile% = 2 'Destination already exists
- EXIT FUNCTION 'Exit with error code
- END IF
-
- '----- Open files for BINARY
- SFileNum = FREEFILE
- OPEN Source$ FORBINARY AS #SFileNum
-
- DFileNum = FREEFILE
- OPEN Dest$ FOR BINARY AS #DFileNum
-
- '----- Now copy the files over
- DO
- Buffer$ = INPUT$(Block, #SFileNum)
-
- The QBNews Page 3
- Volume 2, Number 2 May 31, 1991
-
- PUT #DFileNum, , Buffer$
- LOOP UNTIL EOF(SFileNum)
-
- '----- Set the date and time of the copy to that of the original
- Regs.ax = &H5700
- Regs.bx = FILEATTR(SFileNum, 2) 'This gets DOS's file handle
- INTERRUPT &H21, Regs, Regs 'Get date and time of original
-
- '----- Check for an error
- IF (Regs.flags AND 1) THEN
- CLOSE #SFileNum, #DFileNum 'Close the files
- KILL Dest$ 'Kill our copy because something
- CopyFile% = 3 'went wrong. Exit with error
- EXIT FUNCTION
- END IF
-
- Regs.ax = &H5701
- Regs.bx = FILEATTR(DFileNum, 2)
- INTERRUPT &H21, Regs, Regs 'Set date and time of copy
-
- '----- Check for an error
- IF (Regs.flags AND 1) THEN
- CLOSE #SFileNum, #DFileNum 'Close the files
- KILL Dest$ 'Kill our copy because something
- CopyFile% = 3 'went wrong. Exit with error
- EXIT FUNCTION
- END IF
-
- CLOSE #SFileNum, #DFileNum 'All done
- CopyFile% = 0 'Return with success
-
- END FUNCTION
-
-
- This routine returns a 0 if everything went all right. It will
- return a 1 if the source file doesn't exist and a 2 if the destination
- file does exist. It will return a 3 if something went wrong in setting
- the copy's date and time to that of the original. This routine uses
- BASIC 7 PDS DIR$ function. For those of you with QuickBASIC, I have
- written a DIR$ function for you that appears in this issues SwapShop
- section. The DIR$ I wrote works in much the same way that BASIC 7's
- does.
-
- If you have a question for the Doctor, please send them to:
-
- Ask The Doctor
- P.O. Box 507
- Sandy Hook, CT 06482
-
-
-
-
-
-
- The QBNews Page 4
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- A d v e r t i s e m e n t
- ----------------------------------------------------------------------
-
- PDQComm - Professional Communications for "Power Programmers"
-
- PDQComm contains both low-level and high-level routines that add
- advanced communications capabilities to programs written using
- Microsoft QuickBASIC version 4.0 or later, and BASIC 7 PDS. PDQComm
- was originally designed to be used with our P.D.Q. replacement link
- library, however, PDQComm is also ideal for use with regular BASIC
- programs.
- ***** PDQComm is small and fast *****
- All of the routines provided with PDQComm are extremely small, and
- thus add very little code to your programs. The core routines for
- creating a complete terminal program add less than 2500 bytes.
- Compare that to the more than 12K which QuickBASIC adds, or perhaps
- more important, to other communications libraries that are available!
- ***** PDQComm is easy to use *****
- All of the PDQComm routines have been designed to emulate the syntax
- of the QuickBASIC routines they replace as closely as possible.
- PDQComm also takes advantage of the features available in QuickBASIC
- 4.0 and later. For example, to get a string of characters from the com
- port, you would do the following:
-
- QuickBASIC: PDQComm:
- Work$ = INPUT$(LOC(1), #1) Work$ = ComInput$(ComLoc)
-
- Compare that to what other communications libraries make you do:
- CALL MhGetRecvStatus(Port, CharsInBuffer, ECode)
- Work$ = SPACE$(100 + CharsInBuffer * 2)
- CALL MhGetData(Port, Work$, Length, ECode)
- Work$ = LEFT$(Work$, Length)
- ***** PDQComm supports high speed communications *****
- While most communications libraries claim to support baud rates up to
- 115k, a standard serial port has problems keeping up. To insure error
- free high-speed communications, PDQComm supports the NS16550A UART.
- This is an advanced IC that contains an on chip buffer, allowing the
- PC more time to receive incoming characters.
- ***** PDQComm comes with many bells and whistles *****
- Also included is full emulation for the ANSI, DEC VT52 and VT100, Data
- General D215, and generic terminal standards. These emulations can be
- instructed to operate within a windowed area, and you can even have
- multiple windows active at one time. PDQComm also comes with XModem
- and ASCII file transfer routines. The PDQComm manual contains
- extensive tutorial information explaining modems, serial cables,
- specifying port parameters, and UARTs. All of the important Hayes
- commands are described in detail, and each emulation includes a table
- of codes that are recognized. PDQComm costs $99. For more information
- or to order PDQComm, please call Crescent Software.
-
- Crescent Software - Orders:800-35-BASIC - Tech Supt:203-438-5300
- Crescent Software Support BBS:203-426-5958 - 2400,N,8,1
-
- The QBNews Page 5
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- V i e w P r i n t
- ----------------------------------------------------------------------
-
- BASICZen by John Richard De Palma
-
- Red haired Sandra is the manager of the local Egghead
- Software store. Gazing at her collection of software I said,
- "Hi Sandra, Uh... can you show me what books and software you
- have on learning to program in BASIC?"
-
- "No, no...NOOOO... John, you want this!" Sandra said, as she
- thrust an orange 10 pound box of manuals and disks into my arms
- and gave me a beaming smile.
-
- She went on, "I studied Pascal and "C" in college for TWO
- years, no one, and I mean no one studies BASIC anymore, it's a
- dead programming language." She laughed, "Just as dead as
- learning Latin."
-
- "Well, Uh," I shifted my feet for better support and put
- down Borland's version of Turbo Pascal, "I studied Latin for two
- years, and it's not all that dead," . "You see, Latin teaches
- you to know intuitively many English prefixes, suffixes and many
- of the Romance language verbs and nouns...." my voice trailed
- off, even to me that sounded like an apology for spending two
- years learning about BIG Julie and wars fought with catapults and
- giant slingshots.
-
- "Oh, don't be SILLY," Sandra said, "Here, if you don't like
- that, buy this, its C ++ with OOP."
-
- "I'm not even going to ask what "OOP" is, I said, just sell
- me something in BASIC," I sighed.
-
- "What KIND of basic programming do you want?" Sandra asked
- briskly, swivelling around to check on her employees and
- motioning to Brian to stop playing with the joystick and get back
- to work.
-
- "Well, hell, I DON'T KNOW, I just want to learn how to make
- my own programs like Paul Somerson does. If BASIC is good enough
- for him, it's good enough for me," my voice rising a half-octave.
- I started looking around for the IBM utilities section in the
- hopes of finding some box with basic BASIC information on it.
-
- There was no question that I knew NOTHING about programming.
- I was awkward and out of my depth. I knew nothing about
- programming except that it had to be better than using batch
- files to do things with MS-DOS. I was going to tell Sandra about
- batch files. Tell her about all the batch file programs that I
- had looked at that promised much and delivered little. I wanted
- to tell her about batch techniques that did not allow input into
- them except as parameters on the command line or by using the
-
- The QBNews Page 6
- Volume 2, Number 2 May 31, 1991
-
- dopey "FOR" command or the klutzy "IF ERRORLEVEL" command. I
- wanted to tell her I wanted to make colorful screens with
- selections that could be input by cursor control. I wanted to be
- able to change directories, do file sorts... I wanted to
- understand how the computer worked and then tell it what to do.
- Hell and again hell, I wanted to control the computer software.
-
- Who's Paul Somerson?" Sandra queried. "Some computer
- propeller head in Santa Monica?"
-
- "Gad, Sandy, give me a break! Paul Somerson is the editor
- of my favorite PC bible, "DOS Power Tools," he programs in BASIC.
- Look...look, you have his book on your bookshelf right here.
- Wait... waaait, I'll find the section and read it to you. Come
- back here, Oh let Brian wait on that guy, this will only take a
- minute."
-
- I picked up the book, found the page and read from my hero
- Paul[1],
-
- "One of the nicest things about BASIC is that if you
- suddenly find yourself with a problem BASIC can tackle, you can
- load it, stumble your way through a program and emerge with a
- solution a few minutes later. So maybe your program wasn't the
- most elegant display of programming virtuosity; who cares as long
- as it worked?"
-
- Sandra went on, "Well shoot yourself...I mean suit yourself,
- heh, heh, a little joke there. BASIC is dumb and slow. Learn
- "C" or Pascal, I did when I went to UCLA. No one teaches that
- dumb stuff." Sandra was very convincing and convinced.
-
- Backed into a corner and now defending both Latin, a dead
- language and BASIC a dead programming language I asked, "Well, if
- that's true, let me ask you a couple of questions. Do you use a
- computer...? You do. Do you use a computer to do applications,
- spreadsheets and mathematics...? You do. Do you use ANY of the
- Pascal and "C" you learned to help you to doing things with these
- programs. You don't..? Why?"
-
- Sandra went on to tell me how hard it was to keep up these
- great skills she learned in college and that she really didn't
- have the time to program, or the interest. She freely admitted
- that though she studied programming for two years, she never used
- it outside of class. She glanced at the clock, at the three
- people questioning Brian all at the same time and gave me a book
- called "Learn BASIC Now." She said as she walked away, "BASIC,
- is too dumb, it's a wimpy language. You're wasting your time,
- you'll be sorry. It's really not even a HIGH language."
-
- Apparently I bought a peasant computer language of limited
- capacity for limited minds. If I wanted to be part of the
- intelligentsia, I should program in "C". At least in "C" if not
- in C ++ with OOP or in Pascal. So I went home, loaded the
-
- The QBNews Page 7
- Volume 2, Number 2 May 31, 1991
-
- software and wrote my first BASIC program with Microsoft's Quick
- Basic 4.5 Interpreter. The program was one line of text which
- printed to the screen. Big deal, I want power and I get a batch
- file look alike.
-
- If I couldn't learn BASIC how could I learn these more
- elitist and complicated computer languages? I needed some
- verification and clarification. I began asking my friends about
- computer programming.
-
- Harry said, "Gosh John, I learned FORTRAN and COBOL when I
- was 17, wrote flocks of programs in them, nope don't know BASIC,
- it's too dumb and slow. What's that...do I ever USE FORTRAN and
- COBOL? No, not in years. What good was learning it then? What
- the !@#$%*!, kind of question is that!"
-
- Harry is always a little sensitive if you imply that he
- might be bragging. Harry is a card carrying elitist, he wouldn't
- be caught dead using such a peasant computer language as BASIC.
-
- Ray is different. Ray owns his own manufacturing company
- and has three Phd.s', a law degree, and went to medical school
- for three years. "Of course I can program in BASIC, John, don't
- be silly, that's child's play. But don't get too technical, it's
- been several years now, Hee Hee..., Ray chuckled.
-
- "Well Ray, that's great, I'm having a dickens of a time, I
- didn't realize that there was BASIC, BASICA, GWBASIC, PDB, and
- QUICK BASIC. What do all of these names mean and which BASIC
- should I learn?" I asked naively.
-
- Ray sputtered a fine spray just as he was tasting the wine.
- He ordered another bottle of Petite Sirah; and we were able to
- finish dinner with that question hanging like still smoke in the
- air.
-
- So it went on, if they did program "in the higher languages"
- of C, C +, Pascal they couldn't tell what and how they did the
- programming.
-
- "Well John why do you REALLY want to learn to program for,
- comm' on, tell me....comm' on...tell the truth," Marvin asked.
- Marvin programs in "C" and does programs in artificial
- intelligence and makes jokes about "the artificial
- intelligentsia."
-
- In desperation, I asked Marvin to write me a program that
- could be an all purpose tool, sort of a Swiss Army knife that
- would put up menus, take direct input from the keyboard, let you
- pick your colors, be user friendly, be modifiable, you know like
- software should be. Marvin said that I didn't really know what I
- wanted or, I wanted too much. Besides nobody programs in BASIC.
-
- So I went home and dragged out QUICK BASIC again and tried
-
- The QBNews Page 8
- Volume 2, Number 2 May 31, 1991
-
- halfheartedly to learn something that no one knew about from
- books written by REAL "propeller heads." I read and reread the
- texts trying to UNDERSTAND what the writer was driving at.
- Unfortunately BASIC is mainly written by programmers who can
- write code but who can't write to communicate with humans.
-
- It was a sort of Zen, reading and not understanding. It was
- a sort of chant. Reading again and again such stuff as: "DATE$
- Statement sets the current date," and "DATE$ Function returns a
- string containing the current date," and "FUNCTION Statement
- Declares the name, parameters, and the code that form the body of
- a FUNCTION procedure.[2]" Well that is as clear as Zen, and like
- Zen you have to have a FEEL for the terms. As any Zen master
- will tell you once you have the answer to the question, you DON'T
- have the answer.
-
- QUICK BASIC is Zen, a doing without knowing. But I
- followed the instructions ---cook book style--- and a program
- could be made to do something. The sound of one hand clapping
- makes sense now. Trying to understand what is the meaning of the
- phrase, "What is the sound of one hand clapping?" is no more
- difficult than trying to understand books written by programmers.
-
- I would have given up too, except I was given a QUICK BASIC
- program that did something that I needed to have done. Pete
- programs in QUICK BASIC. Pete is probably the only person I know
- that REALLY programs anything for himself and he uses QUICK
- BASIC. We have a mutual interest and problem with some data
- collection and analysis. Pete had an answer to the problem and
- he had a real program that would give an answer all written in
- QUICK BASIC.
-
- "Now Pete, I WON'T steal this program. Also, I won't sell
- this program and make a million dollars on it (Well... at least
- not without giving you HALF). Yes, I promise, yes that's right,
- cross my heart and hope to die. And I won't give it to the
- Iraqis! Now will you please...please....PLEASE give me a copy to
- take home?"
-
- After whining and pleading that I would not sell his first
- born program into slavery or copyright it, he gave me a copy.
- That is another Zen portion of programming, you have to earn the
- knowledge yourself, no one can do it for you. Only with
- programmers it's worse than Zen, they won't give you a copy of
- what they know! I watched him pull up the file, run it through
- his compiler and give me code that would run by its self. It was
- like watching someone start a fire by using an ancient ritual, by
- using a bow and a stick. It was the dawn of civilization, the
- passing of knowledge, the starting of fire by friction. I was
- given a real stand-alone executable program written by a real
- person, Wow! After more whining he capitulated completely and
- gave me the SECOND file, the QUICK BASIC code file.
-
- I put the diskette in my shirt pocket, it was too important
-
- The QBNews Page 9
- Volume 2, Number 2 May 31, 1991
-
- to place it anywhere's else. That night I ran it inside of my
- QUICK BASIC compiler. Gadsooks! it worked! The damn thing
- calculated and printed the results out lightening fast and it was
- information that I could really use.
-
- Zen, part two, you can't learn something you have no use
- for. That's what Sandra, Harry, Ray and all the others were
- talking about. They wrote programs in class on problems that
- they were given, not on problems they wanted solutions for
- themselves. That's why learning programming is like Zen, it is
- meaningless unless you have some use for the knowledge (which is
- both very much like and UNLIKE Zen).
-
- Good ole Paul Somerson was right. First, you need a project
- that you really...really want to do. Then use the books to look
- up the procedures to do the project with. Just learning all 190
- QUICK BASIC commands won't cut it. You have to use it ...or lose
- it!
-
- I went back to Egghead Software; Sandra and Brian had moved
- on. Scott and Lance programmed in Pascal. I asked them if there
- was anything new in QUICK BASIC that was fun. Lance gave me
- Microsoft's GAMESHOP. It came with the same book that I already
- had, but the software contained 6 games which could be run inside
- of QUICK BASIC, the code could be examined. With much head
- scratching and replaying you could actually figure out how the
- programmers did what they did. Again, like Zen you must
- persevere, be tested, try and fail, try and fail, knowledge
- doesn't come easily. But everyone likes to play games, so it
- wasn't all Zen.
-
- That was a month ago, and though it is still slow going, I
- am making progress. Pete and GAMESHOP gave me hope. I have
- uploaded two programs to CompuServe as shareware. The first
- program has attracted two dozen downloads in two weeks. Not
- great, but a start and this is also Zen; you work and study long
- for small (or no) rewards. I guess some modem users downloaded
- the program because it was simple, colorful, and played a song.
- Nothing grand, just a program called BIRTHDAY.ZIP that puts up
- colored boxes on the screen, accepts user input, and plays "Happy
- Birthday" if the computer clock reads the same day and month as
- the ones you type in. If it's not your birthday, it flashes
- different colors and plays "Happy Unbirthday."
-
- Some one laughed when I played the program for them and
- jokingly asked to see it display the EXACT age of anyone whose
- birthday was not the day it was run. He also wanted something
- that would distinguish if the person inputting the data was young
- or old (over or under 21).
-
- That was beyond my ability, but then I found, if you looked
- hard enough, someone had already done some of these things in
- QUICK BASIC or BASICA. I found a Julian (named after Big Julie
- no less) calendar function which does just that, and added it to
-
- The QBNews Page 10
- Volume 2, Number 2 May 31, 1991
-
- the program. After struggling to add that formula, it was easy
- to figure out a "LOOP" that would change a phrase depending on
- what the person's age was. Though the latter was simple math, it
- had been years since I had been forced to do any thinking about
- mathematics. Zen and math have a lot in common, but that is
- another story.
-
- With a program that calculated the person's exact age, every
- young woman that played the program exclaimed "<Gasp>, that's
- wrong I am NOT 29.078345 years old!" if that was her exact age.
- I now warn women over 30 that this might be a traumatic event as
- the computer will calculate their exact age, but they sail
- blithely ahead, not believing that it will happen. All in all, a
- lot of fun and some insight into human nature.
-
- The second program, FOR-LISA.ZIP uses random number formulas
- to generate screen colors, changes the screen to 40 characters
- wide, and displays more ASCII graphics. This one plays a
- Beethoven sonata and takes advantage of some great 1982 music
- programming in BASICA that I found on a BBS. Again, I generated
- simple mathematical formulas to do the work of many lines of
- code. Another secret of programming which could only be
- uncovered by doing. Zen is doing and not doing.
-
- So, nothing sensational, but now my batch files are getting
- a once over with this new knowledge. Now I realize that the
- macros in Microsoft Word, WordPerfect, and the script in ProComm
- Plus are written in BASIC. Now these macro formulas make sense!
- There has been a mystic clarification of macros, again like Zen
- what you learn affects other areas of knowledge.
-
- I am thinking of ordering from Crescent Software[3] a QUICK
- BASIC package that allows you to program mice, windows,
- accounting, and databases. Now I have hope, and that also is
- Zen. Yeah, nothing sensational unless you thought that BASICA
- was another name for Zen and that "Real Men only program in C."
-
- References:
- (1) Somerson, Paul, PC Magazine Power Tools 2nd Edition,
- Bantam Books, 1990 June;1157.
- (2) Microsoft, Programming in QuickBASIC Version 4.5,
- 1988;270-1.
- (3) Crescent Software, Inc; 32 Seventy Acres, West Redding,
- Connecticut 06896; VOICE: 203-846-2500.
-
- **********************************************************************
- John Richard De Palma is a California physician who practices adult
- internal-medicine. Though he is old enough to know better, he has
- decided to study computers. All the conversations and facts in this
- article are true. Only the names and locations have been changed to
- protect the unknowing and innocent who talked to him. He can be
- reached on Compuserve at 76076,571 or in care of this newsletter.
- **********************************************************************
-
- The QBNews Page 11
-
-
- ----------------------------------------------------------------------
- S w a p S h o p
- ----------------------------------------------------------------------
-
- 'BARS.BAS by David Rice
- ' I've been working on a labor scheduling program for
- ' the past two years, in a manufacturing facility that
- ' builds an automated blood analyzer for hospitals. When an
- ' order is placed by a hospital for one of these units, the
- ' Planner must figure out if her or his manufacturing floor
- ' can handle the added hours in labor (Standard Hours or
- ' Demonstrated (actual) Hours), and if the added labor will
- ' be greater than what the floor can handle (Capacity
- ' Hours).
- '
- ' The best and easiest way for the Planner to see this
- ' is by using a graph. In my scheduling program there is a
- ' spreadsheet to enter quantities (for each week, month,
- ' year, or quarter), for each assembly. A graph allows the
- ' Planner to see immediately where she or he has excess
- ' Capacity, so that assemblies may be scheduled during these
- ' slack periods. Ideally, Scheduled Actual Hours will meet
- ' Capacity, never go higher than Capacity, seldom below.
- ' With a graph, this is easy to see.
- '
- ' In the sample code here, I've excluded the Capacity
- ' bar and just included the single data set, for simplicity.
- ' To be functional, the routine must be able to handle large
- ' numbers mixed with small ones, sizing bars in proportional
- ' to their original values. It must allow the programmer to
- ' select how much room to leave at the top of the chart for
- ' a title, and how much room to allow at the bottom for
- ' stuff like labels, comments, etc.
- '
- ' I've used text mode and not graphics for several
- ' reasons. First is that almost any computer monitor will
- ' handle the graph. Also, if one wants to print out the
- ' graph, one just hits the print-screen button. Since the
- ' scheduling program was designed for a Novel Netware
- ' environment, various and vastly differing hardware may be
- ' used, and text mode allows the programmer to ignore the
- ' problem of different monitor types.
- '
- ' So the sample code is presented here for your use.
- ' The method is extremely simple, works every time, and well
- ' tested. Since there's no point in everyone inventing the
- ' wheel, this code is being published in the QuickBASIC News
- ' letter.
- '
- '-------------------------- Cut Here ------------------------------
- '
- ' BARS.BAS
- ' David Rice
- ' June 16, 1990
-
- The QBNews Page 12
- Volume 2, Number 2 May 31, 1991
-
- '
- ' Define Everything As Integer For Speed
- '
- defint a-z
- '
- ' Top.Row.Allowed is how high you want the
- ' bars to be on the screen. Bottom.Row.Allowed
- ' is how low you want the bars to be on the
- ' screen. This is to allow text to be placed
- ' on the screen where you wish, top or bottom.
- '
- How.Many.Observations = 12
- Top.Row.Allowed = 1
- Bottom.Row.Allowed = 25
- '
- ' Value!() Will Hold The 12 Bar Values. 12
- ' Was Chosen For This Example Because It Spans
- ' One Year (I.e. Bars Represent Months). TOP%()
- ' will hold the top row on the screen to draw
- ' the bars.
- '
- Redim Value!(How.Many.Observations),Top%(How.Many.Observations)
- '
- ' Read in from the DATA statement the sample
- ' values (called "Observations").
- '
- for a = 1 to How.Many.Observations
- read value!(a)
- next
- '
- data 132.3,532,53,123,433,86,445,335,122,134,505,234.74
- '
- ' Some other sample values you may wish
- ' to draw. No matter what range the numbers
- ' are, the largest number will define how
- ' the bars will be drawn.
- '
- ' data 10,20,30,40,50,60,70,80,90,100,110,120
- ' data 110,100,80,60,40,20,20,40,60,80,100,110
- ' data 999,1032,4343,4365,2033,2354,2335,2123,2102,325,3255,1212
- '
- ' If you are using a direct screen writing
- ' utility such as QPRINT or FASTPRT, you'll
- ' want to convert the number into a string.
- ' Also, with the horizontal lines going across
- ' the screen, you'll not want leading or
- ' trailing spaces.
- '
- DEF FN INT.Value$(Value!)
- defint a-z
- '
- ' Round up value!
- '
- If Value! <= 32767 then Value! = cint(Value!)
-
- The QBNews Page 13
- Volume 2, Number 2 May 31, 1991
-
- '
- ' Find how long the string will be.
- '
- Span% = (len(Str$(Value!)) - 1)
- '
- ' Convert number to string, and remove
- ' the leading space.
- '
- XX$ = mid$(str$(Value!),1 - (Value! >=0))
- FN INT.Value$ = xx$
- END DEF
- '
- ' To avoid dividing by zero later,
- ' assign the variable HIGH# a negligable
- ' value. This means that if you try to
- ' graph all observations of zero, no
- ' error will occur.
- '
- high# = 0.02
- '
- ' Find The Highest Bar, and put it's value in HIGH#
- '
- for Bar = 1 to How.Many.Observations
- if Value!(Bar) > high# then high# = Value!(bar)
- next
- '
- ' Define the highest bar in terms of
- ' screen rows. This could be a very small
- ' number when the values being graphed
- ' are large. The largest bar will span
- ' the screen from Top.Row.Allowed to
- ' Bottom.Row.Allowed, minus 1 for the
- ' value labels, and all other bars will
- ' be scaled using PERCENT# to this largest bar.
- '
- Percent# = ((Bottom.Row.Allowed - 1) / high#)
- '
- ' Place horizontal lines on the screen.
- ' You may not want these, however. The
- ' next FOUR lines of code may be removed
- ' without causing problems elsewhere.
- '
- color 13,0,0
- for row = Bottom.Row.Allowed to Top.Row.Allowed step -2
- Locate row,2,0,0,0
- print string$(78,196);
- next
- '
- ' Draw the observations. Start The Loop.
- '
- for Bar = 1 to How.Many.Observations
- '
- color 10,0,0
- '
-
- The QBNews Page 14
- Volume 2, Number 2 May 31, 1991
-
- ' Define each value as a subset of the
- ' largest.
- '
- XX% = (Value!(Bar) * percent#)
- '
- ' Convert to screen row value.
- '
- Top%(Bar) = Bottom.Row.Allowed - (xx - Top.Row.Allowed)
- '
- ' Calculate the column on the screen.
- '
- col = (6 + (Bar - 1) * 6)
- '
- ' Start at the highest row of the bar and
- ' fill down to the lowest row allowed.
- '
- for row = top%(Bar) to Bottom.Row.Allowed
- '
- ' If the value is so small compared to the
- ' largest, it may be too small to draw on the
- ' screen. This much be checked for.
- '
- if row > 1 then
- Locate row,col,0,0,0
- '
- ' Print the bar. The characters may be changed
- ' of course to fit your particular needs. I've
- ' included some "commented-out" samples of
- ' different characters: to try them, put a
- ' squote in front of the first line, and remove
- ' the squote from the line you'd like to try.
- '
- print string$(4,219);
- 'print string$(4,178);
- 'print string$(4,176);
- '
- end if
- next
- '
- ' If you do not want the values printed at
- ' the top of the bar, remove the next FIVE
- ' executable lines that follow.
- '
- ' Find the row to place the number.
- '
- Row = (Top%(Bar) - 1)
- '
- ' If the bar is so small that the number
- ' would be placed lower than the bottom row
- ' allowed, place it on the bottom row allowed.
- '
- if Row > Bottom.Row.Allowed then row = Bottom.Row.Allowed
- '
- color 12,0,0
-
- The QBNews Page 15
- Volume 2, Number 2 May 31, 1991
-
- Locate Row,Col,0,0,0
- print FN INT.Value$(Value!(Bar));
- next
- '
- ' Pause for any key press. We're done!
- '
- while inkey$ = ""
- wend
- ----------------------------------------------------------------------
-
- 'PIES.BAS by David Rice
- ' Make all numeric variables INTEGERS
- '
- defint a-z
- '
- ' Random tile pattern function.
- '
- DEF FN Tile$
- DefInt a-z
- ti$ = ""
- char = 0
- Randomize timer
- '
- while char < 1
- Randomize timer
- char = ((8 * rnd) + 1)
- wend
- '
- for a = 1 to char
- Randomize timer
- b = int((255 - 32 + 1) * RND + 32)
- ti$ = ti$ + chr$(b)
- next
- fn tile$ = ti$
- END DEF
- '
- ' For reasons of demonstration, the number
- ' of observations (slices) in the pie chart
- ' have been randomized to a number from 2 to
- ' 12. The maximum number of slices has been
- ' set to 12, but if you can do without the
- ' legends that are placed on the left of the
- ' screen, you could make room for more slices.
- '
- start.here:
- Observations% = (rnd * 12) + 1
- if Observations% > 12 then Observations% = 12
- if Observations% = 1 then Observations% = 2
- '
- ' Set aside room for the arrays we need.
- '
- Redim Wedge!(Observations%),Degrees!(Observations%)
- Redim Angle!(Observations%),tile$(Observations%)
- Redim x%(Observations%),y%(Observations%)
- Redim Diff!(Observations%)
- '
-
- The QBNews Page 16
- Volume 2, Number 2 May 31, 1991
-
- ' Go to EGA mode, clear the screen, and
- ' set the background color to blue (attribute
- ' of 1). Attribute 15 looks good, too.
- '
- screen 8
- cls
- paint (3,3),1
- '
- ' Get random tile patterns for all observations.
- '
- for tile% = 1 to Observations%
- tile$(tile%) = fn tile$
- next
- '
- ' Find the total value for all observations.
- ' For this demonstration, these values have been
- ' randomized.
- '
- Total! = 0
- for a = 1 to Observations%
- '
- Wedge!(a) = (777 * RND)
- '
- If Wedge!(a) < 1 then Wedge!(a) = 1
- Total! = Total! + Wedge!(a)
- next
- '
- ' Scale everything down to a percent of a
- ' circle (360 degrees). Also draw the circle.
- '
- Pie.Attr% = 14
- Perc! = (total! / 360)
- circle (400,100),205,Pie.Attr%
- '
- ' Calculate the direction to turn the line,
- ' from a starting direction of zero (straight
- ' up).
- '
- Direction! = 0
- '
- ' For every observation calculate how many
- ' degrees of the circle the slice will cover,
- ' then the direction to turn.
- '
- for a = 1 to Observations%
- Degrees!(a) = (Wedge!(a) / Perc!)
- Direction! = Direction! + Degrees!(a)
- '
- ' Move to the center of the pie, without
- ' drawing a line.
- '
- Draw "BM400,100"
- '
- ' Turn the angle and then store this angle
-
- The QBNews Page 17
- Volume 2, Number 2 May 31, 1991
-
- ' for use later.
- '
- Draw "TA=" + Varptr$(Direction!)
- Angle!(a) = Direction!
- '
- ' Draw the slice.
- '
- Draw "U86"
- next
- '
- ' In order to fill the slice with a tile,
- ' we need to know the center of the slice.
- ' If we tried to PAINT outside the slice,
- ' we would get undesirable results, such as
- ' a screen full of trash.
- '
- ' Calculate for every observation.
- '
- for a = 1 to Observations%
- '
- ' If this iteration is the first, we
- ' start from zero, take the angle the slice
- ' was drawn, and find the middle between
- ' the two.
- '
- If A = 1 then
- half! = (Angle!(1) / 2)
- Diff!(1) = Half!
- else
- '
- ' For all other iterations, look for the
- ' distance between this slice and the previous
- ' one.
- '
- Half! = (ABS(Angle!(a) - Angle!(a - 1)) / 2) + Angle!(a - 1)
- Diff!(a) = (ABS(Angle!(a) - Angle!(a - 1)) / 2)
- end if
- '
- ' Throw out a circle if there's more than one.
- '
- If Half! > 359.9999! then half! = half! - 360
- '
- ' Go to the center of the pie, but do not draw
- ' any line.
- '
- Draw "BM400,100"
- '
- ' Make our new course heading good.
- '
- Draw "TA=" + Varptr$(half!)
- '
- ' Move but DO NOT DRAW up to a point
- ' almost but not quite to the circle's
- ' boundry.
-
- The QBNews Page 18
- Volume 2, Number 2 May 31, 1991
-
- '
- Draw "BU83"
- '
- ' Store this position, then calculate
- ' the same for all the other observations.
- '
- x(a) = Point(0)
- y(a) = Point(1)
- next
- '
- for a = 1 to Observations%
- '
- ' If the slice is too small to paint,
- ' do not do so. Otherwise, paint it with
- ' the proper tile.
- '
- If Diff!(a) > .5! then paint (X(a),Y(a)),tile$(a),Pie.Attr%
- '
- ' Calculate the legend bubble position ROW.
- '
- Y = 10 + (A - 1) * 16
- '
- ' Draw bubble and PAINT it with the same tile.
- '
- circle (80,y),16,Pie.Attr%
- Paint (80,y),tile$(a),Pie.Attr%
- '
- ' Calculate the percentage of the whole this
- ' slice is.
- '
- percent# = (wedge!(a) / total!) * 100
- next
- '
- call get.1.chr(ii$)
- '
- ' Like a tile pattern? Hit ALT/P
- ' and it will be saved in as a file.
- '
- If II$ = chr$(0) + chr$(25) then
- Open "Tile.Asc" for output as #1
- for a = 1 to observations%
- '
- print #1, using "Tile.Pattern$(\\) = ";mid$(str$(a),1 - (a >=0));
- '
- Size% = len(Tile$(a))
- for b = 1 to (size% - 1)
- print #1, using "CHR$(###) + ";asc(mid$(tile$(a),b,1));
- next
- print #1, using "CHR$(###)";asc(mid$(tile$(a),size%,1))
- next
- close
- call get.1.chr(ii$)
- end if
- '
-
- The QBNews Page 19
- Volume 2, Number 2 May 31, 1991
-
- if ii$ <> chr$(27) then goto start.here:
- '
- sub get.1.chr(i$) static
- defint a-z
- i$ = ""
- while i$ = ""
- i$ = inkey$
- wend
- end sub
- ----------------------------------------------------------------------
-
- 'DIR.BAS by Dave Cleary
- '
- 'One of the most useful additions to BASIC 7 PDS is the DIR$ function.
- 'This function allows you to read a directory of filenames. It also
- 'allows you to check the existence of a file by doing the following:
- '
- ' IF LEN(DIR$("COMMAND.COM")) THEN
- ' PRINT "File Found"
- ' ELSE
- ' PRINT "File not found"
- ' END IF
- '
- 'Now QuickBASIC 4.X users can have this useful function for their
- 'programs.
- '
- 'Calling DIR$ with a FileSpec$ returns the the name of the FIRST
- 'matching file name. Subsequent calls with a null FileSpec$ return the
- 'NEXT matching file name. If a null string is returned, then no more
- 'matching files were found. FileSpec$ can contain both a drive and a
- 'path plus DOS wildcards. Special care should be taken when using
- 'this on floppy drives because there is no check to see if the drive
- 'is ready.
-
- DEFINT A-Z
-
- DECLARE FUNCTION DIR$ (FileSpec$)
-
- '$INCLUDE: 'QB.BI'
-
- '----- Some constants that DIR$ uses
- CONST DOS = &H21
- CONST SetDTA = &H1A00, FindFirst = &H4E00, FindNext = &H4F00
-
- '--------------------------------------------------------------------
- 'This shows how to call DIR$ to find all matching files
-
- 'CLS
- 'FileSpec$ = "C:\QB\SOURCE\*.BAS"
- 'Found$ = DIR$(FileSpec$)
- 'DO WHILE LEN(Found$)
- ' PRINT Found$
- ' Found$ = DIR$("")
- 'LOOP
-
- '--------------------------------------------------------------------
-
- The QBNews Page 20
- Volume 2, Number 2 May 31, 1991
-
-
- FUNCTION DIR$ (FileSpec$) STATIC
-
- DIM DTA AS STRING * 44, Regs AS RegTypeX
- Null$ = CHR$(0)
-
- '----- Set up our own DTA so we don't destroy COMMAND$
- Regs.AX = SetDTA 'Set DTA function
- Regs.DX = VARPTR(DTA) 'DS:DX points to our DTA
- Regs.DS = -1 'Use current value for DS
- InterruptX DOS, Regs, Regs 'Do the interrupt
-
- '----- Check to see if this is First or Next
- IF LEN(FileSpec$) THEN 'FileSpec$ isn't null, so
- 'FindFirst
- FileSpecZ$ = FileSpec$ + Null$ 'Make FileSpec$ into an ASCIIZ
- 'string
- Regs.AX = FindFirst 'Perform a FindFirst
- Regs.CX = 0 'Only look for normal files
- Regs.DX = SADD(FileSpecZ$) 'DS:DX points to ASCIIZ file
- Regs.DS = -1 'Use current DS
- ELSE 'We have a null FileSpec$,
- Regs.AX = FindNext 'so FindNext
- END IF
-
- InterruptX DOS, Regs, Regs 'Do the interrupt
-
- '----- Return file name or null
- IF Regs.Flags AND 1 THEN 'No files found
- DIR$ = "" 'Return null string
- ELSE
- Null = INSTR(31, DTA, Null$) 'Get the filename found
- DIR$ = MID$(DTA, 31, Null - 30) 'It's an ASCIIZ string starting
- END IF 'at offset 30 of the DTA
-
- END FUNCTION
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 21
- Volume 2, Number 2 May 31, 1991
-
-
- ----------------------------------------------------------------------
- T h e T o o l S h e d
- ----------------------------------------------------------------------
-
- A Look at Crescent Software's PDQComm by Jim Harre
-
- Product Review - PDQComm 2.50
- Source: Crescent Software
- 32 Seventy Acres
- West Redding, CT 06896
- (203) 438-5300
- Price: $99.00
-
- PDQComm 2.50 is a communications add-on library written by Dave
- Cleary (your illustrious QBNews publisher) and marketed by Crescent
- Software. Strangely enough, PDQComm does work with PDQ -- as well as
- QuickBasic 4.x and BPDS 7.x. Since PDQ doesn't provide access to the
- communications ports as QB does, an add-on package is necessary for
- serial work. PDQComm provides this feature.
-
- PDQComm provides you with over 50 low and high level routines. A
- number of the procedures have been lifted from Crescent's QuickPak
- Pro and PDQ packages. The routines are small and speedy. In short,
- it is a complete serial port programmmer's toolkit.
-
- The documentation is absolutely first rate. Those of you upgrading
- from version 2.0 are in for a very pleasant surprise. Besides the
- usual excellent routine descriptions, a brief communications
- tutorial (including a short section on the infamous baud vs. bps
- controversy), connector pinouts, UART descriptions and register
- info, and a brief summary of 'Standard' Hayes commands and S
- registers are included at the end of the manual. If your desk looks
- like mine, it's nice to have just ONE reference with just about
- everything you need.
-
- Crescent has switched from the old, thin, 'blah' beige covers to
- attractively printed heavy card stock covers. This should help keep
- your manuals from being floppier than your disks. The only drawback
- to the manual (and this is a minor nit) is that they have changed
- the binding from a plastic spine to one of those metal double spiral
- bindings that get bent up easily and bind up the pages. At least,
- you could stick a small label on the old spines - these new ones
- don't work well for labeling.
-
- Unlike some add-on libraries, PDQComm provides .QLB and .LIB files
- for both QB and BPDS in one package. The source code is provided as
- with all Crescent Products. A number of demonstration programs are
- provided to acquaint you with using the routines, including a TSR
- comm program.
-
- Several new features are added in version 2.50 -
- <> Two comm ports can be open simultaneously.
- <> Ports with non-standard addresses or IRQs can be opened.
- <> A function to determine the UART type has been added.
-
- The QBNews Page 22
- Volume 2, Number 2 May 31, 1991
-
- <> You can enable/disable the FIFO buffer in 16550 UARTS.
- <> You can adjust the receive buffer size 'on the fly'.
- <> Grab status of CTS, DSR, RI, and DCD as a TYPE variable.
- <> The timeout delay is adjustable in seconds when sending data.
- <> Several routines from PDQ are now included.
-
- QuickBasic and the Basic Professional Development System
- (otherwise known as BPDS) already have communications support built
- in -- so why would anyone buy an add-on package to do something that
- Basic already does? For the same reasons you purchased QB or BPDS when
- Basica or GW-Basic was included with your DOS -- functionality and
- flexibility. One of the great failings of the routines furnished
- with QB is that you need to use ON ERROR to trap errors. This
- results in larger, slower code -- exactly what you don't need when
- working with communications. QB also has a VERY nasty habit of
- dropping Data Terminal Ready when you exit a program. If you are
- writing a series of programs to be executed, this is usually deadly
- to your modem connection since most modems will go onhook when you
- lower DTR.
-
- Over the last couple years that I've carried the QUIK_BAS echo on
- my system, there has been a continuing discussion on the merits of
- using a prewritten library of routines versus writing your own. It's
- no secret that I often use and advocate third party libraries. For
- me, the reason is simple - time is money. When you write code for a
- living, your production rate tends to directly affect your wages at
- salary review time. A hundred bucks for a comm package is a drop in
- the bucket compared to how long it would take me to develop (and
- especially debug) a similiar set of routines in assembly language.
- In a commercial setting and especially a production environment,
- downtime due to program 'quirks' is measured in thousands of
- dollars. Things must be solid the first time out - there isn't much
- time for playing around with it until you get it right. Over the
- last year in production programs, PDQComm has proved to be extremely
- stable and bug free.
-
- Much of my work with PDQComm has been to build TSR "device drivers"
- to communicate with digital scale indicators. Every one of these
- rascals tends to work differently, while the main application
- program needs to remain the same for the user. To avoid maintaining
- a dozen similiar but different programs, the main program simply
- issues an interrupt call and receives a numeric string from the
- scale.
-
- Before the program is launched, a small (8-9K) TSR driver is loaded
- that handles the grunt work of maintaining a conversation with the
- scale and responding to requests from the main program for
- information. This TSR is compiled using PDQ and PDQComm. Each
- different device has it's own driver that handles the peculiarities
- of that scale and has a common output format. By having the driver
- take over and handle an unused interrupt, all the main program needs
- to know is that when it calls INT 61H, the scale data magically
- appears - no matter what scale is attached. Because PDQComm can
- create compact code and PDQ can create TSR's, what would have been a
-
- The QBNews Page 23
- Volume 2, Number 2 May 31, 1991
-
- real drudge with ASM is now almost easy - in BASIC.
-
- To give you an idea what programming with PDQComm feels like,
- here's a small program and comments (lifted directly from the PDQComm
- manual):
-
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Besides using a syntax as close to BASIC's as possible, PDQComm
- also returns error information in the BASIC ERR function. This
- lets you easily test the success or failure of the most recent
- operations, without requiring ON ERROR. Unlike other communi-
- cations libraries you may have seen, PDQComm uses the minimum
- number of parameters possible. This greatly reduces the size of
- your programs, and also improves their speed.
-
- DEFINT A-Z 'all integers please
-
- DECLARE SUB OpenCom (Action$) 'same as OPEN "COM..."
- DECLARE SUB ComPrint (Work$) 'same as PRINT #n,
- DECLARE SUB CloseCom () 'same as CLOSE #n
- DECLARE FUNCTION BIOSInkey% () 'similiar toASC(INKEY$)
- DECLARE FUNCTION ComEof% () 'same as EOF(n)
- DECLARE FUNCTION ComInput$(NumChars) 'same as INPUT$(n,#n)
- CALL OpenCom("COM1:2400,N,8,1,RB512,XON") 'open the port
- IF ERR THEN 'oops
- PRINT "Error opening the communications port."
- END
- END IF
-
- DO
- Char = BIOSInkey% 'get what was typed
- IF Char = 27 THEN EXIT DO 'exit if it was Escape
- IF Char THEN CALL ComPrint(CHR$(Char)) 'anything else, send it
- IF NOT(ComEof%) THEN 'was anything received?
- ComString$ = ComInput$(ComLoc%) 'yes, get the characters
- PRINT ComString$; 'print them on the screen
- END IF
- LOOP 'loop forever
-
- CALL CloseCom 'close the port and end
-
- Here, the OpenCom routine is called specifying communications
- port 1 at a baud rate of 2400, no parity, 8 data bits, and 1 stop
- bit. RB512 specifies a receive buffer size of 512 bytes, and XON
- indicates that XON/XOFF handshaking is to be performed automat-
- ically. We will discuss handshaking as well as selecting an
- appropriate buffer size in a moment.
-
- Once the communications port has been opened, an "endless" loop
- is entered that alternately checks for keyboard activity and
- characters being received. If a character has been entered at the
- keyboard it is sent through the port (unless it was the Escape
- key). And if any characters have been received and are waiting to
-
- The QBNews Page 24
- Volume 2, Number 2 May 31, 1991
-
- be read, the ComInput$ function reads all of them from the receive
- buffer.
-
- The ComEof% function is used to determine if any characters are
- waiting in the buffer. ComLoc% reports how many, and ComInput$
- does the actual reading. Notice that these functions are identical
- to the equivalent BASIC functions EOF(), LOC(), and INPUT$
- respectively.
-
- The BIOSInkey function is much more efficient than the regular
- QuickBASIC INKEY$, because it returns the integer ASCII value
- of the key that was pressed. This requires less code in the BASIC
- program, since integer assignments and comparisons are simpler
- than the equivalent string operations.
-
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- As you can see, using PDQComm isn't too much different from
- standard QB or BPDS. Of course, this simple terminal program doesn't
- show off all the features of the library. You can set the amount of
- time to wait to transmit using ComPrint$. If you'd rather use RTS/CTS
- hardware handshaking instead of software XON/XOFF, it's available.
- If you want to run another program after closing the comm port but
- not drop the line, a routine called SetMCRExit allows you to select
- what happens to the state of the DTR and RTS lines when the port
- closes. PDQComm has low-level routines to handle just about any task
- you can imagine with the serial ports of your PC.
-
- What about high-level stuff? Crescent packages are famous for
- throwing in a number of BASIC routines that not only illustrate the
- usage of the low-level routines, but provide you with easy to use
- building blocks for your own programs. Several terminal programs are
- provided including one that runs as a TSR. For those of you who need
- to transfer files, there are routines for transferring an ASCII file
- (somewhat useless, in my opinion) and a set of XMODEM routines for
- both checksum and CRC (far more useful).
-
- If you need to talk to a terminal, terminal emulation routines are
- provided for TTY, ANSI (PC), VT52 & VT100 (Digital Equipment), and
- D215 (Data General). Routines are provided to define multiple
- windows on the screen - each running a different emulation if you
- wish.
-
- If you are looking for source code to a basic, high performance
- term program that you can customize to your heart's content, PDQComm
- furnishes you with enough tools and toys to keep you busy for
- months. The AnsiTerm program included works rather nicely as an
- example of what you can do with the package; it shows off both ANSI
- emulation and XMODEM file transfers. It also demonstrates the use of
- the XStat routine, a pop-up status window for tracking XMODEM
- transfers.
-
- Technical Support is something that Crescent does well. While
- digging through this package, I ran into a problem running one of
-
- The QBNews Page 25
- Volume 2, Number 2 May 31, 1991
-
- the demo programs (DemoAnsi). A call to Crescent solved the problem
- with a minimum of fuss. If I'd really read the documentation instead
- of skimming it, I'd have found the problem. Instead of reminding me
- what a dummy I was for not fully reading the manual, the person on
- the other end of the phone (Nash) kindly led me through uncommenting
- some lines of code to make things work. Microsoft could learn a few
- things about customer service from these people. (I wish they
- would!)
-
- Nothing in this world (especially in programming) is perfect, but
- PDQComm has few flaws. For those planning to write their own BBS, it
- would be nice to see more file transfer routines though it can be
- easily argued that external programs (like DSZ) can be used to
- provide that service. Other than that, and my earlier nit-picking
- about the binding, there's not much to complain about.
-
- To sum up, PDQComm is an excellent communications package for BASIC
- programmers. It has a well written manual, plenty of examples that
- will interest the novice, and plenty of routines to satisfy the more
- advanced programmer. Tech support is very good and the routines work
- as advertised. The package continues to be improved and Crescent has
- already announced that they will be selling a version of PDQComm for
- the new Visual Basic. Overall, if you are looking for a competent
- communications package, this is money well spent.
-
- **********************************************************************
- Jim Harre is an avid QuickBASIC programmer from St. Louis. He also
- runs a BBS that has been in operation since it ran on a TSR-80. You
- can call his BBS at 314-843-0001 or write to him in care of this
- newsletter.
- **********************************************************************
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 26
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- 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
- ----------------------------------------------------------------------
-
- Working with the Rodent by Daniel R. Berry
-
- The Rodent (mouse) is one of the easiest input devices for computer
- users to adapt to. It allows great flexibility for entering data,
- moving around screens and using menus. Over the last few years the
- Rodent has truly found a home with computer users. This leads you to
- wonder why new programs enter the market without mouse interfaces.
- Probably the most common reason for this oversight is the Rodent
- intimidates programmers. The pesky little critter isn't the easiest
- user interface to program for. Yet, adding a mouse interface to your
- programs is easier than most think.
-
- The mouse functions operate through a device driver such as
- MOUSE.SYS or MOUSE.COM provided with most MS-DOS compatible rodent
- species. This driver ties itself to interrupt 33H allowing the
- programmer direct accessed to the mouse functions. Several programmer
- references document this interrupt and its functions detailing the
- features and complexities of the mouse driver. Over the last few
- years I have played around with mouse interfaces and have finally
- developed a set of routines that allow me to add a mouse interface to
- any QuickBASIC program I write. The routines provide access to most
- of the mouse functions and they aren't that hard to use.
-
- To use these routines in your program you must use the following
- statement at the beginning of your program:
-
- COMMON SHARED /Mouse/ MouseChk%, MouseStat%
- (This statement is provided in the MOUSE.BI file.)
-
- The routines use these variables to track the following:
-
- MouseChk% indicates the availability of an active mouse driver
- and the status of these routines (1=Enabled / 0=Disabled).
-
- MouseStat% shows the status of the mouse cursor or pointer
- (1=On / 0=Off).
-
- Mouse is the heart of the mouse utilities. It provides access to
- interrupt 33h using INTERRUPT provided in the QB.QLB. Almost all the
- other mouse routines call Mouse to complete their functions.
-
- Usage: CALL Mouse (M1%, M2%, M3%, M4%)
-
- M1 - M4 are the system registers AX - DX respectively.
-
- MouseCheck is the second most important of these routines.
- MouseCheck can determine mouse driver availability; enable the mouse
- driver; or disable the mouse driver. This routine must be called at
- the beginning of your program if you want to use the mouse.
-
-
- The QBNews Page 27
- Volume 2, Number 2 May 31, 1991
-
- MouseChk updates MouseChk% and MouseStat% as applicable. You
- should note that when the mouse driver is installed the mouse cursor
- is set to off.
-
- Usage: CALL MouseCheck (MFlag%)
-
- MFlag% = If set to -1 the mouse will be installed, if
- available (if not already done so). If set to -2 the mouse
- routines will be disabled. Any other value will cause this routine
- to determine if the mouse has been installed. A returned value of
- 1 indicates that the mouse driver is installed, 0 indicates that
- the mouse driver has not been installed or is disabled.
-
- MouseCRT will determine or set the mouse video display page. This
- is useful when your programs use multiple display pages.
-
- Usage: CALL MouseCRT(CRT%, Flag%)
-
- The video display page is determined or set by using the CRT%
- variable. Flag% is used to toggle 0=set/1=determine.
-
- MouseInformation provides specific information for the Rodent used
- by the system. This routine provides the mouse driver software
- version and mouse type.
-
- Usage: Call MouseInformation(MouseVer$, MouseType%,
- MouseType$)
-
- MouseVer$ is the current mouse driver version.
-
- MouseType% and MouseType$ represent the following:
-
- 1 - Bus Mouse 2 - Serial Mouse 3 - InPort Mouse
- 4 - PS/2 Mouse 5 - HP Mouse
-
- MouseLeft determines the position of the mouse at the last left
- button depression. Also determines the number of depressions of the
- left button since this routine was last called. Position is returned
- in screen pixels.
-
- Usage: CALL MouseLeft (LCount%, MouseX%, MouseY%)
-
- LCount% = The number of left button depressions since the
- routine was last called.
-
- MouseLeftRC functions the same as MouseLeft except position is
- determined by screen row and column.
-
- Usage: CALL MouseLeftRC (LCount%, MRow%, MCol%)
-
- MouseLightPen will enable (1) or disable (0) mouse light pen
- emulation mode. Calls to the Basic PEN function return the last pen
- down location. Pen down is set when both buttons are depressed.
-
-
- The QBNews Page 28
- Volume 2, Number 2 May 31, 1991
-
- Usage: CALL MouseLightPen (Status%)
-
- MouseLimits will set the mouse limits restricting movement to a
- specific area. Limits are set using screen pixels.
-
- Usage: CALL MouseLimits(MouseX1%, MouseY1%, MouseX2%,
- MouseY2%)
-
- MouseX1/Y1% = Upper left corner horizontal/vertical (X/Y)
- position.
-
- MouseX2/Y2% = Lower right corner horizontal/vertical (X/Y)
- position.
-
- MouseLimitsRC functions the same as MouseLimits except the limits
- are determined by screen row and column.
-
- Usage: CALL MouseLimitsRC(MRow1%, MCol1%, MRow2%, MCol2%)
-
- MRow1%/MCol1% = Upper left corner row/column limit.
-
- MRow2%/MCol2% = Lower right corner row/column limit.
-
- MouseLocate locates the mouse cursor at a specified X and Y
- coordinate. Coordinates are set in screen pixels.
-
- Usage: CALL MouseLocate(MouseX%, MouseY%)
-
- MouseLocateRC functions the same as MouseLocate except coordinates
- are set at specified row and column.
-
- Usage: CALL MouseLocateRC(MRow%, MCol%)
-
- MouseMotion returns the horizontal and vertical mouse motion
- counters. Motion counts are in 1/200 inch increments.
-
- Usage: CALL MouseMotion(Horz%, Vert%)
-
- Horz% = Horizontal motion counter value (positive = right
- motion / negative = left motion).
-
- Vert% = Vertical motion counter value (positive = downward
- motion / negative = upward motion).
-
- MouseOn / MouseOFF turns the mouse cursor on/off as desired. These
- functions use MouseStat% to determine the status of the cursor and
- take action only when needed. This check is used to prevent the
- internal cursor flag from being modified unnecessarily.
-
- Usage: CALL MouseOn / MouseOff
-
- MouseRelease returns the position of the mouse after the button
- requested was last released. Position is returned in screen pixels.
-
-
- The QBNews Page 29
- Volume 2, Number 2 May 31, 1991
-
- Usage: CALL MouseRelease(Button%, Count%, MouseX%, MouseY%)
-
- Button% = The button to be checked (0 = left / 1=right).
-
- Count% = The number of button releases since the last call to
- this routine.
-
- MouseReset resets the mouse driver to the default values and
- updates MouseStat%.
-
- Mouse Position: Screen Center Mouse Cursor: Off
- Light Pen Emulation: On CRT Page Number: 0
-
- Usage: CALL MouseReset
-
- MouseRight determines the position of the mouse at the last right
- button depression. Also determines the number of depression of the
- right button since this routine was last called. Position is returned
- in screen pixels.
-
- Usage: CALL MouseRight(RCount%, MouseX%, MouseY%)
-
- MouseRightRC functions the same as MouseRight except position is
- determined by screen row and column.
-
- Usage: CALL MouseRightRC (RCount%, Row%, Col%)
-
- MouseSensitivity enables programmers to determine or modify mouse
- sensitivity to better suit their needs. Horizontal and vertical
- movement are defined in mickeys. One mickey equals 1/200-inch of
- mouse travel. Mickeys range from 1 to 32,767 (horizontal default is 8
- and vertical default is 16). Doublespeed sets threshold for doubling
- mouse cursor movement (default 64 mickeys/second).
-
- Usage: CALL MouseSensitivity(GetSet%, HMickey%, VMickey%,
- DoubleSpeed%)
-
- GetSet% is used to toggle 0 = Get / 1 = Set.
-
- MouseStatus determines Mouse Status to include position and buttons
- currently depressed. Position is returned in screen pixels.
-
- Usage: CALL MouseStatus(Left%, Right%, MouseX%, MouseY%)
-
- Left% = If returned as 1 then the left button is depressed.
-
- Right% = If returned as 1 then the right button is depressed.
-
- MouseStatusRC functions the same as MouseStatus except position is
- returned by screen row and column.
-
- Usage: CALL MouseStatusRC(Left%, Right%, MRow%, MCol%)
-
- RODENT.BAS provides a demonstration of these routines and designed
-
- The QBNews Page 30
- Volume 2, Number 2 May 31, 1991
-
- to give you a general idea of how the mouse interface works. If your
- rodent is having a problem working with these routines read your users
- manual to ensure that you have MS Mouse emulation active.
-
- Well, that's about it. I have included a few support routines from
- my library to give RODENT.BAS some flair and the *.BIT routines are
- needed by MOUSE.MOU to work with some of the bits returned in the
- system registers. You have everything you need to get that pesky
- rodent to work so why not put that $50 - $90 toy to some use and
- program!
-
- Please feel free to write. I am open to comments, suggestions and
- will even answer a question or two. Complaints are received only on
- Friday, must be in triplicate (no carbons please), must be signed by
- your mother, and be accompanied by a personal check for $200.00.
- (Laugh - my wife did!)
-
- [EDITOR'S NOTE]
- All source code for this article is contained in RODENT.ZIP.
-
- **********************************************************************
- Daniel Berry is a member of the U.S. Air Force. Off-duty he
- writes a utility library for QuickBASIC. Daniel may can be reached
- at 3110-C South General McMullen, San Antonio, TX 78226.
- **********************************************************************
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 31
- Volume 2, Number 2 May 31, 1991
-
- A Graphics Mouse Cursor Design System by Dr. Warren G. Lieuallen
-
- MOUSCURS.BAS will allow you to draw your own graphics cursor
- design without having to worry about all those crazy hex numbers,
- and what to do with them! You'll simply draw your cursor shape
- on the screen, and then save the data. A complete, stand-alone
- QuickBASIC program will be created which will simply define your
- cursor and turn it on. The purpose of this is for you to then
- add the rest of your program; MOUSCURS will have taken care of
- the nitty-gritty of your custom mouse cursor. For the more
- adventurous of you, you can also save only the DATA statements,
- and then do with them what you will.
-
- MOUSCURS.BAS was designed and tested on a Hercules
- monochrome system, and checked on a VGA system. It should work
- with any graphics system, but I've not used it with CGA or EGA.
- If you have trouble, feel free to fiddle with the code yourself.
-
- To use MOUSCURS.BAS, you must load QuickBASIC with CALL
- Interrupt support. The easiest way to do this is to load the
- QB.QLB quick library by entering "QB /L QB" to run QuickBASIC.
- You'll also need CALL Interrupt support for your program which
- uses MOUSCURS to define the cursor. My recommendation is to add
- the CALL Interrupt routine to your own custom quick library;
- that's what I did!
-
- Once you run MOUSCURS, you'll seen the main (and only!)
- screen. You can now use your mouse to draw a shape. Move around
- the "cursor mask" screen; pressing the LEFT button will toggle
- the individual pixels on and off. Once your shape is defined
- (you'll see a true-size representation of the cursor in the
- "Custom Cursor" window), you'll then need to work on the screen
- mask. The easiest way to do this is to click on the "Expand".
- This will copy your cursor to the screen mask window, and draw a
- border around it automatically. You can then edit it to
- perfection; watch the "Custom Cursor" window to see what the
- cursor looks like on a "normal" and "inverse" screen.
-
- Before you finish, you must also define a "hot spot". This
- is the single pixel which defines the cursor's location (e.g. the
- spot that must be inside the button you're clicking on). To
- select a "hot spot" click the RIGHT button in the cursor mask
- window. The hot spot will be indicated by an "X". However, by
- clicking in the same spot, you can define an "invisible" hot
- spot, which will be defined by a "0". The best way to learn how
- the RIGHT button works is to just play with it, and watch the
- "Custom Cursor" window to see if the spot is turned on or off.
- Also, remember to use the RIGHT button for the hot spot, and the
- LEFT button for everything else.
-
- At any time, you can also clear either of the windows by
- clicking on the "Clear" buttons. You can also copy the cursor
- mask to the screen mask by clicking on the "Copy" button.
-
-
- The QBNews Page 32
- Volume 2, Number 2 May 31, 1991
-
- Finally, as a test of your new cursor, you can click on the
- "Activate" button to replace the cursor with your own design. Be
- sure you have something defined before you do this, or you'll
- lose the cursor, and won't be able to see what you're doing! You
- can turn your cursor back off and return to the hand by clicking
- on the "DeActivate" button.
-
- Once your cursor is finished, you can save it by clicking on
- either the "Save Data" or "Save Program" buttons. "Save Data"
- does just what it says; it will save only the DATA statements
- needed to define your custom cursor. "Save Program" will create
- a stand-alone program that will define your cursor and turn it on
- (in fact, you can run this program just to see what your cursor
- looks like once you're done). Both of these options create a
- file called CURSORn, with "n" being a sequential number; you will
- not overwrite existing cursor files (old files must be deleted
- manually). Data is saved with a .BI extension; programs are
- saved with the standard .BAS extension. You can, of course,
- rename any of these files after you've created them via DOS.
-
- Finally, if you've already created some cursors, you can
- edit them by using the "Load Cursor" button. You'll be asked to
- provide the filename and extension; the data will then be loaded
- and the cursor displayed just as you had drawn it.
-
- Feel free to examine the code of MOUSCURS.BAS. It was
- written primarily as an learning exercise; there are undoubtedly
- other (and probably better!) ways to accomplish the same task.
- MOUSCURS.BAS was my first (and so far, only) graphic program, so
- please bear with me. For more details on programming mouse
- functions in QuickBASIC, refer to the QB News (volume 2,
- number 2).
-
- [EDITOR'S NOTE]
- The code for this article can be found in MOUSECUR.ZIP. This program
- will not work in the QBX environment or with far strings. This
- program also requires the DIR$ function contained in the SwapShop
- section of this newsletter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 33
-
-
- ----------------------------------------------------------------------
- T h e Q B N e w s P r o f e s s i o n a l L i b r a r y
- ----------------------------------------------------------------------
-
- Fast Screen Printing by Christy Gemmel
-
- [EDITOR'S NOTE]
- All code for this article may be found in FASTPRNT.ZIP. This article
- also refers to figures which included in FIGURES.TXT which is in
- FASTPRNT.ZIP.
-
- This article presents a rapid method of displaying a string of ASCII
- characters on the screen without updating the cursor position. The
- calling program should pass the string, the row/column co-ordinates of
- the screen location where it is to be printed and the number of the
- colour or display attribute required.
-
- Many routines in my Assembly-Language Toolbox are concerned with the
- video display, this being the primary means through which we
- communicate with the users of our program. Later, when we get around
- to developing such things as Popup Windows and Dialogue Boxes, we will
- need to acquire some pretty sophisticated screen-handling techniques.
- For now, however, let us look at the more mundane task of displaying
- text on the screen.
-
- For most applications the QuickBASIC PRINT statement is perfectly
- adequate. Because it is a general-purpose statement, however, which
- can be used to direct output to the printer or a file as well as to
- the screen, PRINT is not as fast as it might be. Moreover, to display
- a string of characters at a specific place on the screen you must
- first position the cursor with a LOCATE statement. Then, if you want
- to display the string in a different colour than the background text,
- you must issue a preliminary COLOR statement before printing. What we
- need is a screen-specific display routine that combines these three
- statements into one. Naturally, since we are going to the trouble of
- writing it in Assembly-Language, we expect it to be as fast as
- possible.
-
- Let us, then, set out our objectives for FastPrint:
-
- 1) The ROW/COLUMN location where the string is to be printed is
- specified to the routine, so that there is no need for a seperate
- LOCATE statement to position the cursor.
-
- 2) You must be able to place the string anywhere on the display,
- including the bottom line of the screen, no matter what VIEW
- PRINT parameters may be in effect.
-
- 3) Output to the bottom line of the display should not cause the
- screen to scroll.
-
- 4) You should be able to specify the colour and/or display attribute
- of the text to be printed, so there is no need for a seperate
- COLOR statement. Furthermore the attribute specified should appy
-
- The QBNews Page 34
- Volume 2, Number 2 May 31, 1991
-
- only to the text being printed, it must not effect the colour of
- any subsequent PRINT statements.
-
- 5) To obtain maximum performance, FastPrint should write directly to
- video display memory. This will be particularly useful when we
- need to output large blocks of text.
-
- This last clause needs some explanation. In general, there are two
- methods of outputting text to the screen. The first makes calls to the
- video services built into the PC's ROM-BIOS and can, consequently, be
- used by any computer that is BIOS-compatible with the IBM family of
- personal computers. This method, however, is considered to be a little
- slow by today's standards.
-
- The alternative technique bypasses ROM-BIOS completely and writes
- directly to the video display buffer. Since the display, in most PCs,
- is mapped by the video hardware to a fixed location in memory, any
- characters that are written to this area will immediately appear on
- the screen. This is the fastest method of all, but has the
- disadvantage that it will only work on computers that are hardware-
- compatible with the original IBM PC. However, since this includes all
- modern XT, AT and PS/2 class machines, it is not unduly restrictive,
- but it does eliminate some older models like the Tandy 2000.
-
- We will adopt the second method. It is, after all, the one used by 90%
- of today's software and has become something of a de facto standard in
- its' own right. This is the only way we can achieve some real
- performance in our programs.
-
- The bulk of the work is done by a short assembly-language procedure
- that is designed to be called from QuickBASIC. It can be part of a
- Quick Library for use in the programming environment or assembled into
- a single module that can be linked to stand-alone programs compiled
- with BC's /O switch. I will show you both methods later.
-
- Although short, FASTPRINT illustrates some important features of
- mixed-language programming that I will discuss in some detail. It was
- written for MicroSoft's Macro Assembler (MASM) version 5.1 and makes
- use of the simplified segment directives that are a feature of that
- assembler. This lets us define the Memory Model of the routine to
- match that of the calling program.
-
- .model medium
-
- All QuickBASIC programs use the MEDIUM memory model, which means that
- all simple data fits within a single 64K segment, although the program
- code may be greater than 64K. When we enter the routine, therefore,
- the DS (Data Segment) register is already pointing to the segment
- containing the string of characters we will be printing and we can use
- near pointers, offset from DS, to address this string. The main
- procedure, however, must be declared FAR so that the Code Segment (CS)
- register is set correctly when it is called. FastPrint is the name you
- will be using when you call this routine from your program, declare it
- PUBLIC so that QuickBASIC can find it.
-
- The QBNews Page 35
- Volume 2, Number 2 May 31, 1991
-
-
- public FastPrint
-
- Now for the routine itself, here are the first few lines:
-
- .code
-
- FastPrint proc far
- push bp ; Save Base pointer
- mov bp,sp ; Establish stack frame
- push es ; Save Extra Segment
- push si ; and index pointers
- push di
-
- Remember that QuickBASIC uses the Medium Memory model. This means that
- we can't assume our assembled routine will be linked into the same
- code segment as the main program that calls it, so the procedure must
- be declared as FAR. The next two lines are concerned with setting up a
- pointer to the stack so that we can easily get at the parameters that
- the routine is expecting, more about this in a minute. We must also
- preserve the values of any segment registers (except for CS, which has
- already been modified by the call itself) that are altered by the
- routine, also the Index registers DI and SI if they are used.
-
- When the routine is called, QuickBASIC pushes a two-byte value
- corresponding to each of the supplied parameters onto the program
- stack. These are followed by the return address which, since this is a
- FAR procedure, is a four-byte pointer (Segment and Offset) to the
- statement following the call to FastPrint. When we have finished
- saving our own working registers, the stack will look like this:
-
- Figure 1.1 Stack contents after entry into FastPrint.
-
- Note that, since we copied the contents of the Stack Pointer to BP
- immediately after BP itself was pushed, This register can now be used
- as a fixed pointer through which we access the parameters that were
- passed. Normally, QuickBASIC passes these arguments as 2-byte offset
- addresses, which point to the named variables in the program's Data
- Segment.
-
- We, however, are going to override this and pass the numeric arguments
- BY VALue, forcing QuickBASIC to copy the actual contents of the
- variables into the appropriate stack locations. Then all we need do is
- read the data supplied, directly into the target registers:
-
- mov ax,[bp+12] ; Get row number
-
- Passing by VALUE saves us having to hunt for the variables containing
- our data and so makes our routine faster and more compact. It also,
- incidently, makes it easier if we ever need to convert FastPrint to a
- C function, since the C language does it by default. We'll make use of
- the technique in a minute or two, but first we must collect some
- important information about the computer our program is running in.
-
-
- The QBNews Page 36
- Volume 2, Number 2 May 31, 1991
-
- Although we have decided that our program need only support machines
- that are hardware-compatible with the IBM PC family, this still leaves
- a variety of video environments to cater for. We must, for example,
- find out whether the host computer is fitted with a colour or
- monochrome display adaptor since the address of the screen buffer we
- will be writing to depends on this. Computers with EGA and VGA cards,
- moreover, can switch between up to eight display pages so, if our
- program is running in one of these machines, we must make sure that
- FastPrint sends its output to the correct page. Last, but not least,
- if the host system does have an EGA or VGA we must find out whether
- the current screen is set to a height of 25, 43 or 50 rows, so that we
- can format our printing properly.
-
- We could, of course, code the instructions that collect this data
- directly into FastPrint itself. It is likely, however, that many
- other programs we write will need the same information. Better, then,
- to make our video system identification function an independent
- procedure that can be called by whichever program needs it. This saves
- us repeating the same block of code in every screen routine and makes
- the Toolbox tighter and more efficient.
-
- call VideoType ; Get video parameters
-
- Since VideoType, as we have just decided, is going to be called by
- many Toolbox routines, we must make sure that the linker can find it
- when your program is built. This means that we have to declare it
- PUBLIC by putting the following line at the top of the source code.
-
- public VideoType
-
- Note that versions 5 and 5.1 of MASM have a bug which makes all
- procedures PUBLIC by default. If you are using either of these
- versions of the Macro Assembler, therefore, this line is not strictly
- necessary. However, because we cannot rely on this feature being
- retained in future releases, it is best to use an explicit PUBLIC
- declaration.
-
- VideoType also needs some space to store the data it collects. Insert
- the following lines in your source file, immediately after the .CODE
- segment declaration but before the first PROC statement. I will
- explain them more fully in a few moments.
-
- SnowFlag db 0 ; Snow prevention flag
- VideoRam dw 0B000h ; Default video segment
- VideoPort dw 03BAh ; Default video status port
- Param1 label word
- Mode db 7 ; Current screen mode
- Columns db 80 ; Current screen width
- Param2 label word
- Rows db 25 ; Current screen height
- ActivePage db 0 ; Current video page
-
- Notice that VideoType, like FastPrint itself, is a FAR procedure. This
- is necessary if it is to be called by routines in seperately-linked
-
- The QBNews Page 37
- Volume 2, Number 2 May 31, 1991
-
- modules that may have different Code segments.
-
- See the VideoType routine in DISPLAY.ASM.
-
- VIDEOTYPE
-
- As with all assembly-language procedures, it is good practice to
- preserve the contents of any registers that will be changed by the
- routine and are not used to return data. Do this by pushing the
- contents of these registers onto the stack immediately after entry and
- popping them again just before you return.
-
- Our first task is to check the current display mode to see if we are
- running in a machine with a colour or monochrome monitor. The easiest
- way is to call a service routine in the computer's BIOS and let the
- system do the work for us. Fortunately there are many such services,
- grouped by the hardware devices that they interface with, and with
- each group being accessed through a dedicated software interrupt. The
- Video services are called through Interrupt 16 (10 Hex).
-
- To gather the information we want, VideoType issues an INT instruction
- together with the interrupt number. Interrupt 16 (10 Hex) is a gateway
- to some very useful video services. When called with AH set to 15 (0F
- hex) it returns with the current display mode in AL, the number of
- screen columns in AH, and the current video page in BH.
-
- An interrupt is a signal to the microprocessor that its attention is
- required. When one occurs, the processor suspends the current task and
- jumps to a routine that is designed to deal with the event that
- triggered off the interrupt, this routine is called an interrupt
- handler. When the handler has done whatever is required, control
- returns to the next instruction in the interrupted task and execution
- resumes from there. Just like the return from a BASIC subroutine.
-
- The 80x86 family of processors allows for 256 diffent interrupts,
- numbered from 0 to 255. Some are dedicated to hardware devices, every
- 54.936 milliseconds, for example, the 8253 timer chip generates
- interrupt number 8, which executes a subroutine to update the system
- clock and date and time flags.
-
- Most interrupt numbers, however, are reserved for software interrupts
- that can be generated by programs, using either the assembly-language
- INT instruction or the QuickBASIC CALL INTERRUPT statement.
-
- You call an interrupt handler, not by specifying its address, but by
- supplying the interrupt number you require. The actual addresses are
- stored in an interrupt vector table at the very beginning of memory,
- being written there by the initialisation process when your computer
- is booted-up. When an interrupt is issued, the processor simply looks
- up the table entry for that interrupt number and jumps to the address
- contained there. Because different models of computer have different
- hardware configurations as well as different versions of DOS and BIOS,
- the actual addresses in the table will vary from machine to machine.
- But, since the interrupt numbers themselves do not change, programs
-
- The QBNews Page 38
- Volume 2, Number 2 May 31, 1991
-
- that use them are still portable between all computers in the PC
- family.
-
- When an interrupt is executed, the processor makes the following
- actions:
-
- 1) The FLAGS register, the current Code Segment (CS) and the
- Instruction Pointer (IP) are saved on the stack.
-
- 2) The address of the handling routine is looked up in the Interrupt
- Vector Table, starting at location 0000:0000 in memory. Since
- each table entry is four bytes long, the correct entry can be
- found by multiplying the interrupt number by four.
-
- 3) The segment and offset address of the interrupt handling routine
- are loaded into the CS:IP registers, transferring control to that
- routine.
-
- 4) The code at the handling routine is executed until the
- processor encounters an IRET (RETurn from Interrupt) instruction.
-
- 5) The original Instruction Pointer, Code Segment and Flags register
- are then restored from the stack and execution proceeds with the
- instruction that followed the original interrupt call.
-
- Figure 1.2 The interrupt sequence used on computers such as the
- IBM-PC, which use the Intel 80x86 family of micro-
- processors.
-
- On return from Interrupt 16, VideoType first checks the current video
- display mode. Notice that we are looking to see if AL contains a value
- of 7. This is only returned if your computer has a monochrome display.
- If AL does equal 7, we can skip the rest of the procedure, since our
- local variables are set for a monochrome display by default. Anything
- other than 7, however, means that we have a graphics adaptor to
- contend with and must adjust the defaults accordingly.
-
- Two variables are involved. The first, labelled VIDEORAM is set to the
- segment address of the display memory we will be using. This is at Hex
- 0B000 for mono adaptors (the default) and 0B800 for colour adaptors.
- The other variable is the number of the hardware port that controls
- the video display. For mono adaptors this is numbered 3BA (hex). For
- colour machines the port number must be reset to 3DAh.
-
- Notice that we are accessing local variables through the CS register,
- using a SEGMENT OVERIDE directive; e.g.
-
- mov CS:VideoRam,0B800h
-
- The reason for this is that the DS register, which is normally used to
- address data, is still pointing to the calling program's Data Segment.
- We need to leave DS intact so that we can use it to get at our display
- string when we eventually return to FastPrint. For now, however, we
- carry on and store the screen width and display mode, which were
-
- The QBNews Page 39
- Volume 2, Number 2 May 31, 1991
-
- returned in the upper and lower bytes of AX, in another of our local
- variables. The active page, which is in BH, is saved, temporarily, on
- the stack until we can obtain the screen height to go with it.
-
- In computers fitted with EGA and VGA adaptors the video hardware adds
- its own set of video functions to the BIOS video services. One of
- these, interrupt 16 sub-function 17/48, returns amongst other things,
- the information we require; the screen height in rows set in DL.
-
- What if our host computer doesn't have an EGA or VGA? No need to
- worry, calling an interrupt service that doesn't exist will not cause
- an error. All that happens is that the function returns with registers
- unchanged. Since other video adaptors only allow screen heights of 25
- rows, if we previously set DL with this number, the correct value will
- still be in the register after the interrupt call. Even if an EGA or
- VGA isn't present. Notice, however, that the value we set is actually
- 24. BIOS routines typically use a numbering system based on zero
- rather than one, so a screen height of 25 rows is returned as 24. This
- is why we increment the return value by one, before storing it in its
- destination variable.
-
- One final thing that VideoType must do is to detect whether the host
- computer is using a Colour Graphics Adaptor (CGA). The reason for this
- is that there is a special problem with CGAs when we write directly to
- video memory. I'll go into more detail about this later. For now we
- just need to set a flag to indicate the presence of a CGA.
-
- How do we find out if this computer has a CGA? Easy. The trick is to
- find a video interrupt service which only works on machines fitted
- with an EGA or VGA and set an impossible value into one of the return
- registers. If, after the interrupt call has completed, this register
- is unchanged then an EGA or VGA is not present and we must have a CGA.
- Remember we have already eliminated systems with Monochrome Display
- Adaptors (MDA). Video service 18/16 is a suitable candidate. It
- returns a value of between 0 and 3 in BL to indicate the amount of
- memory, in 64K blocks, installed on your video card. VideoType presets
- BL with 16 (10 hex) before calling the interrupt. If this value is
- still in BL when the interrupt returns, then we have a CGA to contend
- with and we must set the SnowFlag accordingly.
-
- Before popping its saved registers and returning, VideoType's final
- task is to retrieve all the information it collected from local
- storage. Back in FastPrint, we resume our task by isolating the
- information that is needed next, the current screen dimensions. These
- are collected in DX so that we can check them against the start
- position of the string to be printed, making sure that it is within
- the screen boundaries.
-
- mov dh,ah ; Load screen dimensions
- mov dl,bl ; into DX
-
- QuickBASIC, conventionally numbers screen rows from 1 to 25 and screen
- columns from 1 to 80. Since the ROM-BIOS co-ordinate system uses row
- and column numbers starting from zero we need to convert our
-
- The QBNews Page 40
- Volume 2, Number 2 May 31, 1991
-
- parameters to base zero before we can start printing. At the same
- time it would be a good idea to check for legal values.
-
- This is where we start collecting the parameters that were passed to
- us by our caller. First the row co-ordinate:
-
- mov ax,[bp+12] ; Get row number
- dec al ; Convert to base zero
- cmp al,0 ; Top screen row
- jae Fast_01 ; Jump if not below
- xor al,al ; Don't go over the top!
- Fast_01:
- cmp al,dl ; Bottom row?
- jb Fast_02 ; Go no further
- mov al,dl ; Substitute maximum
- dec al ; row number
-
- Now let's do the same for the column co-ordinate supplied:
-
- Fast_02:
- mov bx,[bp+10] ; Get column number
- mov ah,bl ; into AH
- dec ah ; Convert to base zero
- cmp ah,0 ; Leftmost column?
- jae Fast_03 ; Jump if not below
- xor ah,ah ; Don't fall off the screen
- Fast_03:
- cmp ah,dh ; Rightmost column?
- jb Fast_04 ; Go no further
- mov ah,dh ; Substitute maximum
- dec ah ; column number
-
- Once we have a set of legal row and column co-ordinates we need to
- translate them into the actual address in the video display buffer
- where the data will be written. Since, like VideoType, this is a task
- that our Toolbox routines will have to perform often, we had better
- write a seperate procedure to handle it.
-
- Fast_04:
- call ScreenAddress ; Calculate target address
-
- ScreenAddress, again, must be a FAR procedure so that it can be called
- from programs in seperately-linked modules that may have different
- Code segments. As always, we preserve on the stack any working
- registers that are not used to return values. The row and column co-
- ordinates which ScreenAddress will convert into a memory address are
- supplied in the low and high bytes of AX.
-
- See the ScreenAddress routine in DISPLAY.ASM.
-
- ADDRESSING MEMORY
-
- The 80x86 CPU uses two registers to fully describe memory addresses.
- It does this by dividing the absolute address by 16 and storing the
-
- The QBNews Page 41
- Volume 2, Number 2 May 31, 1991
-
- result of this calculation in a SEGMENT register. Then another, INDEX,
- register is used to hold the remainder, which is called the OFFSET of
-
- the object from the start of the segment. The byte at absolute decimal
- location 753666, for instance, would be addressed as;
-
- Segment = (753666 \ 16) = 47104 Offset = (753666 MOD 16) = 2
-
- Using hexadecimal (base 16) notation, makes it much simpler to work
- with segments and offsets, since all you need do is shift all digits
- of the absolute address, one place to the right, the rightmost digit
- falling off to become the offset part of the address:
-
- 753666 = B8002 (Hex) --------> Segment B800 : Offset 0002
-
- More conventionally, this is written by assembly-language programmers
- as B800:0002. It is actually the memory address of the character
- displayed in the second column of the top row of the screen (if your
- computer has a color adaptor).
-
- Using this method, the PC's 1-megabyte of address space can be divided
- into 65536 (0 - FFFFh) possible segments. Each segment starts at a
- different paragraph boundary (a paragraph is a block of 16 bytes) and
- contains up to 65536 (0 - FFFFh) different byte addresses. Any segment
- larger than 16 bytes, of course, will overlap with the segments
- starting at the next and subsequent paragraph boundaries.
-
- To obtain the address of the position on the screen where our text is
- to be printed, ScreenAddress's first move is to copy the supplied
- column co-ordinate into BH. It then obtains the screen width, in
- columns, from the local variable that was previously set by VideoType.
- Since each column on the screen takes up two bytes of memory, one for
- the character stored there and the other for the attribute that
- governs how it is displayed, we now need to multiply the screen width
- by two to get the number of bytes per row. In assembly-language this
- is easy; the SHL instruction shifts all bits of the binary number in
- BL one position to the left, effectively doubling its value.
-
- Since AL contains the row number, we can now multiply it by BL and
- get the byte offset of this row. The MUL instruction extends the
- result of this calculation into AX, which is why we moved the column
- number into BH out of the way. Now we must use SHL again to convert
- this into bytes and add the result to AX. We now have the target
- address, offset from the beginning of the screen and it only remains
- for us to copy it into DI, one of the index registers used for
- addressing memory.
-
- If PCs only used a single screen page we could return right away.
- However machines with CGA, EGA and VGA cards are capable of displaying
- multiple pages so we must find which one is currently on the screen.
-
- We already have the page number from VideoType but BIOS makes it even
- easier by providing the actual address of the current display page,
- which is what we really want.
-
- The QBNews Page 42
- Volume 2, Number 2 May 31, 1991
-
-
- We don't need to use an interrupt call this time. BIOS maintains its
- own data block at segment 40h in low memory and this contains, amongst
- many other things, the exact information that we're looking for. The
- address of the current display page is stored as a two-byte number at
- offset 4Eh into this block. Notice, however, that ScreenAddress
- actually uses 0000:044Eh to reach it. This is because it is slightly
- quicker to clear the ES segment register than it is to load it with a
- value. The actual memory location remains the same.
-
- Figure 1.3 PC Memory map highlighting the BIOS data area in low RAM
-
- Once we have the page offset all that remains is to add it to the row
- and column offset that is already in DI. VideoType has already stored
- the video segment and port address for us so we just need to retrieve
- these parameters before returning to FastPrint.
-
- The result of all this register juggling is that we now have the ES:DI
- register pair pointing to the address in memory where output is to
- start. DX is also loaded with the address of the video controller
- port. Now we're ready to find the string to display.
-
- What QuickBASIC passes when a string is specified as parameter to an
- external procedure, is a pointer to a STRING DESCRIPTOR in the Data
- Segment. This is a four-byte block of data of which the first two
- bytes are the string length. In QuickBASIC strings may be up to 32767
- bytes in length:
-
- Figure 1.4 Structure of the String Descriptor passed by QuickBASIC
-
- The second two bytes of the string descriptor contain a pointer to the
- first character of the string itself. This is an offset address,
- relative to the start of DGROUP, QuickBASIC's default Data Segment.
- This is the address that is returned by the SADD function in
- QuickBASIC. When used with a string, VARPTR returns the address of the
- string descriptor instead.
-
- If you are using Microsoft's BASIC 7 Professional Development System
- then the method of passing strings is rather different. See the
- sidebar for more details.
-
- Before going any further, we should check that there is a string to be
- printed. If the first two-bytes of the string descriptor evaluate to
- zero, a null string has been passed so there is no point in proceeding
- further. Consequently we set the AX register to an error code and jump
- to the exit. It is good practice to return a code indicating the
- success or failure of an operation when we leave, even if the calling
- program will not read it. Most DOS applications return such an
- ERRORLEVEL as a matter of course.
-
- Well the string is there, so we can load its address, which is the
- second two bytes of the string descriptor, into our other Index
- Register, SI.
-
-
- The QBNews Page 43
- Volume 2, Number 2 May 31, 1991
-
- mov bx,[bp+8] ; Index to string descriptor
- mov cx,[bx] ; Get string length
- cmp cx,0 ; Make sure it isn't
- ja Fast_05 ; a null string
- mov ax,1 ; If so set Error code
- jmp short Fast_07 ; and abort
- Fast_05:
- mov si,[bx+2] ; DS:SI==> string data
- mov ax,[bp+6] ; Get display attribute
- xchg ah,al ; into AH
- cld ; Clear direction flag
-
- This is a good opportunity to get the final parameter, the display
- attribute we are to use, into the AH register. The CLD (Clear
- Direction Flag) instruction ensures that any subsequent string
- manipulation instructions move data forwards in memory. Now that we
- are ready to start printing, the processor registers are set up as
- follows:
-
- Segment Registers: ES points to the current video segment.
- DS points to the calling program's DATA segment.
-
- Index Registers: DI points to the offset address, relative to ES,
- where the string will be copied to.
- SI points to the beginning of our source string,
- relative to the DS register.
-
- General Registers: DX contains the video status port address.
- CX contains the length of the source string.
- AH contains the display attribute to be given to
- each output character.
-
- The last section of code is a simple loop that copies each byte of the
- source string to its destination address in video memory. Instead of
- using a MOV instruction to copy each byte of the string into the AL
- register before transferring it to the screen, we use another assembly
- instruction, LODSB.
-
- Fast_06:
- lodsb ; Get a byte from the string
-
- LODSB is one of a set of string manipulation primatives built into the
- Intel family of microprocessors. Why they are called 'primitive' I
- don't know. They are, in fact, extremely powerful. In just one
- statement, LOSB will load a byte from the address pointed to by DS:SI
- into the AL register and then automatically increment SI to point to
- the next byte. If we were to prefix it with a REP instruction it would
- repeat the whole operation for the number of times that the value in
- CX is set to. This, as you can see, is just the thing for loops.
-
- In fact, if we didn't have to cater for systems with CGA video cards,
- we could do the remainder of the job in just one line. LODSB has a
- companion instruction, MOVSB, which, as it's name implies, moves the
- byte at DS:SI to a destination address pointed to by ES:SI. In this
-
- The QBNews Page 44
- Volume 2, Number 2 May 31, 1991
-
- case both of the index registers, SI and DI, are incremented ready for
- the next byte to be transfered. Like LODSB, MOVSB takes a REP prefix
- and, since we already have the length of our string in CX, all that
- would be necessary is to enter the instruction ....
-
- rep movsb ; Shift the whole string
-
- ... and the job would be done.
-
- But we do have to contend with CGA cards so our task is a little more
- complicated and, since it is one that we will need to repeat in other
- programs, we had better do it in a sub-routine.
-
- call ScreenWrite ; Write a byte and attribute
- loop Fast_06 ; Repeat for each character
-
- See the ScreenWrite routine in DISPLAY.ASM.
-
- The problem with CGAs occurs only when we write directly to video
- memory. If the 6845 CRT Controller attempts to fetch a character from
- the screen buffer whilst data is being written to that same location,
- the resulting interference will cause 'snow' or glitches to appear on
- the screen. We can prevent this happening by making sure that we only
- output to the display when the 6845 is not reading from it.
-
- Fortunately we do not have to wait long, since every 12 microseconds,
- the 6845 performs what is known as a horizontal retrace. During this,
- time the controller is not doing any reading so it is safe for our
- program to write to the display.
-
- We can detect when a horizontal retrace is in progress by testing bit
- zero of the video adaptor status port, its address is now in DX,
- remember? If this bit is set then a retrace is under way. In practice
- we let any current retrace complete and wait for the next to begin,
- before moving data. This ensures that we have we a full retrace period
- in which to place the character and attribute byte into their proper
- buffer addresses.
-
- Computers with monochrome adaptors and those with more modern versions
- of the CGA, do not experience 'snow' problems and, if you are sure
- that you will only be using FastPrint in such systems, you are welcome
- to leave out the routine. Me, I wouldn't bother. Using it ensures a
- good clean display, no matter which computer you use the program in,
- and the increase in processing time does not slow your programs down
- enough to be noticed. It is a lot faster than PRINT, at any rate.
-
- All that remains, now that our string has been output to the display,
- is to tidy up the stack and return safely to the QuickBASIC program
- that called us.
-
- First we recover all the registers that were pushed on entry to the
- routine.
-
- xor ax,ax ; Report success
-
- The QBNews Page 45
- Volume 2, Number 2 May 31, 1991
-
- Fast_07:
- pop di ; Clean up the stack
- pop si
- pop es
- pop bp
-
- The final return instruction must adjust the stack so that any
- parameters that were originally passed are now discarded. Our routine
- received four parameters, each of which took up two bytes of stack, so
- we issue a RET 8 to decrement the Stack Pointer by eight, ensuring
- that the correct return address is popped back into CS:IP.
-
- ret 8 ; Return to Quick BASIC
- FastPrint endp
-
- end
-
- Last of all, don't forget to tell the assembler where the current
- procedure and program end.
-
- Here is the full listing of FastPrint again. If you type it in, don't
- forget to include the code for the three procedures ScreenAddress,
- ScreenWrite and VideoType in their proper places before the final END
- directive. Notice that, since all the routines in the file are related
- to the video display, I have given it the name DISPLAY.ASM. I suggest
- that you use this name as well. We are going to add to it in the
- ensuing chapters.
-
- ASSEMBLY AND LINKING
-
- Since all the procedures we have written so far are concerned with the
- video display, I propose that we call the source file that contains
- them DISPLAY.ASM. Save it as such and then assemble it using the
- following command:
-
- MASM /V/W2/Z display;
-
- The /V (VERBOSE) switch instructs the assembler to report statistics
- such as the number of program lines and symbols processed.
-
- The /W2 switch sets the assembler's WARNING level to maximum. This
- instructs it to report statements that may result in inefficient code,
- as well as actual errors. It reports, for example, when you have
- issued a normal JMP instruction where a short jump will do. This helps
- you write tighter code.
-
- The /Z switch directs MASM to list any lines, where errors are found,
- on the screen. Another help in debugging.
-
- If you use an assembler other than MASM, of course, the above
- instructions do not apply. In this case consult your own assembler's
- documentation.
-
- If the assembly is successful, you will have a file, DISPLAY.OBJ,
-
- The QBNews Page 46
- Volume 2, Number 2 May 31, 1991
-
- containing the assembled object code. This is all ready for linking
- directly to compiled Quick BASIC programs which are to be run from the
- DOS command line. You can link it with the instruction:
-
- LINK yourprog DISPLAY;
-
- (where 'yourprog' is the name of your own program)
-
- If you want to use FastPrint in the QuickBASIC environment, you will
- also have to include it in a Quick Library. Use the Linker for this as
- well, the command is:
-
- LINK /QU DISPLAY,,,BQLB45.LIB;
-
- BQLB45.LIB is the standard library interface module supplied with
- QuickBASIC 4.5, (if you are using the Extended QuickBASIC which comes
- with MicroSoft's BASIC 7 PDS, the equivalent module is named
- QBXQLB.LIB). Whichever one you use, make sure that it is in the
- current directory when you issue the LINK command. You should now have
- a file DISPLAY.QLB.
-
- If you've got this far, you will, no doubt be anxious to try out
- FastPrint in a QuickBASIC program. Let's start with a small one which
- draws coloured boxes on the screen, just to test that it is working
- properly. We'll call it PANELS.BAS.
-
- Start up QuickBASIC with the following ...
-
- QB PANELS.BAS /L DISPLAY.QLB
-
- The first thing to do is to declare our routine as an external
- procedure. We won't be expecting it to return any value, so we declare
- it as a SUBprogram rather than a FUNCTION.
-
- DECLARE SUB FastPrint (BYVAL Row%, BYVAL Col%, Text$, BYVAL Attr%)
-
- Make sure that all the parameters are correctly listed and of the
- correct type. Integers for the Row, Column and Attribute arguments and
- a string for the text which we will be supplying.
-
- Okay, was that fast enough for you?
-
- What you have done, in effect, is to add your own extension to the
- QuickBASIC language. Provided that the procedure is properly declared
- at the top of your program, and the object file is linked or in an
- attached Quick Library, you can use FastPrint as easily as any other
- QuickBASIC statement or function. You don't even have to preface it
- with the CALL directive, nor do you need to enclose the parameter list
- with parentheses.
-
- If you are not sure how to work out proper values for the colours and
- attributes which you want your display to have, Appendix A goes into
- this in some detail. By all means experiment, your taste is very
- likely different from mine. You may even want to write special SUBS
-
- The QBNews Page 47
- Volume 2, Number 2 May 31, 1991
-
- for commonly-used attributes, for instance ...
-
- SUB RevPrint (Row%, Column%, Text$) STATIC
- FastPrint Row%, Column%, Text$, 112
- END SUB
-
- ... calls FASTPRINT with the attribute set for REVERSE VIDEO text,
- Black characters on a White background (actually Green on monochrome
- monitors.
-
- SUB NormalPrint (Row%, Column%, Text$) STATIC
- FastPrint Row%, Column%, Text$, 7
- END SUB
-
- ... calls FASTPRINT with the attribute set to normal video. Just like
- PRINT in fact, only faster.
-
- By the way, what did all those panels remind you of? That's right,
- WINDOWS. Well you'll just have to wait. The Windows will be opened in
- a future article.
- ----------------------------------------------------------------------
-
- ROM-BIOS Video Services
-
- ROM-BIOS provides services which enable us to determine the current
- display mode, select the video page to which output will be directed,
- find the current cursor position and the character and attribute
- underneath it, and to selectively scroll a specified area of the
- display. They are accessed by loading the AH register with the number
- of the service required, and then issuing interrupt 16 (10 Hex). You
- may have to preset values into other registers, depending upon the
- service being called.
-
- Unless used for returned values, the contents of the BX, CX and DX
- registers are preserved across these calls. Likewise, the segment
- registers will be returned intact. You should not assume, however,
- that the contents of other registers will be maintained. Remember also
- that the system, used by the BIOS for numbering screen rows and
- columns, differs from QuickBASIC in that the x/y co-ordinate of the
- top-left corner of the screen is regarded as being 0,0 instead of 1,1.
-
- ----------------------------------------------------------------------
- INT 10h Get current video display mode. all systems
-
- Call with: AH = 0Fh (15 decimal)
-
- Returns: AL = display mode (see table below)
- AH = screen width in columns
- BH = cureent display page
-
- Mode Resolution Colours Screen Mode Resolution Colours Screen
-
- ----------------------------------------------------------------------
- 0 40 x 25 2 text 1 40 x 25 2 text
- 2 80 x 25 2 text 3 80 x 25 16 text
- 4 320 x 200 4 graphics 5 320 x 200 4 graphics
-
- The QBNews Page 48
- Volume 2, Number 2 May 31, 1991
-
- 6 640 x 200 2 graphics 7 80 x 25 2 text
- 8 160 x 200 16 graphics 9 320 x 200 16 graphics
- 10 640 x 200 4 graphics 13 320 x 200 16 graphics
- 14 640 x 200 16 graphics 15 640 x 350 2 graphics
- 16 640 x 350 16 graphics 17 640 x 480 2 graphics
- 18 640 x 480 16 graphics 19 320 x 200 256 graphics
- ----------------------------------------------------------------------
-
- Computers fitted with the Monochrome Display Adaptor (MDA) will only
- support mode 7, (80 x 25 character text).
-
- Modes 4 and 6 correspond to QuickBASIC's SCREEN 1 and SCREEN 2.
-
- Modes 8, 9 and 10 are only available on the IBM PCjr (and Tandy 1000).
-
- Modes 13 and up are only available on machines fitted with EGA or VGA
- adaptors, Mode 16 supports either 4 or 16 colours, depending upon the
- amount of video memory available.
- ROM-BIOS VIDEO SERVICES
-
- ----------------------------------------------------------------------
- INT 10h Get Font information EGA, VGA, MCGA only
-
- Call with: AH = 11h (17 decimal)
- AL = 30h (48 decimal)
- BH = 00h for default character set.
-
- Returns: CX = point size (number of bytes per character)
- DL = screen height in rows - 1
- ES:BP => address of character definition table
-
- Note: information about the alternative character sets
- provided by your video adaptor is obtained by loading
- BH with the appropriate font number. See your EGA or
- VGA reference manual for more details.
-
- ----------------------------------------------------------------------
- INT 10h Get Configuration information EGA, VGA only
-
- Call with: AH = 12h (18 decimal)
- BL = 10h (16 decimal)
-
- Returns: BH = display type (0 = colour, 1 = monochrome)
- BL = video memory installed
- (0 = 64K, 1 = 128K, 2 = 192K, 3 = 256K)
- CX = Adaptor feature bits and DIP switch settings
-
- Notes: BL will still return a value of 3 even if more than
- 256K of video memory is installed.
-
- for more information about the meaning of the value returned in CX
- consult your EGA or VGA reference manual.
- ----------------------------------------------------------------------
-
-
-
- The QBNews Page 49
- Volume 2, Number 2 May 31, 1991
-
- Using FastPrint with BASIC 7
-
- If you intend using FastPrint with programs compiled under the BASIC 7
- Professional Development System then a few changes are necessary. This
- is because BASIC 7 uses Far Strings which gives strings a memory
- segment of their own instead of putting them into DGROUP, the default
- Data Segment pointed to by DS.
-
- To enable you to find the address of a far string, BASIC 7 provides a
- built-in function called StringAddress. This must be declared at the
- head of your source code file between the .MODEL and .CODE directives,
- so that the Linker can fix-up references to the function when your
- program is built:
-
- extrn StringAddress: proc
-
- This done, you should rewrite the lines between labels Fast_04: and
- Fast_06: as follows:
-
- Fast_04:
- push ax ; Save display co-ordinates
- mov ax,[bp+8] ; Index to string descriptor
- push ax ; Call BASIC for
- call StringAddress ; string parameters
- pop bx ; Recover co-ordinates
- jcxz Fast_06 ; Abort if a null string
- mov ds,dx ; String segment to DS
- mov si,ax ; DS:SI==> string data
- mov ax,bx ; Co-ordinates to AX
- call ScreenAddress ; Calculate target address
- mov ax,[bp+6] ; Get display attribute
- xchg ah,al ; into AH
- cld ; Clear direction flag
-
- Notice that, just like QuickBASIC 4.5, we still have to obtain the
- address of the string descriptor from our argument list. With BASIC 7,
- however, we pass it on to StringAddress by pushing it back onto the
- stack before calling this function. On return, BASIC 7 will have set
- our registers as follows:
-
- DX = segment of target string
- CX = length of target string
- AX = offset of target string
-
- The explanation in the BASIC 7 manual and on-line Help implies that
- you need to call a seperate function, StringLength, to find the length
- of the string. In practice this is not necessary since StringAddress,
- itself, returns this information in CX.
-
- **********************************************************************
- Christy Gemmell resides in England and was the major author of the
- Waite Group book QuickBASIC Bible. Christy also has a shareware
- called the Assembly-Language Toolbox for QuickBASIC. Christy can be
- reached in care of this newsletter.
- **********************************************************************
-
- The QBNews Page 50
- Volume 2, Number 2 May 31, 1991
-
-
- ----------------------------------------------------------------------
- P o w e r P r o g r a m m i n g
- ----------------------------------------------------------------------
-
- An Improved Cloning Algorithm by Larry Stone
-
- Who ever said that there is no such thing as a bug free program
- must have been very familiar with my work. To my chagrin, the code I
- wrote for "The QBNews", Vol. 1, No. 3, concerning programs that clone
- to themselves, contained a bug that could hang your system. In the
- endeavor to wipe the egg off of my face, I present a new function that
- corrects this error and, as a side benefit, executes faster and, for
- those of you who use the PDQ library, is compatible with PDQ.
-
- The function, SearchEXE$, as originally published, used a DO...LOOP
- terminated with the instruction, "DO WHILE NOT EOF(1)". In the event
- that the program does not contain the special marker in the EXE's
- token area (refer to QBNWS103), the loop would execute indefinitely
- because the EOF is never read with files opened in the BINARY mode.
- The solution is one line of code:
-
- IF Bytes + Portion& >= FiSize& THEN EXIT DO
-
- The other major change presented here is the substitution of GET
- for INPUT$(). The GET will operate faster and will make the code
- compatible with Crescent's PDQ.
-
- FUNCTION SearchEXE$ (FileName$, Key$, DatLen) STATIC
-
- '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 16000 byte "GET" cuts the marker in two, you don't have to worry
- 'about it because we adjust the file pointer accordingly.
-
- Bytes = 16000 '16000 bytes to read with each pass.
- BytesToData& = 0 'Initialize it to zero.
- Portion& = 1 'Initialize to file's 1st byte.
- CountToKey = 0 'The count to Key$ location.
-
- Handle = FREEFILE 'Get a number for the file.
- OPEN FileName$ FOR BINARY AS #Handle
- FiSize& = LOF(Handle)
-
- DO
-
- '---- 16000 bytes is to many so, reduce it.
- IF Bytes > FiSize& THEN Bytes = FiSize&
-
- '---- If Portion& + Bytes is greater than FiSize&, reduce Bytes.
- IF Bytes + Portion& > FiSize& THEN Bytes = FiSize& - Portion&
-
- '---- Point into the file (Portion&) and input "Bytes".
- A$ = SPACE$(Bytes) 'Configure the string to "Bytes" length.
- SEEK #Handle, Portion& 'SEEK to the portion.
-
- The QBNews Page 51
- Volume 2, Number 2 May 31, 1991
-
- GET #Handle, , A$ 'Using GET works with PDQ & is faster.
-
- CountToKey = INSTR(A$, Key$) 'Is Key in A$?
- IF CountToKey THEN 'Yes, we found the Key!
-
- '---- Calculate were the data is located.
- BytesToData& = Portion& + CountToKey + LEN(Key$) - 1
-
- A$ = SPACE$(DatLen) 'Configure the string to DatLen.
- SEEK #Handle, BytesToData& 'SEEK to the data location.
- GET #Handle, , A$ 'Now get the data.
- SearchEXE$ = A$ 'Set the function.
- CLOSE #Handle 'Close the file.
- A$ = "" 'A little garbage collection
-
- EXIT FUNCTION
- END IF
-
- '---- We've reached the end of the file and did not find our
- ' Marker$. This prevents an endless loop.
- IF Bytes + Portion& >= FiSize& THEN EXIT DO
-
- '---- We subtract the key length in case it was split by our GET.
- Portion& = Bytes + Portion& - LEN(Key$)
-
- LOOP
-
- CLOSE #Handle
- PRINT "Error. Could not find key!"
- END
-
- END FUNCTION
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 52
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- N e w a n d N o t e w o r t h y
- ----------------------------------------------------------------------
-
- Custom Control Factory for Microsoft Visual Basic by Desaware
-
- Desaware has announced the Custom Control Factory version 1.0, a
- companion product to Microsoft Visual Basic which permits the user to
- create a rich variety of custom button controls without the need for
- special programming.
-
- The Custom Control Factory has been developed to bridge the gap
- between the standard controls included with Visual Basic and custom
- controls which require advanced programming with the Windows Software
- Development Kit and Control Development Kit for Visual Basic. Custom
- Control Factory buttons are created interactively from within the
- Visual Basic design environment without the need for special
- programming. A runtime version of the product can be distributed with
- compiled Visual Basic applications without further licence fees.
-
- The Custom Control Factory version 1.0, along with over fifty sample
- controls, is being introduced at only $48 and will be available
- immediately after the release of Visual Basic version 1.0.
-
- You can contact Desaware by calling 408-377-4770.
-
-
- If you have a new product or an upgrade to an existing product you
- would like announced in The QBNews, please send info to:
-
- The QBNews
- P.O. Box 507
- Sandy Hook, CT 06482
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 53
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- F u n a n d G a m e s
- ----------------------------------------------------------------------
-
- ASCII Art -- A Piece of Computer History by Charles Graham
-
-
- In The Beginning ...
-
- folks created ASCII Art. Before ANSPAINT, THEDRAW, GIFs and all
- the rest, before color and sound and animation techniques, before CGA,
- EGA and VGA, people used COPY CON, EDLIN or their favorite text editor
- to produce art similar to the typewriter art of earlier, pre-PC
- generations.
-
- Over a number of years, I have collected 12 of these pictures from
- bulletin boards and individuals. For all I know, these are the only
- examples of ASCII art that remain. Evidently, most ASCII artists were
- people who liked to draw full-figured nude women. I have never seen
- an ASCII picture of anything but this particular subject. To the best
- of my knowledge and belief, all of the pictures that come with this
- collection are of unknown origin and are in the public domain.
-
- I have always felt these low-tech creations were worth saving if
- only for historic or nostalgic purposes -- like the early efforts of
- cave dwellers when they drew stick figures of buffalo on the walls of
- their abode.
-
- ASCII art is created by using lower-ASCII characters starting with
- ASCII 32 (the blank or space character). To my knowledge, no
- upper-ASCII (8th bit on) graphics or foreign language characters were
- ever used.
-
- Even using this limited palette, however, viewing and printing the
- pictures always presented certain problems. When using the DOS TYPE
- command, only a small fraction of the work is on screen at any moment,
- and the work is badly out of proportion. Printing them can also be
- tricky because the default values of most printers (a horizontal pitch
- of 10 characters per inch and a vertical pitch of 6 lines per inch)
- produces images that are too long and contain too much white space.
- So I created ASCIIART.BAS
-
- What Is ASCIIART.BAS?
-
- ASCIIART solves the on-screen viewing problems by translating the
- characters that make up an ASCII picture into color attributes. It
- uses these attributes to put pixels on your screen. The resulting
- image is perhaps closer to the way the artist originally envisioned
- his subject then the DOS TYPE command could ever allow. On EGA
- systems, the picture is small but high- resolution and may contain up
- to five colors plus black. On CGA systems, the picture is of medium
- size and resolution and may contain up to three colors plus black.
- ASCIIART does not support monochrome systems.
-
-
- The QBNews Page 54
- Volume 2, Number 2 May 31, 1991
-
- Color Selection
-
- I began the color selection process with what I thought was a
- logical assumption: ASCII artists would instinctively choose
- characters with more "weight" to denote shading and less "weight" to
- denote highlights. I defined "weight" as the amount of ink that hits
- the paper when a particular character is printed.
-
- I put my dot matrix printer into draft mode and printed all the
- printable characters. I used a magnifying glass and inspected each
- one. I counted and recorded the number of dots used to print each
- character and divided them into six "weight" groups.
-
- Then through trial and error I began associating different colors
- with different "weight" groups until I began to get a pattern that
- "worked." Further refinement and tinkering developed the pattern that
- comes hard coded in ASCIIART.BAS.
-
- Because different ASCII artists favored different characters to
- draw with, the method by which ASCIIART assigns color attributes to
- characters is a compromise. However, for the twelve ASCII pictures I
- have managed to collect, I believe it is the best compromise available.
-
- Users who want to experiment with color selection can easily do so
- by altering the DATA statements at the end of ASCIIART's main module
- as well as the FOR/NEXT loops in SUB loadarray. You can come up with
- some rather garish renditions without much effort.
-
- Printing The Pictures
-
- ASCIIART also assists you in making a decent looking copy of an
- ASCII picture on your printer. The printer parameters that I have
- found work best are:
- -- Condensed Print, i.e., a horizontal pitch of 17 characters per
- inch or close to it
- -- Near Letter Quality (NLQ or double-strike) printing as opposed
- to Draft Quality printing
- -- Uni- as opposed to Bi-directional printing, and
- -- a vertical pitch of 7/72nds of an inch, i.e., approximately 10
- 1/4 lines per inch.
-
- To set these parameters on IBM printers, the following ASCII
- characters need to be sent:
- -- ASCII 15 (to enter condensed mode)
- -- ASCII 27 and 71 (to enter NLQ mode)
- -- ASCII 27, 85 and 49 (to enter unidirectional mode)
- -- ASCII 27, 65and 7 (to store a vertical pitch of 7/72")
- -- ASCII 27 and 50 (to begin using the stored vertical pitch).
-
- To produce the best possible rendition, ASCIIART will automatically
- send the correct control codes and escape sequences to supported
- printers before printing the pictures. And it allows those who don't
- want to send any control codes or escape sequences not to do so.
-
-
- The QBNews Page 55
- Volume 2, Number 2 May 31, 1991
-
- ASCIIART also invites the owners of non-supported printers to enter
- their own control codes and escape sequences to set the correct
- printer parameters. Entering "C" (for Custom) at the printer
- selection screen will allow such users to do this.
-
- Printing Other Pictures
-
- ASCIIART has a feature that will allow you to print or view other
- ASCII pictures, should you come across one or care to create one.
- Place the picture in the same directory as all the other files
- included with this collection and name it OTHER.ASC. Then, when you
- are prompted for the name of the picture, enter the name OTHER. You
- can even view your word processing documents this way -- if you'd like!
-
- In Closing
-
- To help keep this edition of The QBNews at a reasonable size, at
- the Editor's request only 2 of the 12 available ASCII pictures have
- been included. The full set of 12 may be downloaded as ASCIIPIC.ZIP
- on the Crescent Support BBS at no cost. If calling Crescent is
- inconvenient, the same set is available from the author on a 360K
- diskette for $3.00 to cover the cost of materials, postage and
- handling.
-
- I find ASCII art to be quaint and entertaining. If you come across
- or create any good ASCII pictures I'd appreciate your sending me a
- copy.
-
- Enjoy!
-
- *********************************************************************
- Charles Graham is a division head for a local government agency in St.
- Louis County, Missouri. He also teaches QuickBASIC part time at a
- local community college. He is the author of several shareware
- products including MOVIES . ON . LINE and Quick Dial. He can be
- contacted at Post Office Box 58634, St. Louis, MO 63158, and on the
- National QuickBASIC Conference.
- *********************************************************************
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 56
- Volume 2, Number 2 May 31, 1991
-
-
-
- ----------------------------------------------------------------------
- Q B N e w s S p e c i a l R e p o r t
- ----------------------------------------------------------------------
-
- Special Preview of Visual Basic by Dave Cleary
-
- On May 20, 1991, Microsoft announced the long anticipated Visual
- Basic Windows Development Environment. Steve Gibson calls it the
- "masterstroke of the decade". Stewart Alsop calls it "the perfect
- user programming environment - for the 1990s". But what does Visual
- Basic mean to me and you, the QuickBASIC developer?
- First, I'm going to start out telling you what Visual Basic is and
- isn't. Visual Basic isn't an upgrade to QuickBASIC. VB is a whole new
- product that requires all new tools and a totally different thought
- process in regards to designing your programs. This is because VB
- creates Microsoft Windows programs and writing Windows programs is
- like write for a whole new operating system. Instead of calling DOS
- to perform needed functions, you call the Windows API (Application
- Programming Interface).
- Windows is an Event Driven environment. This is why writing
- programs in VB requires a different thought process. When you create
- a VB program, the majority of your subs and functions will not be
- invoked by you. Instead, Windows will invoke them depending on
- actions performed by the user. We will go deeper into event driven
- programming later in the article.
-
- The Visual Basic environment isn't as sophisticated as the
- QuickBASIC environment. Although VB does contain many features of the
- QB environment, some are left out. The biggest omission is the fact
- you can not set up a watchpoint on a variable. Instead, VB allows you
- to go the an immediate window to view or set variable values. VB also
- lets you insert Debug.Print statements throughout your code to print
- values to your immediate window as the program runs. VB does contain
- QB's threaded p-code technology allowing you to change code on the
- fly without a recompile. The amusing thing is that C and Pascal
- programmers who try VB think it is the greatest thing since sliced
- bread. I feel, however, that QB programmers who try VB will be a
- little disappointed - at first.
- VB is probably the easiest and most productive Windows development
- environment around. For instance, I can create a Windows file manager
- that contains a drive list, a directory list, and a file list, and
- give the user three push buttons with the choice of editing, running,
- or deleting the selected file. All this can be done with about ten
- lines of code. Of course, creating sophisticated programs still
- require a good amount of work and skill by the programmer.
-
- Creating programs with VB is a two step process. The first step is
- to create your user interface. This is done with VB's visual form
- designer and a collection of controls. A control is an object like a
- push button, a text box, or a timer event. VB comes with 15 such
- controls, but VB also lets you add custom controls. This effectively
- lets you extend the VB environment. To create a custom control, you
- need to use either C or ASM and the Windows SDK. However, numerous
- third party vendors will be selling libraries of custom controls.
-
- The QBNews Page 57
- Volume 2, Number 2 May 31, 1991
-
- A control has properties, events and methods. A property is a
- physical characteristic of the control. For instance, the text in a
- push button is a property of that control. You are allowed to set and
- read properties of controls when you create them (design time), and
- when you execute your program (run time).
- After you are down drawing your user interface a setting up your
- default control properties, you are ready to start coding. The big
- difference is that most of your code will be associated with a
- control event. An event is basically an action by the user that has a
- subprogram associated with it. This is how you program for Windows
- event driven environment. For instance, when you draw a push button
- on the screen, certain events are associated with it. One of these
- events is when the user clicks the button. VB creates a procedure
- called Command1_Click. Command1 is the default name given to the
- first push button you draw, but you can change it to whatever you
- like by setting its control name property. The code you put in this
- sub is executed every time a user clicks the button.
- Finally, controls have methods associated with them. A method can
- be thought of as an executable statement of the control. For
- instance, VB has a List Box control. You add items to the list box by
- using the AddItem method.
- If you aren't totally confused by now, then I'm suprised. The
- above is not meant to teach you how to program in VB, but rather to
- show you how different it is. This is why I feel porting existing QB
- programs over to VB will be difficult at best. Now the question is
- "Should I buy VB?". If you plan on doing any Windows development at
- all, then the answer is a resounding yes. If you don't plan on
- writing any Windows programs, but use Windows as your environment of
- choice, then the answer is still a resounding yes. You will be able
- to create those little utilities you wished you had, but haven't
- found yet and you will be able to do it in short order. If you hate
- Windows, or don't own an 80286 or 80386 machine, then don't bother.
- You won't be able to use VB anyway.
- Registered users of any Microsoft BASIC product can buy VB from
- Microsoft for $99, half off list price. You can call Microsoft at
- 1-800-426-9400 or wait for a coupon to appear in your mail. Also, I
- have started a Windows BASIC conference on Fidonet. This conference
- is for the discussion of all Windows BASIC products, not just VB.
- Sysops interested in linking up to this conference should contact me
- at 1:141/777. Also, if you are interested in checking out some actual
- VB applications, you can give my BBS a call at 203-426-5958.
-
- *********************************************************************
- Dave Cleary is an electronics engineer for Vectron Labs in Norwalk,
- CT. Besides being a Visual Basic beta tester, Dave is also the author
- of Crescent Software's PDQComm and is the publisher of this
- newsletter. He can be contacted on Compuserve at 76510,1725, on
- Prodigy at HSRW18A, and on Fidonet at 1:141/777.
- *********************************************************************
-
-
-
-
-
- The QBNews Page 58
-
-
- ----------------------------------------------------------------------
- E O F
- ----------------------------------------------------------------------
-
- Receiving The QBNews
-
- The QBNews is distributed mainly through BBS systems around the
- world. Some of the networks it gets distributed through are SDS
- (Software Distribution System) and PDN (Programmers Distribution
- Network). Ask the sysop of your local board about these networks to
- see if there is a node in your area.
-
- The QBNews can also be found on CompuServe in the MSLang
- (Microsoft Language) forum. It can be found in file area 1 or 2 of
- that forum. Just search for the keyword QBNEWS. The QBNews will also
- be available on PC-Link. I send them to Steve Craver, who is the BASIC
- Programming Forum Host on PC-LINK and he will make them available. I
- would appreciate anybody who could upload The QBNews to other services
- such as GENIE since I don't have access to these.
-
- I have also set up a high speed distribution network for people
- who would like to download The QBNews at 9600 baud. The following
- boards allow first time callers download privileges also. They are:
-
- Name Sysop Location Number Node #
- ---------------------------------------------------------------------
-
- Treasure Island Don Dawson Danbury, CT 203-791-8532 1:141/730
-
- Gulf Coast BBS Jim Brewer New PortRichey,FL 813-856-7926 1:3619/20
-
- 221B Baker St. James Young Panama City,FL 904-871-6536 1:3608/1
-
- EMC/80 Jim Harre St. Louis, MO 314-843-0001 1:100/555
-
- Apple Capitol BBS Bob Finley Wenatchee, WA 509-663-3618 1:344/61
-
-
- Finally, you can download The QBNews from these vendors BBS's:
-
- The Crescent Software Support BBS 203-426-5958
-
- The Microhelp BUG BBS 404-552-0567
- 404-594-9625
-
-
- You do not have to be a customer of these vendors in order to download
- The QBNews, but the Microhelp BBS only allows non-members 15 minutes
- of time per call.
-
- If you would like to receive The QBNews on disk, I offer a yearly
- subscription for $15.00. This includes four disks containing each
- issue as it is published. If you would like a disk with all the back
- issues of The QBNews, please enclose an additional $5.00. The pricing
-
- The QBNews Page 59
- Volume 2, Number 2 May 31, 1991
-
- structure is as follows:
-
- Base Price for 1 Year - $15.00
- Disk with Back Issues - $5.00
- 3.5" disk surcharge - $5.00
- Canada and Mexico surcharge - $5.00
- All other foreign orders - $10.00
-
- The base price includes 5.25" 360k disks. Send a check or money
- order in U.S. funds to:
-
- The QBNews
- P.O. Box 507
- Sandy Hook, CT 06482
-
- Please be sure to specify what archive format you want. The
- QBNews normally uses PKZip as it's archiver.
- ----------------------------------------------------------------------
-
- Submitting Articles to The QBNews
-
- The QBNews relies on it's readers to submit articles. If you are
- interested in submitting an article, please send a disk of Ascii text
- of no more than 70 characters per line to:
-
- The QBNews
- P.O. Box 507
- Sandy Hook, CT 06482
-
- Articles can also be submitted via E-Mail. Send them via Compuserve to
- 76510,1725 or via FidoNet to 1:141/777. I can be reached at the above
- addresses as well as on Prodigy as HSRW18A.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The QBNews Page 60
-
-