                 OnLine's Electronic Magazine (EMAG)
                               Issue #5
                                   

The fifth issue of OnLine's Electronic Magazine (EMAG) is available
for downloading in the Software library. The file is EMAG5.ARC.
Microsoft has created this magazine to provide our OnLine customers
with information about the OnLine service, including techniques on how
to most effectively use the service. We also hope the magazine will
encourage you to send us feedback so that we can provide the best
possible service to you, our OnLine customers.

                          Table of Contents
                          -----------------

Product Support Services Is Taking Off --
Internationally........................................by Deb Chastain

Knowledge Base Search Help: Queries....................by C.J. Pilgrim

Microsoft Technical Tips................by MS OnLine Support Personnel
(The information in these articles may also be found in the Knowledge
Base by searching on the appropriate Q number shown in parentheses.)
   
   FAT Versus HPFS File System Information (Q50213)
   New Method of Starting Programs in OS/2 Version 1.20 (Q50620)
   Making an Application HPFS Aware for Version 1.20 (Q57842)
   Installing Version 1.20 DUALBOOT (Q51673)
   Copying Files from FAT Drive to HPFS Drive in 1.20 (Q51807)
   Configuring a Secondary HPFS Partition in Version 1.20 (Q51686)
   .TYPE Extended Attribute Information (Q57542)
   PM and LAN Manager Printing Information (Q52203)
   Playing of Metafile Can Result in Out of Memory Error (Q51993)
   Blanking Out the Password in a Dialog Box (Q52208)
   Storing a Multipaged Document in a Metafile (Q57424)
   Disabling Key Combinations Such As CTRL+ALT+DEL (Q57419)
   Setting Up OS/2 LAN Manager to Use Replicator in 2.00 (Q57836)
   Avoiding File Access/Locking Problems (Q52205)
   Load-Time and Run-Time Dynamic Linking Overview (Q59745)

Microsoft FORTRAN 5.00..............................by Debbie Watkins
(The information in these articles may also be found in the Knowledge
Base by searching on the appropriate Q number shown in parentheses).

   FORPATCH Available in Software Library (Q51298)
   Reading Environment Variables from FORTRAN 5.00 (Q48957)
   OS/2 Graphic Routines Available with FORTRAN 5.00 GRTEXTP.LIB
      (Q50600)
   Graphics Routines, Unresolved Externals, and FGRAPH.FI & FGRAPH.FD
      (Q48025)
   C Compatibility and FORTRAN 5.00 Libraries (Q49446)
   Opening More Than 20 Files with FORTRAN 5.00 (Q48797)
   FORTRAN Reserved Filenames (Q50332)
   VAX Extensions Available with FORTRAN 5.00 (Q50504)
   
Presentation Parameters and Combination Boxes
for OS/2 Version 1.20.....................................by Joe Hayes
                                   
Creating and Using a Dynamically Linked Version of
the C Run-Time Library................................by Rick LaPlante
                                   
C Run-Time Routines Cannot Be Placed in an Overlay..by Renata Bachelor

Programming the Mouse for a Hercules Monochrome
Graphics Card..........................................by Tony Claflin

Answers to Common Questions About Microsoft
QuickBASIC Version 4.50.................by Edna Kainz and Steve Elston


======================================================================
                                   
 Microsoft Product Support Services Is Taking Off -- Internationally!

                           by Deb Chastain


There are currently 14 Microsoft subsidiaries in various locations
around the globe. They are: England, Sweden, Germany, France, Spain,
Holland, Italy, Australia, Canada, Mexico, Brazil, Japan, Korea, and
Taiwan.

The mission of International Product Support is to "Make sure that
Microsoft's services to customers are the best in the software
industry in each country."

To provide this high quality support, Microsoft has made a large
investment in personnel and technology. The support staff in each
country is responsible for providing the highest quality support in a
timely manner to Microsoft customers via telephone calls, letters,
faxes, and electronic Service Requests.

International support staff members around the world recently received
a new support tool -- PRISM. PRISM provides them with an up-to-date
knowledge base of technical information, the ability to receive and
respond to customer-generated Service Requests via Microsoft OnLine,
and the ability to monitor and track customer activity. PRISM is an
internally developed OS/2 application that uses Microsoft LAN Manager
and SQL server to full advantage. With the release of PRISM, all of
Microsoft's international PSS customers are on equal footing with the
U.S. customers because of the 24-hour update capabilities our internal
network provides.

This is an important step for Microsoft's international support
organizations, and one that will greatly benefit Microsoft's
international customers.

The subsidiaries have set individual service and quality goals for the
OnLine product, and several subsidiaries are actively advertising and
selling the OnLine product to customers. Currently, the subsidiaries
in Europe, Canada, and Australia are selling OnLine and striving
toward their projected goals. The subsidiaries in the Far East and in
Mexico and South America will develop marketing plans for OnLine and
begin selling in July. Below is a list of subsidiary telephone numbers
for inquiries about local OnLine availability:

   Country                          Telephone Number
   -------                          ----------------
   
   Reading, England                 (44)(734) 391-123
   Stockholm, Sweden                (49)(89) 461-070
   Munich, Germany                  (46)(8) 752-5600
   Paris, France                    (33) 69-86-46-46
   Madrid, Spain                    (34)(1) 262-7000
   Copenhagen, Holland              (31) 25-03-13181
   Milan, Italy                     (39)(2) 210-7201
   Sydney, Australia                (61)(2) 452-0288
   Ontario, Canada                  (416) 673-9728
   Mexico City, Mexico              (52)(5) 525-2121
   Sao Paulo, Brazil                (55)(11) 530-4455
   Tokyo, Japan                     (81)(3) 221-7230
   Seoul, Korea                     (82)(2) 780-0286
   Taipei, Taiwan                   (886)(2) 504-3122
   

The subsidiaries aren't in this alone! They have various organizations
at Microsoft in Redmond, Washington, to help them provide high quality
support to their customers. The following three groups provide support
to the subsidiaries on various issues: the International Product
Support Services Team, the International Sales Support Team, and the
International Product Development Group.

International PSS works primarily with the support organizations to
help deliver tools, technical training, and information, which will in
turn help the subsidiary support staff provide support to the
customers. The International Sales Support Team provides sales support
to the marketing and retail groups in the subsidiaries who are selling
Microsoft products, and keeps customers informed of prelate programs.
The International Product Development Group works with the
subsidiaries to localize products for release into the international
marketplace. Customers play an important role in helping us build
better localized products by providing feedback directly to our
Product Support personnel in the subsidiaries.

The subsidiaries, with the assistance of these three organizations,
have built a strong worldwide support team for Microsoft customers. We
look forward to serving you in the future.


======================================================================
                                   
                 Knowledge Base Search Help: Queries

                          by Charles Pilgrim


Before pursuing the closing puzzle of my last article, a short history
lesson is in order. It is commonly known in literary circles that
Charles Dickens was paid serially. For those who do not understand the
jargon of the writing industry, being paid serially means that the
author is paid based on the number of words in the article or story.
For example, at a base rate of $0.03 per word, a 5000 word article or
story would return $150.00. This is hardly enough to pay the groceries
for the time it took to write the article.

As a consequence of being a serial author, Dickens adjusted his
writing style to increase the number of words in his stories, thereby
increasing the amount he received. By converting all of the "of the
person" to "the person's," "Great Expectations" could have been about
half the length. Now, what does this have to do with searching the
Knowledge Base and the Software Library?

Consider the number of words composing the two queries (shown below,
taken from the "no hit" list) that I used in my last article. (Also
consider the costs associated with connect time while performing these
searches.)

   prod(mouse) and ibm and word and date(x891011 -to- x999999)
   
   prod(mouse) and ibm and prod(word) and 5

In the first query, the phrase "and ibm" and the date function are
likely not helping; in the second query, "and ibm" is probably not
helping, and having two prod functions in the same query presents a
problem. (Remember that each article is keyed to only one product.)
Removing these extraneous phrases, and adjusting, yields the following
queries:

   prod(mouse) and word
   
   prod(mouse) and word and 5.*

At the time I tried these queries, the first returned three articles;
the second, two. Begging the pardon of Aesop, the moral of this story
is to use as few words and phrases as possible when composing a query.
(Why did I add the wildcard on the version number? The complete and
totally honest reply is pure, unadulterated laziness. I didn't want to
spend the time or try my brain remembering what 5.00 sub-versions of
Word, if any, were shipped -- besides, it's fewer keystrokes.)

Do these queries return the information that was being sought?
Possibly, but I think not. The problem in this case is not returning
too many articles, but too few. I suspect the query is seeking
information about problems with the mouse while running Word 5.00. As
such, the following query might be a more reasonable start in locating
the desired information:

   prod(word) and mouse

Of course, the large number of articles returned by this query
requires refining the query somewhat, but it provides enough returned
articles that the desired information is only a matter of another
phrase or two away.

Up to now, my articles have centered on querying the Knowledge Base.
The Software Library also uses the same query structure as the
Knowledge Base, and many of the querying practices described in
previous articles work equally well -- especially succinctness.

The Knowledge Base and the Software Library are similar in many
respects, but differ in others. For example, the prod function that
simplifies searching in the Knowledge Base does not exist in the
Software Library -- beyond the DATE and TITLE functions, the Software
Library does not have additional, customized functions.

The Knowledge Base consists of a large number of text articles that
are searched according to the phrases in a query. The Software Library
consists of a number of uploaded files, each file having a unique S-
Number (identical to a unique Q-Number in the Knowledge Base), a title
line, and a description (the combination of the file, the title and
the description is referred to as a document). When querying the
Software Library, the title line and the descriptions are searched
based on the phrases of the query. Note that the files themselves are
NOT searched.

The Knowledge Base and the Software Library are interconnected through
the use of keywords, the unique S-Numbers, and the unique Q-Numbers.
Also, for each file in the Software Library, at least one article
exists in the Knowledge Base that references that Software Library
file.

Now that most readers are scratching their heads trying to decipher
what this all means, let's look at the interconnections a little
closer. The primary keyword in the Knowledge Base that connects the
Knowledge Base and Software library is "SOFTLIB". SOFTLIB is used in
Knowledge Base queries as follows:

   softlib and prod(word)
   prod(c) and softlib
   prod(fortran) and softlib

These queries return the articles for the specified products that
reference files in the Software Library. When I tested this, the third
query, FORTRAN, returned one article. The article title is "Q51298
FORPATCH Available in Software/Data Library." Reading the article, I
learn this file is a patch for the first pass of the FORTRAN 5.00
compiler as well as the high-capacity compiler. I also learn that the
S-Number for this file is S12450.

Armed with this information, the Software Library can now be queried
using "S12450". Since S-Numbers are unique, one document is returned
for the file described in Knowledge Base article Q51298. (S-Numbers
appear in the titles of the Software Library documents, but unlike the
Knowledge Base, entering "TITLE(S12450)" is not necessary to return
the unique document.)

The above discussion shows how to locate and use an S-Number from the
Knowledge Base to find a document in the Software Library. Once the
Knowledge Base article is found, the Software Library can also be
queried using the Q-Number of the article, which returns the same
document in the Software Library. Whether the S-Number or the Q-Number
is used to query the Software Library is inconsequential UNLESS the
Knowledge Base article references more than one Software Library
document. If this is the case, using the Q-Number returns all Software
Library documents that are referenced by the Knowledge Base article.

Let's perform a Dickensian review: Knowledge Base articles that
reference Software Library documents contain the keyword "SOFTLIB";
the unique S-Number referenced in a Knowledge Base article is used to
locate the document in the Software Library; and the Q-Number of the
Knowledge Base article that references a Software Library document can
be used to query the Software Library. (No, I don't get paid serially.
Repetition is the rote of learning; besides, I'm naturally wordy.)

This article has shown how to locate references in the Knowledge Base
to Software Library documents, and how to use the information
contained in these Knowledge Base articles to query the Software
Library and find the document. In closing, I will state that it is
possible to go from the Software Library back to the Knowledge Base to
locate the Knowledge Base articles that reference a document in the
Software Library.

Having brought that up, it is now a fine time to present this issue's
querying puzzle. Correct the following Software Library queries, then
locate the Knowledge Base articles that reference the returned
documents. (The corrected queries may return quite a few documents;
just locate the matching Knowledge Base articles for a couple or a
few.)

   dde and os2
   prod(winsdk)
   prod(quickc)

Since you've suffered through Dickens so patiently, I'll leave you
with more than just the above gruel: this article contains all the
information you need; and remember the uniqueness of the
interconnections.


======================================================================
                                   
                       Microsoft Technical Tips
                                   
                by Microsoft OnLine Support Personnel
                                   
                                   
               FAT Versus HPFS File System Information


Listed below is information on FAT versus HPFS file systems:

FAT = File Allocation Table
---------------------------

FAT is the file system used by MS-DOS and OS/2. Filenames can have up
to eight characters for the filename and three characters for the
filename extension. For example, "88888888.333". Alpha-numeric,
underscore, and hyphen characters are allowed in filenames.

HPFS = High Performance File System
-----------------------------------

HPFS is an optional addition to OS/2 Version 1.20. It allows for
longer filenames (up to 255 characters) and case sensitivity. Blanks
are also allowed in the middle of a filename (for more information,
query in this Knowledge Base on "metacharacter and o_os2sdk and
1.20"). For example:

   LongCaseSensitive.Names  and blanks

HPFS is 40 percent faster than a FAT system (with a range of 20-500
percent). The cluster size is 512 bytes (FAT is 4096 bytes); this
saves disk space.

An HPFS drive cannot be formatted with the MS-DOS FORMAT command. It
must be formatted from OS/2 with HPFS arguments. An HPFS drive is NOT
recognized by MS-DOS. If you try to access an HPFS drive from MS-DOS,
you receive an "invalid drive specification" error.

An HPFS drive is recognized by OS/2 Version 1.20, and the OS/2 Version
1.20 DOS compatibility box, although only DOS-legal (8.3) filenames
will be displayed.


======================================================================

         New Method of Starting Programs in OS/2 Version 1.20


In Version 1.10, OS/2 launches applications using the Start Programs
menu. Under OS/2 Version 1.20, there no longer is a Start Programs
menu. Instead, there are multiple, user-defined Group menus that are
used to launch your applications.

Despite this difference, the way in which programs are started is
essentially the same as it is under OS/2 Version 1.10. That is, the
program group menus are oriented toward applications rather than
documents. You use the program menus to indicate what application you
want to start, and then you indicate to the application what document
(if any) you want the application to process.

The File Manager (known as the File System under OS/2 Version 1.10)
provides a more object-oriented approach to using your computer. The
File Manager displays documents with a corresponding icon (the icon
can be a default icon, or a user-associated icon) and allows you to
associate a particular document with one or more programs. You then
can select and launch a document along with its associated application
in a single step using either the mouse or the menus. You also can do
this with the File System under OS/2 Version 1.10; however, the OS/2
Version 1.20 File Manager makes more effective use of icons.


======================================================================

          Making an Application HPFS Aware for Version 1.20


The following changes are necessary to make an application HPFS aware.

There is a new keyword that must be used in your module definition
file (.DEF file) to mark your application as HPFS aware. Place the
LONGNAMES directive on the same line as the NAME directive in your
.DEF file. For example, for a VIO window compatible application called
FOO that recognizes long HPFS filenames, you would use the following
statement in your .DEF file:

   NAME FOO WINDOWCOMPAT LONGNAMES

The LONGNAMES directive tells LINK to set the NEWFILES bit in the
executable file header. It indicates that the module supports non-8.3
filenames. This bit is meaningless in real mode, MS-DOS, and in
versions of OS/2 earlier than Version 1.20.

You also should make sure that you use the version of LINK.EXE that
comes with OS/2 Version 1.20, or the version that comes with IBM's
development toolkit for OS/2 Version 1.20. The version of LINK.EXE
that comes with the Microsoft C Compiler Version 5.10 does not
understand the NEWFILES bit.

Another method to set the LONGNAME bit in the EXE header is to use the
lfns switch in the resource compiler (RC) from the OS/2 Version 1.20
toolkit. This will set the LONGNAME bit and allow you to still use the
linker that came with the Version 1.20 toolkit (or C 5.10), rather
than the linker that came with OS/2. It is preferable to use the
linker from C 5.10 since the linker that comes with OS/2 Version 1.20
causes problems when you attempt to bind applications to run in real
mode.


======================================================================

                   Installing Version 1.20 DUALBOOT


The following are questions about how the Version 1.20 Install Program
installs DUALBOOT:

1. The Install program appears to check certain prerequisite
   conditions for DUALBOOT, copies BOOT.COM, and then performs the
   necessary actions to install DUALBOOT. What are the prerequisite
   conditions it checks for?

   To install DUALBOOT on your hard disk, you must already have either
   MS-DOS (Version 3.20 or later) or an earlier version of Microsoft
   OS/2 DUALBOOT installed on your hard disk. The Microsoft OS/2
   Install program does not install MS-DOS on your computer. If you
   have chosen to use HPFS on your start-up drive, you cannot install
   DUALBOOT.

   If you have been running only MS-DOS in the past, you must create a
   C:\DOS subdirectory and copy your MS-DOS files to this new
   subdirectory before you install Microsoft OS/2 DUALBOOT. You must
   also specify the location of your MS-DOS files for OS/2 by
   modifying your AUTOEXEC.BAT and CONFIG.SYS files (make sure that
   you modify the MS-DOS versions of these files if you already have
   the Version 1.10 DUALBOOT installed).

   To specify the location of your MS-DOS files in your CONFIG.SYS
   file, perform the following modifications:

   a. Add "SHELL=C:\DOS\COMMAND.COM C:\DOS /P" to your CONFIG.SYS
      file.

   b. Edit any DEVICE and COUNTRY configuration statements in your
      CONFIG.SYS file so that the new C:\DOS subdirectory is specified
      in these statements.

   To specify the location of your MS-DOS files in your AUTOEXEC.BAT
   file, edit the SET PATH command so that it includes the new C:\DOS
   subdirectory.

   In addition to the above modifications to AUTOEXEC.BAT and
   CONFIG.SYS, you should move the MS-DOS COMMAND.COM file to the
   C:\DOS subdirectory.

2. If the prerequisite conditions are met, what does the Install
   program do to install DUALBOOT?

   After you install DUALBOOT on your computer, you will find copies
   of both the Microsoft OS/2 and MS-DOS configuration files in the
   C:\OS2\SYSTEM subdirectory of your hard disk. You will also find a
   file called BOOT.DOS in the C:\OS2\SYSTEM directory. BOOT.DOS is a
   copy of the MS-DOS boot record that existed on your hard disk prior
   to installation of Microsoft OS/2.

3. What does BOOT.COM do when it is run?

   When you execute the command "BOOT /DOS" from Microsoft OS/2, the
   following occurs:

   a. The Microsoft OS/2 configuration files are copied from the root
      directory and placed in C:\OS2\SYSTEM as AUTOEXEC.OS2 and
      CONFIG.OS2.

   b. The MS-DOS configuration files (AUTOEXEC.DOS and CONFIG.DOS) are
      copied from C:\OS2\SYSTEM and placed in the root directory as
      AUTOEXEC.BAT and CONFIG.SYS.

   c. A copy of the OS/2 boot record is made and placed in
      C:\OS2\SYSTEM as BOOT.OS2, and the file BOOT.DOS is copied from
      C:\OS2\SYSTEM to the boot record of the primary partition.

      An analogous process occurs when you type "BOOT /OS2" from MS-
      DOS.


======================================================================

          Copying Files from FAT Drive to HPFS Drive in 1.20


It is not necessary to use the File Manager when copying files from a
FAT drive to an HPFS drive.

You can use the COPY command to copy files back and forth between FAT
and HPFS file systems. However, there are a few things to be aware of
when copying files with long names. If you use the COPY command to
copy a file with a long name from an HPFS partition to a FAT
partition, you must specify a short name for the file on the FAT
partition.

By using the File Manager, you can copy a file or directory between
different file systems without losing the long name. The File Manager
automatically shortens the name for use in the FAT file system and
gives you the option of preserving the long name in an extended
attribute on the FAT partition.


======================================================================

        Configuring a Secondary HPFS Partition in Version 1.20


During the installation process, you selected the primary partition as
a FAT file system. To format the secondary partition as HPFS, you
inserted the following line in your CONFIG.SYS file:

   IFS=C:\OS2\HPFS.IFS /C:64

You also deleted the line "DISKCACHE=64" since Page 49 of the
"Microsoft Operating System/2 Command Reference for Version 1.20"
recommends not using the DISKCACHE statement if your system has an
HPFS partition. You then could format the secondary partition as HPFS.

You should use the following statements in your CONFIG.SYS file for
HPFS, and caching with HPFS:

   IFS = C:\OS2\HPFS.IFS /C:64
   RUN = C:\OS2\CACHE.EXE /LAZY:ON

CACHE.EXE is used with HPFS drives. DISKCACHE is not used with HPFS,
although no harm should be done if HPFS, CACHE.EXE, and DISKCACHE are
used together. However, DISKCACHE gives optimum results with a FAT
file system.


======================================================================

                 .TYPE Extended Attribute Information


Question:

The documentation describes the .TYPE EA (Extended Attribute) as
"similar to the earlier use of filename extensions" on Page 25 of the
"Microsoft Operating System/2 Programmer's Reference Volume 4" for
Version 1.20. Does this literally mean that OS/2 will be moving away
from using file extensions of .EXE, .CMD, etc., for recognizing
executable files? Also, we didn't find any .EXE files with a .TYPE EA
in the files included with Version 1.20. Is there a reason for this?

Response:

Microsoft is moving toward using the .TYPE fields rather than file
extensions. This transition will take quite a while since most or all
current applications aren't yet aware of the .TYPE field or EAs in
general. As you noticed, the .EXE files shipped with Version 1.20
don't contain .TYPE EAs. This is an example of the fact that it will
take a while for more applications to become EA aware.

In the case of our .EXE files, the linker must be EA aware to write
the .TYPE field of the .EXE file when it created the file. Since the
linker isn't aware of EAs yet, it didn't add those EAs.


======================================================================

               PM and LAN Manager Printing Information


The following are questions regarding the interaction of the GPI
calls, the printer driver, the OS/2 spooler, and the LAN Manager
spooler and redirector:

1. What is transferred over the network, given a series of GPI calls
   destined for the printed page?

   The only information that is transferred over the network is the
   escape codes that are appropriate for the printer in question. By
   the time a job actually gets sent over the network, whether or not
   the spooler has intervened in the process, the job has been
   entirely translated to escape codes/PostScript, etc.

2. We assume that the device driver "intercepts" the GPI calls at some
   location and translates this information into a bitmap
   representation, given the size of the file that the LAN Manager
   spooler deals with. Where does this occur? Given the redirection,
   does the device driver even need to be installed on the netstation?

   Yes, the device driver does interpret the GPI calls. It does so as
   the GPI calls are made (locally).

   A printer driver's internal entry point for various low-level
   primitives can be entered whenever those primitives are called by
   the graphics engine. The Epson driver has the graphics engine
   primitives actually executed. Other drivers might go ahead and
   implement some of the primitives themselves, which saves the engine
   simulations for more difficult tasks.

   At any rate, at this point from the first time the printer driver
   was called, the printer driver has created something in a format
   only it knows about: either printer escape codes for a direct job,
   or possibly translated into a "metafile" language format for stored
   spooled jobs. All of this occurs on the private workstation.

   Because it is necessary to have the device driver present [by use
   of DosLoadModule()] locally to open a DC (device context), not to
   mention that the device driver must be around to be called by the
   engine, a device driver for the printer in question must exist on
   the workstation.

3. Ignoring the current OS/2 Version 1.10 problem with the OS/2
   spooler, what would the spooler do on the netstation and the
   server?

   The flow of events is diagrammed below:

                        Spooling Data Flow


                      PM application          Non-PM application
                          |                         |
                          |  DevOpenDC(OD_QUEUED..) |
                          V                         |
                      PM device driver (Part I)     |
                          |                         |
                          |  SplQmOpen              |
                          V                         V
          Spooler puts data (metafile or raw data) into remote file
              |
              |
              V
                      Spooler chooses job
                          |
                          |  SplQpOpen
                          V
                      Print processor
                          |
                          |  DevOpenDC(OD_DIRECT..)
                          V
                      PM device driver (part II)
                          |
                          |  PrtOpen
                          V
                      Spooler
                          |
                          |  DosOpen (or DosMonWrite)
                          V
                        port

   Please note that this diagram is for the "local" chain of events.
   Again, on the server side, it is queuing up files with escape codes
   only. That is, by the time the file gets to the network server to
   which the printer is attached, no translation of the print job data
   will take place.

4. Is the action of the OS/2 spooler discussed in Question 3 different
   in Version 1.20?

   The diagram above also describes how the Version 1.20 spooler
   works.

5. If we define, via the Control Panel, an entry for a printer on a
   redirected port (for example, LPT7), using the same device driver,
   where is the translation from GPI to printer control
   characters/bitmap made? How do driver settings (for example,
   low/medium/high resolution settings) interact between the client
   and the server?

   Again, since all print job creation takes place locally, there is
   no effect on client/server communication, regardless of the
   settings.

   The final translation to escape codes takes place at the last step
   in the above diagram for some printer drivers, and at the first
   step for other printer drivers.

6. What is the preferred method of performing printing in a situation
   like this?

   It makes no difference how you print. There is no reason to alter
   your printing strategy based on whether or not the spooler is
   involved because you are not altering the eventual chain of events.

   In fact, whether or not the spooler is attached should be entirely
   transparent to the application.


======================================================================

        Playing of Metafile Can Result in Out of Memory Error


GpiPlayMetaFile() allocates DCs (device contexts) and bitmaps that are
not released until the process is terminated. Because there is an
approximate limit of 100 on the number of DCs, PMGRE soon runs out of
heap space and an out of memory error occurs.

The problem with a PS (presentation space) not releasing the DCs and
bitmaps created during the playing of a metafile can be alleviated via
the use of GpiReset(hps, GRES_ALL). It is by design that the resources
are not automatically freed after a GpiPlayMetaFile() call is issued.
If you call the GpiReset() function, you should not run out of heap
space.

Interestingly, this implies a limit on the number of bitmaps in a
metafile. That limit is approximately 100, the limit of the number of
DCs that can be created at any one time. This is a limit because you
cannot "reset" the PS containing the bitmaps before the metafile
finishes playing. Thus, during the course of the playing of the
metafile, PMGRE will run out of heap space.


======================================================================

                Blanking Out Password in a Dialog Box


Question:

When obtaining a password on a login procedure for a PM program, using
a dialog box to get the name and a second dialog box to obtain the
password, the password characters are visible. Is it possible to blank
out the characters going to the screen while getting them for password
verification?

Response:

In Version 1.10, you can accomplish this by subclassing the entry
field in question and handling the WM_CHAR message. When a character
is entered in the entry field, if it is alphanumeric (in the set of
characters you allow in passwords), you must "replace" the character
with some other character, for example a blank or an asterisk (*)
character.

There are a couple of ways to keep track of the characters that were
entered in the control. You can track them yourself, or send a
duplicate of the WM_CHAR messages to an invisible entry field that
will track them for you.

In Version 1.20 of the system, you can set the color of the text in
the entry fields using Presentation Parameters. Thus, you can specify
white on white, and there will be no problem with password entry
fields because the text won't be visible.


======================================================================

             Storing a Multipaged Document in a Metafile


If you are using a metafile to store some sort of a generic multipage
document, you may find that metafiles are less than optimal for this
purpose. The following is a discussion of the drawbacks and possible
workarounds that you should consider before using this approach.

A metafile is a tape recorder of GPI functions. When played, it does
nothing more than execute the graphics orders it contains on the PS
(presentation space), creating an image but no underlying data
structures. This will make it difficult for you to "read in" a
document stored as a metafile.

You can store GPI segments in metafiles, which is one way to impose
some sort of structure on the saved image. When played into a PS in
Retain mode, the segments will be re-created. This method could be
used to store a multipage document: one parent segment per page, with
the numbering of the segments predetermined.

However, you are again limited as to what you can "store" in a
metafile. It would be difficult to transparently store formatting
information, or any other object not expressly provided for by the GPI
functionality.

Another alternative is to store information in some sort of rich text
format, by using the metafile as an intermediary between your
application and the "real" output/data structures that drive it. For
example, you could store a document in rich text format via multiple
GpiCharString() calls, and query out the metafile bits when you load
the metafile. You would never actually be playing the metafile.
However, this is again a nontrivial operation as you will have to
parse the metafile to retrieve your information.

One last limitation you should be aware of is that metafiles, like
GPI, have a 16-bit limit on coordinates. This implies a -32K/+32K
limit on the coordinate space used to store any image or document.
This may or may not be a consideration for you if you need to
represent highly dense coordinate spaces.

Metafile orders are stored in a graphics language called GOCA, which
is a language that closely mirrors GPI. GOCA and the format of
metafiles is documented by IBM in its "IBM Operating System/2 Version
1.1 Technical Reference" manuals. This information is not included in
Microsoft's OS/2 Version 1.10 Programmer's Toolkit; however, it will
be included in a future release of QuickHelp. You may be interested in
examining this language/format to see if it would fit your needs as a
storage medium, and to get a better idea of what you would be working
with if you decided to parse, modify, or write code dependent on the
metafile structure.


======================================================================

           Disabling Key Combinations Such As CTRL+ALT+DEL


It is not possible to disable CTRL+ALT+DEL, CTRL+ESC, or ALT+ESC. This
is with regard to writing software for process monitoring and control,
while at the same time preventing accidental (or deliberate)
disruption of programs, These hotkeys never enter the monitor chain
(the normal way to stop or alter keystrokes is with a keyboard
monitor), and thus, no application ever gets a chance to see or change
them. They are translated into keyboard events, which are handled by
the kernel.

With respect to CTRL+C and CTRL+BREAK in a VIO application, an
application can prevent these from stopping or breaking the
application by setting a signal handler for the application. In this
manner, the signals generated by the CTRL+C and CTRL+BREAK keystrokes
can be intercepted. See the documentation for DosSetSigHandler() for
more information. In a PM application, these keystrokes have no
special effect, so you do not need to be concerned with these
keystrokes.

You might be able to partially generate the behavior you require by
writing your entire application as a VioPopup() application.
VioPopup() windows cannot be exited by pressing CTRL+ESC or ALT+ESC.
You can still reboot the machine with CTRL+ALT+DEL; however, you
cannot switch screen groups.

Generally speaking, the inability to prevent the behaviors associated
with these "system" keystrokes is a design limitation of the system.
The system simply lacks the facilities to implement a truly "secure"
application, one that is safe from all user interaction.


======================================================================

        Setting Up OS/2 LAN Manager to Use Replicator in 2.00


The replication service is a new feature included in OS/2 LAN Manager
Version 2.00. The documentation for the replication service is fairly
complete, and documents the two points discussed below; however, these
two points can be somewhat confusing.

In the example listed below, assume the export server is named
EXPORT1, and the import server is named IMPORT1. When starting the
replicator, you should do the following:

1. Make sure the IMPORT1 account on EXPORT1 (the export server) has
   "RA" authority on the entire C:\LANMAN\REPL\EXPORT tree.

   The easiest way to do this is with the NET ADMIN command. First,
   authorize IMPORT1 (the import server) to solely
   C:\LANMAN\REPL\EXPORT, then immediately after clicking on <Permit>
   you will be returned to a menu where you can click on <Permit
   tree>.

2. On IMPORT1, the import server, do the following

      md c:\lanman\repl\import\subdir1
      md c:\lanman\repl\import\subdir2

   so that the subdirectories that IMPORT1 is supposed to import (in
   this example, subdir1 and subdir2) will already exist. The
   replicator will not create these subdirectories for you; you must
   do this yourself. The replicator does not create these
   subdirectories for you because this is one way to control which
   subdirectories, of the potentially many subdirectories an export
   server might export, are actually imported to by a given import
   server.


======================================================================

                Avoiding File Access/Locking Problems


Question:

A workstation and a server are on a local area network (LAN). The
server shares one of its drives with the workstation. When an
application running on the workstation locks a record (10 bytes) in a
file on the shared drive, the server does not see the lock because the
same application running on the server is able to lock the same record
in the file.

Using the NET ADMIN utility, you can see the file being opened by the
workstation; however, the record lock does not show on the status
screen. If a second copy of the application is run on the workstation,
the application receives a lock error. The NET ADMIN utility sees the
file open for the second time and finally "sees" the lock from the
first application. Is there a workaround for this problem?

Response:

When you lock a portion of a file from a remote workstation, the file
locking mechanism of the server records this fact, such that if you
try to lock the same portion of the file from a second workstation (or
run the same program from a different screen group of OS/2), you get a
locking violation error.

However, if you run a file locking program on a workstation and you
run the same program on the server, then try to lock the file, the
server does not know about this lock, and thus will not return an
error message. The server keeps all over-the-network locks to itself
and does not pass them down to OS/2. That's why the second workstation
(or a second screen group) will get a locking violation if it tries
locking over the network.

If you are accessing files on the server from the server itself, you
may experience a number of access violation problems. Please see
Chapter 14 of the "Microsoft Operating System/2 LAN Manager
Administrator's Guide" ("Monitoring and Trouble-shooting Server
Operations") for more information on how to avoid these problems.

Listed below are some helpful hints on how to avoid these access
violation problems.

From the server, use the shared drive/directory as a remote drive. For
example, use the following commands on the server:

   net share share=d:\
   net use s: \\server\share

When accessing the files locally on this share point, do not use the
direct paths (for example D:\FILES). Instead use redirected paths (for
example S:\FILES). This way, you will eliminate any possible
access/locking violations.


======================================================================

           Load-Time and Run-Time Dynamic Linking Overview


Listed below is information about the two types of dynamic linking:
load-time dynamic linking and run-time dynamic linking.

Load-Time Dynamic Linking
-------------------------

When you build an .EXE file that explicitly calls functions contained
in a .DLL (dynamic linked library), these external references are
recorded in the .EXE file; however, they remain unresolved until the
.EXE file is actually loaded.

When you launch a program that contains such unresolved .DLL calls,
the following occurs:

1. The OS/2 loader checks to see if the .DLL has already been loaded
   and brings it into memory, if necessary.

2. Any global or instance initialization of the .DLL is performed.

3. The loader examines the segment tables for the .DLL and allocates a
   selector from the launching program's LDT (local descriptor table)
   for each segment in the .DLL.

One step still remains. Each segment in a .DLL is marked as either
PRELOAD (load the segment at run time) or LOADONCALL (don't load the
segment until it is called during execution of the program). All
segments marked as PRELOAD are brought into memory by the loader and
any unresolved external references to those segments are fixed up.
Segments marked as LOADONCALL are not brought into memory until they
are called, and any unresolved external references to those segments
remain unresolved until that segment is explicitly accessed.

Run-Time Dynamic Linking
------------------------

When you use run-time dynamic linking, your application explicitly
directs the kernel to load a .DLL [using DosLoadModule()] and obtain
the address of the desired function in that .DLL [using
DosGetProcAddr()]. If the .DLL is not already in memory, or if
referenced LOADONCALL segments of the .DLL are not yet in memory, the
kernel must load the necessary items from disk. Any per instance
initialization of the .DLL also occurs at this point, and this may
incur other disk performance hits.

While run-time dynamic linking is a bit more complex, it does have the
following advantages: memory is conserved, load time is decreased, and
you have more flexibility in how and when you load functions.

This is a quick overview of dynamic linking under OS/2. For more
detailed information on dynamic linking, please see the books in the
following bibliography:

1. "Design Concepts and Considerations in Building an OS/2 Dynamic-
   Link Library," by Ross M. Greenberg. "Microsoft Systems Journal,"
   Volume 3 Number 3, May 1988.

2. "Strategies for Building and Using OS/2 Run-Time Libraries," by
   Ross M. Greenberg. "Microsoft Systems Journal," Volume 4 Number 3,
   May 1989.

3. Chapter 19, "Dynamic Link Libraries," "Advanced OS/2 Programming,"
   by Ray Duncan. Microsoft Press, 1989.

4. Chapter 3, "How Dynamic Link Libraries Work," "Software Tools for
   OS/2: Creating Dynamic Link Libraries," by Michael J. Young.
   Addison-Wesley, 1989.

5. "Inside OS/2," by Gordon Letwin. Microsoft Press, 1988.

6. Chapter 45, "Dynamic Linking," "Microsoft Operating System/2
   Programmer's Reference Volume 1" for Version 1.10.

7. Chapter 2, "Segmented-Executable Linker," "Microsoft Operating
   System/2 Presentation Manager Programming Tools" for Version 1.10.

8. Chapter 6, "IBM Operating System/2 Version 1.1 Technical Reference
   Programming Reference: Volume 1."


======================================================================
                                   
                        Microsoft FORTRAN 5.00

                          by Debbie Watkins


                FORPATCH Available in Software Library


There is a file in the Software Library called FORPATCH that consists
of a README file, a patched version of the first pass of the FORTRAN
Version 5.00 compiler (F1.EXE), and a patched, high-capacity compiler
(F1L.EXE).

This update corrects the following problems:

1. The I/O of a STRUCTURE element generates an F1001 Internal Compiler
   Error in omf_ms.c:1.118, line 1093, or a protection violation.

2. NAMELIST statements in multiple subprograms in one file cause the
   machine to hang.

3. SAVEing a common block in multiple subprograms causes a compiler
   error F2348: already declared SAVE.

4. Using /4Yi, /4Ys, or /4Yv, and an asterisk in column one to
   indicate a comment generates a compiler error F2037: illegal label
   field.

This file can be found in the Software Library by searching on the
keyword FORPATCH, Q51298, or S12450. FORPATCH was archived using the
PKware file-compression utility.


======================================================================

           Reading Environment Variables from FORTRAN 5.00


The program below demonstrates how to obtain environment variables
from the MS-DOS environment. The program calls the C getenv()
function, which is a built-in part of the FORTRAN Version 5.00
library.

The interface statement and the character function GETENV are the
required portions, while the main program is for demonstration
purposes.

The problem occurs because the C function is designed to return a
pointer to the contents of the variable. The function does not find
the variable; it returns a NULL, which causes a problem under FORTRAN
because there is no way to check for a NULL.

To correct this problem, you need to look for a variable that does not
exist. Use the following procedure:

1. Call getenv() a on nonexistent variable.

2. Call getenv(VAR) where VAR is what you want to find.

3. If the results match, VAR does not exist.

4. If the results do not match, you have a return value.

Sample Program
--------------

       program environment
       character name*20,  string*128, fgetenv*128
       write (*,*) ' Enter name of environment variable'
       read (*,'(A)') name
       string = fgetenv(name)
       write (*,*) 'Value is: ',string
       stop
       end

       interface to character*128 function getenv [c] (var)
       character*21 var [reference]
       end

       character*128 function fgetenv(var)
       character getenv*128, dummy*128, var*20, cvar*21
       integer n
       n = len_trim(var)
       cvar = var(1:n)//char(0)
       fgetenv = char(0)
       dummy = getenv(fgetenv)
       fgetenv = getenv(cvar)
       if (fgetenv.eq.dummy) then
           fgetenv = ' '
       end if
       fgetenv = fgetenv(1:index(fgetenv,char(0)))
       return
       end


======================================================================

    OS/2 Graphic Routines Available with FORTRAN 5.00 GRTEXTP.LIB


The OS/2 graphics library GRTEXTP.LIB supports the following routines
(which are also listed in the "Microsoft FORTRAN Advanced Topics"
manual, on Page 148):

   clearscreen         getvisualpage       settextwindow
   displaycursor       outtext             setvideomode
   getactivepage       setactivepage       setvideomoderows
   getbkcolor          setbkcolor          setvisualpage
   gettextcolor        settextcolor        wrapon
   gettextcursor       settextcursor
   gettextposition     settextposition
   getvideoconfig      settextrows

This library must be linked instead of GRAPHICS.LIB to use these
routines under OS/2. Routines not included in the above list are not
available under OS/2.

The OS/2 Presentation Manager can be programmed to use additional
graphics routines under OS/2.


======================================================================

  Graphics Routines, Unresolved Externals, and FGRAPH.FI & FGRAPH.FD


Page 138 of the "Microsoft FORTRAN Advanced Topics" manual for Version
5.00 states that for every file that makes a graphics call, you must
have the INTERFACE statements at the beginning of that file (INCLUDE
'FGRAPH.FI'). You then must include FGRAPH.FD (variable declarations)
in every subroutine that calls a graphics routine.

Note: The INTERFACE statements (or the line INCLUDE 'FGRAPH.FI) need
to be in EACH FILE in which a graphics routine is called. If these
include files are not in the proper location within the program, the
link error, L2029, unresolved external may be generated.


======================================================================

              C Compatibility and FORTRAN 5.00 Libraries


In the second paragraph under "Specifying Libraries" on Page 79 of the
"Microsoft FORTRAN Advanced Topics" manual for Version 5.00, the
following statement is made:

   If your program uses both FORTRAN and C, then specify the library
   for the most recent of the two language products first.

The above information is correct; however, the following later
sentence is incorrect:

   If you use C 5.1 or later, specify the C library first.

The FORTRAN 5.00 library should come before the C 5.10 library because
the FORTRAN 5.00 library contains newer start-up code. The next line
states that you should "make sure you choose a C-compatible library
when you install FORTRAN."

If the version of FORTRAN is newer than the version of C (for example,
FORTRAN 5.00 is newer than C 5.10), FORTRAN should NOT be installed
with C compatibility, and the LINK options /NOD and /NOE should be
used to avoid errors about multiply defined symbols.


======================================================================

             Opening More Than 20 Files with FORTRAN 5.00


Under FORTRAN Version 5.00, you are limited to opening 20 files. This
limit can be changed by following the instructions on Pages 405-407 of
the "Microsoft FORTRAN Reference" manual for Version 5.00 This
modification requires Microsoft Macro Assembler Version 5.10.


======================================================================

                      FORTRAN Reserved Filenames


The following is a list of reserved filenames in Microsoft FORTRAN.
This information is from the FORTRAN 5.00 README.DOC.

   Reserved Word     Description
   -------------     -----------
   
   CON               Keyboard and screen
   USER              Keyboard and screen
   PRN               Printer (LPT1)
   COM1              Communications port 1
   LPT1              Printer
   NUL               Null device
   AUX               Communications port (COM1)
   ERR               Standard error output (screen)
   LINE              Communications port (COM1)

You can use READ, WRITE, and OPEN statements (as appropriate) to
access these devices, and you can use CLOSE statements to disconnect
them, just as you would with other files. FORTRAN carriage-control
characters are recognized for these devices.

Problems can occur if you use these reserved words incorrectly (for
example, if you try to use one as a regular disk filename). For
instance, if you open a file called LINE.DOC, reading from that file
can cause your computer to lock unless there is an active data
transmitting device connected to COM1.


======================================================================

              VAX Extensions Available with FORTRAN 5.00


Microsoft FORTRAN includes many, but not all, VAX extensions. Most of
these extensions are found on Pages 331-332 of the "Microsoft FORTRAN
Reference" manual for Version 5.00. Appendix B of the same manual
lists additional features that are new in FORTRAN 5.00.

Query on Q50504 for a complete list of the available VAX extensions.


======================================================================
                                   
 Presentation Parameters and Combination Boxes for OS/2 Version 1.20

                             by Joe Hayes


Introduction
------------

On January 8, 1990, Microsoft announced and shipped the OS/2
Presentation Manager Toolkit Version 1.20. This development
environment, specifically designed for OS/2 and Presentation Manager
applications, incorporates the new additions introduced in OS/2
Version 1.20. Two of these new features, presentation parameters
(presparams) and combination boxes (combo boxes) are discussed here
and are demonstrated in the sample application PRESPARM.EXE contained
within PRESPARM.ARC.

The file PRESPARM.ARC can be found in the Software/Data Library by
searching on the filename PRESPARM, the Q number xxxxx, or S12520.
PRESPARM was archived using the PKware file-conversion utility.

Further information can be obtained from the "Microsoft Operating
System/2 Programmer's Reference Volume 4," the "Microsoft Operating
System/2 Presentation Manager Softset: Software Tools for Developing
OS/2 Presentation Manager Programs," and the QuickHelp included with
the OS/2 Programmer's Toolkit Version 1.20.

Presentation Parameters
-----------------------

Presparams are a feature of OS/2 Version 1.20 that control the
appearance of a custom dialog box, window, or control when it is first
created. Presparams can also be used to change the appearance of the
dialog box, window, or control dynamically during program execution.
This is a new feature, as by changing the presparam, a paint message
is not sent to the dialog box, window, or control. This is handled
internally by OS/2 as a final step in output pipeline.

Two examples of the presentation parameters demonstrated in the sample
program are color and fonts. These parameters of the dialog box,
window, or control can be set in the resource file through the use of
the PRESPARAMS, CONTROL, or WINDOW statement. They can also be changed
on the fly using the WinSetPresParam() function.

Combination Boxes
-----------------

Combo boxes are a new feature of OS/2 Version 1.20. They can be
thought of as a concatenation of two existing control types: a single
line entry field and a list box. A combo box gives the user the
flexibility of entering data in the entry field, as in previous OS/2
applications. EM_ messages can also be sent to the combo box entry
field to provide a similar interface to the standard entry field.

The list box portion of the combo box gives the user a standard array
of choices that can be selected into the entry field. This gives both
you and the user some predefined choices that can be selected and
optionally edited in the entry field before use in the application.
LM_ messages can be sent to the list box portion of the combo box,
again to add the standard interface now used for existing list boxes.

Other new CBM_ and CBN_ messages have been added to the Toolkit to
give the application developer the ability to manipulate and be
notified by the combo box. For example, an application using combo
boxes that have drop-down lists can display the list of a combo box by
sending it a CBM_SHOWLIST message. The user would display the list by
clicking the drop-down icon just to the right of the entry field.

There are three types of combo boxes: simple combo boxes, drop-down
combo boxes, and drop-down-list combo boxes. Simple combo boxes are a
combination of an entry field and a list box that is always displayed.
The user can choose list box selections and/or edit selections from
the entry field. Drop-down combo boxes are identical to simple combo
boxes, except the list box is not always displayed. The user accesses
the list box portion by clicking the drop-down icon. Drop-down-list
combo boxes are identical to drop-down combo boxes except that the
user cannot edit the list box selections. Drop-down-list boxes are
excellent for finite numbers of fixed choices where the selection
itself needs to be displayed after the selection is made.

Sample Program -- PRESPARM.ARC
-----------------------------

The sample program PRESPARM.EXE is a simple Presentation Manager
window with a Demomenu presenting a Dialogmenu item. By selecting the
Dialog item, a dialog is displayed demonstrating presentation
parameters and combo boxes. The dialog box contains two combo boxes, a
list box, three entry fields, three push buttons, and several
descriptive text fields.

The combo box toward the upper left of the dialog box is a drop-down
combo box. It is used to control the editing of the text field
immediately below it. The text field is intended to be the title of
the list box. Thus, the user can select one of the predefined text
items contained in the drop-down combo box list portion and can then
edit and/or select that item as the title of the list box below. The
list box title can be changed by pressing the Update Display push
button.

Some code for this combo box can be found in the WM_INITDLG: portion
of the GetPresParamsDlgProc() function. For example:

     /* Initialize drop down combo box */

     WinSetDlgItemText (hwnd, DID_EDITLIST, szTitle) ;

     WinSendDlgItemMsg (hwnd, DID_EDITLIST, LM_INSERTITEM,
                    MPFROMSHORT ((SHORT) LIT_END),
                    MPFROMP ((PSZ) "Demo Strings:")) ;
     WinSendDlgItemMsg (hwnd, DID_EDITLIST, LM_INSERTITEM,
                    MPFROMSHORT ((SHORT) LIT_END),
                    MPFROMP ((PSZ) "Test Strings:")) ;
     WinSendDlgItemMsg (hwnd, DID_EDITLIST, LM_INSERTITEM,
                    MPFROMSHORT ((SHORT) LIT_END),
                    MPFROMP ((PSZ) "List Strings:")) ;

The three entry fields toward the upper right of the dialog box are
the RGB values that correspond to three presentation parameters of the
list box toward the lower left of the dialog box. By entering
different RGB values and selecting "Update Display," the user can then
change the color of the presentation parameters. The presparam can be
selected using the drop-down-list combo box immediately under the RGB
entry fields. A drop-down-list combo box was selected because the
choices for the presparams are finite and cannot be edited by the
user.

Code for the presentation parameters can be found in the WM_COMMAND:
portion of the same function. For example:

     /* Get new color value */

     WinQueryDlgItemShort (hwnd, DID_RED, &usTempRed, FALSE) ;
     WinQueryDlgItemShort (hwnd, DID_GREEN, &usTempGreen, FALSE) ;
     WinQueryDlgItemShort (hwnd, DID_BLUE, &usTempBlue, FALSE) ;

     clr = RGB (usTempRed, usTempGreen, usTempBlue) ;

     /* Query type of PresParam to change */

     usTempListIndex = (USHORT) WinSendDlgItemMsg (
                         hwnd,
                         DID_LISTCOMBO,
                         LM_QUERYSELECTION,
                         MPFROMSHORT ((SHORT) LIT_FIRST),
                         0L) ;

     /* Update PresParams */

     WinSetPresParam (hwndListBox,
               idPresParam[usTempListIndex],
               (LONG) sizeof (LONG),
               (PVOID) &clr ) ;


To close the dialog box, select the Save Changes or Cancel push
button. The Save Changes button saves the presparams for the duration
of the application's execution.

The PRESPARAMS statement is demonstrated in the resource file
PRESPARM.RC to set the font used by the About dialog box. To view this
dialog box, select the About option under the Demo menu selection.


======================================================================
                                   
  Creating and Using a Dynamically Linked Version of the C Run-Time
                               Library
                                   
                           by Rick LaPlante
                                   
                                   
With programming for the OS/2 operating system becoming more
significant, it is clear that some important features of programming
for OS/2 are in need of further documentation. One such feature is the
ability to use Microsoft C Version 5.10 to create a dynamically linked
version of the C run-time library.

This article will discuss two issues regarding creating a dynamically
linked version of the C run time (CRT): how to create the dynamic-
linked libraries (DLL) version, and program design considerations when
using the DLL version of the CRT.

How to Create a DLL Version of the CRT
---------------------------------------

The following information is taken from Section 5, "Creating Dynamic-
Link Libraries," of the Microsoft C Version 5.10 MTDYNA.DOC file.

The process of creating a multiple-thread dynamic-link library version
of the C run time is outlined below. This process is also contained in
the file CDLLOBJS.CMD:

1. Create a definition file that specifies the exports from the C run-
   time library for the dynamic-link library. The file CDLLOBJS.DEF,
   which is included with Microsoft C Version 5.10, is a sample
   definition file that includes all of the C run-time functions
   currently supported. Any routines listed in the EXPORTS section of
   the definition file will be included in the DLL.

2. Link the special start-up file CRTLIB.OBJ with CDLLOBJS.LIB,
   DOSCALLS.LIB, and the definition file (CDLLOBJS.DEF) from Step 1.
   This creates a customized C run-time dynamic-link library file
   (named CRTLIB.DLL). The following files are linked together:

      link crtlib.obj,crtlib.dll/noi,,cdllobjs.lib doscalls.lib /NOD
      /NOE, cdllobjs.def

   where:

      crtlib.obj         Start-up code for CRT library files
      cdllobjs.lib       C run-time library object modules
      doscalls.lib       OS/2 support library (may use OS2.LIB
      cdllobjs.def       Definition module from Step 1
      crtlib.dll         Output from LINK

3. Run IMPLIB on the definition file from Step 1 to create a
   customized library file (CRTLIB.LIB) containing the exported
   functions. The command is shown below:

      implib crtlib.lib cdllobjs.def

The only similarity between libraries created by IMPLIB and libraries
created by LIB is the filename extension ".LIB".

Libraries created by IMPLIB contain the names of functions and modules
only to satisfy the linker. The actual code is brought in later by
loading dynamic-link libraries.

4. Use the Microsoft Library Manager (LIB) to append CDLLSUPP.LIB to
   the customized library created in Step 3. The file CDLLSUP.LIB
   contains a few small routines that cannot be dynamically linked due
   to design constraints as they are called near.

      lib crtlib.lib+cdllsupp.lib;

Programming Considerations
--------------------------

One of the most important things to remember when using a DLL version
of the CRT is that the DLL is multiple-threaded. Therefore, you MUST
use the multiple-threaded version of the C header files (include
files). To do this you can either give explicit paths to the multiple-
threaded include files in the source or use the CL compiler switch
"/I" to modify the current setting of the INCLUDE environment
variable. Compiling a C source using Microsoft C Version 5.10, and
utilizing a DLL version of the CRT, would look something like the
following:

   cl /I\include\mt /AS /Gs2 /DDLL /c main.c

The "/I\include\mt" specifies that the multiple-threaded include files
are to be used. The "/Gs2" switch generates 80286 code and turns off
stack checking. This is very important. Stack checking MUST be turned
off with small or compact memory model programs, which utilize DLLs.
Stack checking can be on with medium or large/huge memory models. The
/DDLL switch defines the DLL symbol, which is used to distinguish
between the non-DLL version of the CRT, LLIBCMT.LIB, and the DLL
version, CRTLIB.DLL. To link an object module with the DLL version of
the CRT, the following command is used:

   link /NOI /NOD main+crtexe,,,crtlib.lib doscalls.lib,main.def

The /NOD is required so that symbols are not multiply defined. The
file CRTEXE.OBJ links in start-up code for the executable file that is
not present in the library created by IMPLIB. MAIN.DEF is the module
definition file for MAIN.C.

Another thing to consider during program design is that the C run-time
data is shared between the main program and any other DLLs that access
the CRTLIB.DLL in the process. In other words, even though the main
program and each DLL have their own data segments, which are not
shared, they all share the C run-time data. C run-time data includes
such things as environment strings, global C run-time data, and thread
ID numbers. The following is from Section 5.2 in MTDYNA.DOC:

A program built using the dynamically linked multiple-threaded support
of the run-time library may share the C run-time library with one or
more dynamic-link libraries that are closely related to it. C run-time
global data (such as the standard I/O package FILE, pointers of
buffered I/O, and memory allocated with malloc functions) is shared.
This means that the program and the associated dynamic-link libraries
must cooperate on the usage of this data.

For complete details on creating a DLL version of the C run time, as
well as other information on both single and multiple-threaded
programs, your first reference should be MTDYNA.DOC.


======================================================================
                                   
          C Run-Time Routines Cannot Be Placed in an Overlay

                          by Renata Bachelor


On some occasions you may want to extract a routine from the C run-
time library and put it in an overlay. If you try this procedure, your
program will compile and link without warnings or errors. However,
when you run the program, your machine may hang.

This problem occurs because a segment is requested by a call to a
routine in that segment. The FIRST request for a segment determines
where the linker will place the ENTIRE segment.

After you extracted a module from the library, you put the .OBJ in
either the root or in an overlay. If you put the overlay in the root,
the entire segment goes in the root; if you put it in an overlay, the
entire segment goes in the overlay.

This is expected linker behavior for the following reasons:

1. The run-time routines for medium and large models (the only ones
   that overlays deal with) are compiled with /NT _TEXT. This causes
   ALL the run-time routines to be placed in the same named segment
   (_TEXT); the linker cannot split a segment between the root and the
   overlay.

2. Segmentation takes precedence over overlays.

3. The linker constructs overlays from segments, not individual
   functions or library modules.

So, when you extract a module from the run-time library and put it in
the overlay, ALL the run time gets put in the overlay. As a result,
the entry point of the overlay manager is put into the overlay and not
in the root. The overlay manager code (also in the _TEXT) is not
present in memory at startup and the machine hangs.

Putting the .OBJ in an overlay may APPEAR to succeed (the machine does
not hang) if the first reference to _TEXT is made by a function called
from the root. The entire segment of routines is then placed in the
root, including the routines called from the "overlaid" .OBJ.

The linker behavior is the same for routines from GRAPHICS.LIB (and
PGCHART.LIB, which is distributed with QuickC and QuickAssembler).

If you are curious about which segments get which symbols, create and
view a link map made at compile or link time.


======================================================================
                                   
    Programming the Mouse for a Hercules Monochrome Graphics Card
                                   
                           by Tony Claflin


When programming the mouse driver in C to display the default graphics
cursor (an arrow), you must perform the following steps in the
sequence shown:

1. Store a "6" in memory location 40h:49h if the Hercules card is
   using the C run-time library (CRT), Page 0. Store a "5" in memory
   location 40h:49h if the Hercules card is using the CRT, Page 1.

2. Reset the mouse driver (call function 0).

3. Put the Hercules card into graphics mode.

4. Display the cursor (call function 1).

The sequence of steps in the "Microsoft Mouse Programmer's Reference
Guide" is incorrect for C programming. When this sequence is followed,
the program displays streaks and/or dots instead of an arrow. The new
"Microsoft Mouse Programmer's Reference" from Microsoft Press has the
correct sequence in the programming example on Pages 250-252.

The following programming example displays an arrow and allows you to
move it around with the mouse. This ability terminates when you press
a key.

#include <graph.h>

main()
{   char far * videomode=(char far *)0x00400049;
     int m1,m2,m3,m4;

     *videomode=6;
     m1=0;
     cmouses(&m1,&m2,&m3,&m4);
     _setvideomode(_HERCMONO);
     m1=1;
     cmouses(&m1,&m2,&m3,&m4);
     getch();
     *videomode=7;
     _setvideomode(_DEFAULTMODE);
}


======================================================================
                                   
 Answers to Common Questions About Microsoft QuickBASIC Version 4.50
                                   
                    by Edna Kainz and Steve Elston
                                   
                                   
This article is intended for individuals who are using QuickBASIC
Version 4.50 for the IBM PC and compatibles, and provides answers to
common questions, along with supplementary information on QuickBASIC
Version 4.50.


MEMORY MANAGEMENT AND MODULAR PROGRAMMING
-----------------------------------------

Modular Programming
-------------------

Question:

What is modular programming? How do I modularize a program?

Response:

QuickBASIC has several features to help you create programs that are
organized in a logical and structured manner. This style of
programming is often referred to as "modular" programming. There are
many advantages to modular programming; the most important advantage
is that the logic of a modular program is clearer.

A modular program is structured in such a way that the various
functional blocks of source code are isolated in separate procedures.
This makes it easy to reuse particular procedures in other programming
projects and greatly simplifies debugging. In a modular program,
problems can be quickly isolated to a given procedure. The procedure
can then be tested and debugged separately, without you having to
consider the remainder of the program.

QuickBASIC Modular Programming Vocabulary
-----------------------------------------
   
There are several important terms used by QuickBASIC programmers when
talking about program structure. It is important to understand these
terms in order to fully utilize the QuickBASIC programming
environment.

1. Module: A section of program source code that is stored in a
   separate file and can be separately compiled. Every program has at
   least one module (the main module) and may consist of many modules
   (support modules). The modules are separately compiled and linked
   together to produce a finished executable program.

2. Procedure: A general term referring to either SUBs or FUNCTIONs in
   QuickBASIC. Conceptually, a procedure is a functional block of code
   that performs a specific action and that is logically distinct from
   the rest of the program.

3. SUB: Short for SUBProgram. A block of QuickBASIC code is delimited
   by SUB....END SUB. Do not confuse this with a subroutine.
   Subroutines are blocks of code that are terminated with a RETURN
   statement and were used in older forms of BASIC.

4. FUNCTION: A block of code that is delimited by FUNCTION....END
   FUNCTION. Similar to SUBs except that FUNCTIONs are used when a
   procedure is needed that returns a single value. Do not confuse
   FUNCTIONs with the older DEF FN functions.

5. Module level code: The code that is found at the module level,
   which is outside of any procedure.

6. Procedure level code: The code that is found inside a SUB or
   FUNCTION procedure.

QuickBASIC Modular Programming Features
---------------------------------------
   
By pressing the F2 key or choosing View Subs from the View menu inside
QuickBASIC, you can see an outline view of the program that is
currently loaded. The resulting window will show each module name, and
each of the procedures in that module will be indented under it. Each
editing window in QuickBASIC shows the code of one procedure at a
time. Use the View Subs display window to select the procedure that
you want to edit. Also, from this same display, you can delete and
move procedures at will. Whenever you enter the reserved word SUB or
FUNCTION, followed by a procedure name, QuickBASIC creates a new
editing window for you so that you can add the code for that
procedure.

The fastest way to program in QuickBASIC is to design your program so
that the main module-level code calls procedures. Just determine each
action that the program must perform and then write a procedure to
accomplish that task. Then create the module-level code to tie all of
the procedures together.

Execution starts at the beginning of the main module-level code. If
your program requires more than one module, your support modules will
contain additional procedures; however, note that since the only way
to transfer control across modules is to call a procedure, module-
level code in support modules is unreachable. This means that support
modules contain only declarative statements and procedures. You will
never have any executable statements in the module-level code of a
support module. The flow of control, for the overall program, is
governed by the module-level code of your main module.


Memory Management, the Big Picture
----------------------------------

Question:

How do I get more string space?

Response:

There are several things to keep in mind when programming in
QuickBASIC. Because BASIC manages memory for you, you need to
understand the limitations of the BASIC memory-management system. The
most important points for the programmer are the following:

1. Your program receives one 64K code segment for each module that it
   contains. If the code generated by the compiler for a given module
   approaches 64K, you must add a new module to your program to
   continue adding code. The easiest way to determine if you need to
   add a new module is to look at the .MAP file produced by the
   linker, LINK.EXE. You will notice at the top of the .MAP file
   listing that there is a segment with the same name as your module
   with an _CODE appended, listed under the BC_CODE class. This is the
   code segment for that module and must be smaller than 64K.

2. Your entire executable program, no matter how many modules it
   contains, has only one near data segment. All ordinary variables,
   all variable-length STRINGs, and your stack are located in this
   segment. The FRE() function can be used to determine if you are
   close to filling up this segment. The "Out of STRING Space" error
   indicates that this segment is full.

   Usually, the best approach to minimizing your usage of the near
   data segment is to move as many items as possible out into the far
   heap. However, the BASIC memory management engine allows only
   certain types of data items to be placed in far memory. These items
   are DYNAMIC arrays of numeric data or fixed-length STRINGs.
   Variable-length STRINGs never go in the far heap.

   The easiest way to move these items out of the near data segment is
   to make all arrays DYNAMIC unless there is a specific reason to
   keep them STATIC. Usually, the program structure shown below is the
   simplest organization:

      Pseudo Code
      -----------
      
      DIM all STATIC arrays first
      COMMON statements next
      REM $DYNAMIC
      DIM all DYNAMIC arrays here,
          including the ones placed in COMMON
      
   Also, if practical, use only arrays of fixed-length STRINGs.
   Remember, arrays of variable-length STRINGs cannot go into the far
   heap. These techniques will minimize the portion of the near data
   segment that your program's data requires, leaving more room for
   conventional variables and variable-length STRINGs. If any of your
   DYNAMIC arrays must be larger than 64K, you will need to start
   QuickBASIC or compile with the /Ah option.

   Note: Microsoft BASIC Professional Development System (PDS) 7.00
   offers support for far variable-length strings and Expanded Memory
   Specification (EMS 4.0), while giving your programs more code and
   data space so that you can develop dramatically larger programs for
   MS-DOS or OS/2.


COMPATIBILITIES
---------------

Question:

Which versions of Microsoft FORTRAN, Macro Assembler, Pascal, C
Compiler, and QuickC are required with QuickBASIC 4.50 for mixed-
language programming?

Response:

QuickBASIC Version 4.50 creates .OBJ modules that can be linked with
.OBJ modules from the following languages:

   Microsoft Pascal Version 4.00
   Microsoft FORTRAN Versions 4.10 and 5.00
   Microsoft C Version 5.10 and QuickC Versions 1.01 and 2.00
   Microsoft Macro Assembler (MASM) Versions 5.00 and later

Programs should be assembled/compiled using the medium, large, or huge
memory model to be compatible with compiled BASIC, which is
effectively in the medium memory model.

Video Problems
--------------
   
QuickBASIC Version 4.50 is more selective of the video hardware on
which it will operate than QuickBASIC Versions 4.00 and 4.00b.
QuickBASIC requires a video card that is 100-percent compatible with
an IBM CGA, EGA, VGA, or Hercules Monochrome card.

If QB.EXE Version 4.50 does not operate with your video system, try
invoking QuickBASIC with each of the video-specific options, such as:
   
   Option      Description
   -----       -----------
   
   /b          (black-and-white) option
   /nohi       (no high-intensity) option
   /g          (update screen as fast as possible) option
   /h          (high-resolution) option

Example:

   qb /b

Also, try setting the video mode from MS-DOS using the MODE command
before initiating QuickBASIC (for example, MODE CO80 or MODE BW80).

Example:

   MODE CO80
   qb

   MODE BW80
   qb

If a ghost image appears after running QuickBASIC on your video
system, use the MS-DOS MODE command to clear the screen if CLS doesn't
clear it.

The following is a list of known compatibility problems:

1. According to Microsoft's testing, the following cards loaded
   QB.EXE, but had numerous problems with screen swapping:

      Tecmar VGA
      Quadram VGA
      Vega Video Seven FastWrite VGA
      Vega VGA (a customer suggested QB /H for better Vega VGA
         behavior)
   
2. According to Microsoft's testing, the following cards will not load
   QB.EXE:

      COMPAQ Laptop (BIOS problem -- no correction)
      COMPAQ SLT/286 (okay with AC power, fails with battery unless
         you disable the power-conservation utility PWRCON.EXE or
         PWRCON.COM.)
      Genoa SuperVGA HiRes
      ATI VIP VGA
      Sigma EGA


HINTS AND SUGGESTIONS
---------------------

Question:

How should I set up my COMmunications line in QuickBASIC 4.50?

Response:

If you have problems using COM1 or COM2, try the following OPEN
statement, which makes BASIC as tolerant as possible of hardware-
related problems:

   OPEN "COM1:300,N,8,1,BIN,CD0,CS0,DS0,OP0,RS,TB2048,RB2048" AS #1

(This OPEN is FOR RANDOM access.) The following is an explanation of
each recommended parameter used in this OPEN statement:

1. The higher the baud rate, the greater the chances for problems;
   thus, 300 baud is unlikely to give you problems. 2400 baud is the
   highest speed possible over most telephone lines, due to their
   limited high-frequency capability. 19,200 baud, which requires a
   direct wire connection, is most likely to cause problems. (Possible
   baud rates for QuickBASIC are 75, 110, 150, 300, 600, 1200, 1800,
   2400, 4800, 9600, and 19,200.)

2. Parity usually does not help you significantly; because of this,
   you should try No parity (N).

   For those devices that require parity, you should use the PE option
   (Parity Enable, required to turn on parity checking) in the OPEN
   COM statement. When the PE option turns on parity checking, a
   "Device I/O error" occurs if the two communicating programs have
   two different parities. (Parity can be even, odd, none, space, or
   mark.) For example, a "Device I/O error" occurs when two programs
   try to talk to each other across a serial line using the following
   two different OPEN COM statements:

      OPEN "COM1:1200,O,7,2,PE" FOR RANDOM AS #1

   and

      OPEN "COM2:1200,E,7,2,PE" FOR RANDOM AS #2

   If the PE option is removed from the OPEN COM statements above, no
   error message displays.

3. 8 data bits require No parity (N) because of the size limit for
   BASIC's communications data frame (10 bits).

4. The BIN (binary mode) is the default. Note: The ASC option does NOT
   support XON/XOFF protocol, and the XON and XOFF characters are
   passed without special handling.

5. Ignoring hardware handshaking often corrects many problems. Thus,
   if your application does not require handshaking, you should try
   turning off the following hardware line-checking:

      CD0 = Turns off time-out for Data Carrier Detect (DCD) line.
      CS0 = Turns off time-out for Clear To Send (CTS) line.
      DS0 = Turns off time-out for Data Set Ready (DSR) line.
      OP0 = Turns off time-out for a successful OPEN.

6. RS suppresses detection of Request To Send (RTS).

7. For buffer-related problems, try increasing the transmit and
   receive buffer sizes above the 512-byte default:
   
      TB2048 = Increases the transmit buffer size to 2048 bytes.
      RB2048 = Increases the receive buffer size to 2048 bytes.

A larger receive buffer can help you work around BASIC delays caused
by statements such as PAINT, which use the processor intensively.

The following are additional important hints for troubleshooting
communications problems:

1. You should use the INPUT$(x) function in conjunction with the
   LOC(n) function to receive all input from the communications device
   [where x is the number of characters returned by LOC(n), which is
   the number of characters in the input queue waiting to be read; n
   is the file number that you OPENed for "COM1:" or "COM2:"]. Avoid
   using the INPUT#n statement to input from the communications port
   because INPUT#n waits for a carriage return (ASCII 13) character.

   Avoid using the GET#n statement for communications because GET#n
   waits for the buffer to fill (and buffer overrun could then occur).

2. For an example of data communications, please refer to the
   TERMINAL.BAS sample program that comes on the release disk for
   QuickBASIC Version 4.50. Many communications problems may actually
   be due to inappropriate source code design and flow of control.

3. Many communications problems can be shown only on certain hardware
   configurations and are difficult to resolve or duplicate on other
   computers. We recommend experimenting with a direct connection
   (with a short null-modem cable) instead of with a phone/modem link
   between sender and receiver to isolate problems on a given
   configuration.

4. The wiring schemes for cables vary widely. Check the pin wiring on
   your cable. For direct cable connections, a long or high-resistance
   cable is more likely to cause problems than a short, low-resistance
   cable.

5. If both "COM1:" and "COM2:" are open, "COM2:" will be serviced
   first. At high baud rates, "COM1:" can lose characters when
   competing for processor time with "COM2:".

6. Using the ON COM GOSUB statement instead of polling the LOC(n)
   function to detect communications input can sometimes help you work
   around timing or buffering problems caused by delays in BASIC.
   Delays in BASIC can be caused by string-space garbage collection,
   PAINT statements, or other operations that heavily use the
   processor.

Many commercial communications programs use sophisticated techniques
not found in Microsoft BASIC, and may give better performance.

If you need better communications performance than you are getting
from BASIC, you may want to try Microsoft C. (You can call Microsoft C
Versions 5.x routines from QuickBASIC Version 4.50.)


Question:

Why doesn't QuickBASIC support COM3 and COM4 serial ports?

Response:

Support for these two additional communications ports requires a
larger code size for QuickBASIC in both the compiler and the run-time
module. Therefore, the decision was made NOT to support COM3 and COM4.

The QuickBASIC compiler supports the use of serial communications
ports COM1 and COM2 through the use of the OPEN "COM" statement.

To access COM3 and COM4, it is possible for compiled BASIC to call
third-party library routines, which are listed in catalogs such as the
"Programmer's Connection Buyer's Guide" [in the United States: (800)
336-1166, in Canada: (800) 225-1166, Customer Service: (216) 494-
8899]. For example, you may want to contact the Software Interphase
Company to determine if its QuickComm product supports COM3 and COM4,
which are called from Microsoft compiled BASIC.


Question:

Can you give an example of key trapping?
   
Response:

Pressing any key in combination with CTRL, SHIFT, ALT, CAPS LOCK, or
NUM LOCK changes the keyboard scan code. To trap combinations of keys,
the KEY statement requires adding together the values of the keyboard
flags as shown in the code example below.

The following is a code example:

   CONST alt = &H8
   CONST noflag = &H0
   CONST leftshift = &H1
   CONST rightshift = &H2
   CONST ctrl = &H4
   CONST numlock = &H20
   CONST capslock = &H40
   CONST extendedkeyboard = &H80
   CONST left = &H4B
   CONST right = &H4D
   CONST up = &H48
   CONST down = &H50
   CONST C = &H2E
   CONST scrolllock = &H46
   
   KEY 15, CHR$(extendedkeyboard + numlock) + CHR$(left)
   KEY 16, CHR$(extendedkeyboard + numlock) + CHR$(right)
   KEY 17, CHR$(extendedkeyboard + numlock) + CHR$(up)
   KEY 18, CHR$(extendedkeyboard + numlock) + CHR$(down)
   KEY 19, CHR$(ctrl + capslock) + CHR$(C)
   KEY 20, CHR$(extendedkeyboard + ctrl + numlock) + CHR$(scrolllock)
   
   ON KEY(15) GOSUB Keyleft
   ON KEY(16) GOSUB Keyright
   ON KEY(17) GOSUB Keyup
   ON KEY(18) GOSUB Keydown
   ON KEY(19) GOSUB Keybreak
   ON KEY(20) GOSUB Keybreak
   
   
   
   KEY(15) ON
   KEY(16) ON
   KEY(17) ON
   KEY(18) ON
   KEY(19) ON
   KEY(20) ON
   
   WHILE UCASE$(INKEY$) <> UCASE$("q")
   WEND
   END
   
   Keyleft:
    PRINT "left"
   RETURN
   
   Keyright:
    PRINT "right"
   RETURN
   
   Keyup:
    PRINT "up"
   RETURN
   
   Keydown:
    PRINT "down"
   RETURN
   
   Keybreak:
    PRINT "break"
   RETURN

Execution Speed
---------------

Question:

Why are the newer versions of QuickBASIC slower than the previous
ones?

Response:

The execution speed differences among different versions of QuickBASIC
are due to different internal floating-point math representations.
QuickBASIC Versions 1.00 and 2.00 used Microsoft Binary Format (MBF)
representation. QuickBASIC 3.00 was actually shipped with two
different versions: QB.EXE used MBF representation, and QB87.EXE, for
machines with a math coprocessor, used IEEE format floating-point
representation. All Microsoft BASIC products (for MS-DOS or OS/2)
since QuickBASIC Version 4.00 have used IEEE format exclusively.

There are several reasons why Microsoft chose to support the IEEE
floating-point standard rather than continuing to use MBF. The main
reason is that IEEE is the industry standard and is required for the
Intel 80x87 math coprocessors. Also, all other Microsoft language
products (except COBOL) use IEEE. Therefore, supporting IEEE in
QuickBASIC, as well, makes interlanguage programming using any
combination of these products much easier.

IEEE support, however, requires more overhead and did cause execution
speed to slow, although execution speed on machines equipped with a
math coprocessor is slightly faster than older (MBF) versions of
BASIC.

Since INTEGER math is much faster than floating-point math, the best
way to improve the speed of your program is to use INTEGER variables
whenever possible. One easy way to accomplish this is to use the
following code fragment in the beginning of your programs:

   DEFINT A-Z

The default, in BASIC, is to create new variables as SINGLE-precision
floating point. Using the DEFINT A-Z forces all new variables that are
not declared as some other type (usually this is done with a type
specifier such as x! for SINGLE precision) to be INTEGERs. On most
programs this makes a dramatic improvement. The variables that have
the greatest effect upon execution speed are those that are frequently
accessed, such as loop and array indexes. Make these types of items
INTEGERs whenever possible.

Limitations of Floating-Point Mathematics
-----------------------------------------

Question:

What are some mathematical rounding issues?

Response:

Floating-point mathematics is a complex topic that confuses many
programmers. The tutorial below should help you recognize programming
situations where floating-point errors are likely to occur and show
you how to avoid them. It should also allow you to recognize cases
that are caused by inherent floating-point math limitations as opposed
to compiler errors.

Decimal and Binary Number Systems
---------------------------------
   
Normally, we count things in base 10. The base is completely
arbitrary. (The only reason that people have traditionally used base
10 is that they have 10 fingers, which make handy counting tools.)
   
The number 532.25 in decimal (base 10) means the following:

   (5 * 10^2) + (3 * 10^1) + (2 * 10^0) + (2 * 10^-1) + (5 * 10^-2)
       500    +     30     +      2     +     2/10    +    5/100
   _________
   =  532.25

In the binary number system (base 2), each column represents a power
of 2, instead of 10. For example, the number 101.01 means the
following:

   (1 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (1 * 2^-2)
       4     +      0    +     1     +      0     +    1/4
   _________
   =  5.25  Decimal

How Integers Are Represented in PCs
-----------------------------------
   
Since there is no fractional part to an integer, its machine
representation is much simpler than it is for floating-point values.
Normal integers on PCs are 2 bytes (16 bits) long with the most
significant bit indicating the sign. Long integers are 4 bytes long.
Positive values are straightforward binary numbers. For example:

   1 Decimal = 1 Binary
   2 Decimal = 10 Binary
   22 Decimal = 10110 Binary  etc.

However, negative integers are represented using the "two's
complement" scheme. To get the two's complement representation for a
negative number, you need to take the binary representation for the
number's absolute value and then flip all the bits and add 1. For
example:

   4 Decimal = 0000 0000 0000 0100
               1111 1111 1111 1011     flip the bits
     -4      = 1111 1111 1111 1100     add 1

Note that -1 Decimal = 1111 1111 1111 1111 in binary, which explains
why BASIC treats -1 as logical true (all bits = 1). This is a
consequence of not having separate operators for bitwise and logical
comparisons. Often in BASIC, it is convenient to use the code fragment
below when your program will be making many logical comparisons. This
greatly aids readability.

   CONST TRUE = -1
   CONST FALSE = NOT TRUE

Note that adding any combination of two's complement numbers together
using ordinary binary arithmetic produces the correct result.

Floating-Point Complications
----------------------------
   
Every decimal integer can be exactly represented by a binary integer;
however, this is not true for fractional numbers. In fact, every
number that is irrational in base 10 also is irrational in any system
with a base smaller than 10.

For binary, in particular, only fractional numbers that can be
represented in the form p/q, where q is an integer power of 2, can be
expressed exactly with a finite number of bits. Even common decimal
fractions, such as decimal 0.0001, cannot be represented exactly in
binary (0.0001 is a repeating binary fraction with a period of 104
bits).

This explains why a simple example, such as the following will print
1.000054 as output:

   SUM = 0
   FOR I% = 1 TO 10000
      SUM = SUM + 0.0001
   NEXT I%
   PRINT SUM                   ' theoretically = 1.0
   
The small error in representing 0.0001 in binary propagates to the
sum.

For the same reason, you should always be very cautious when making
comparisons on real numbers. The following example illustrates a
common programming error:

   item1# = 69.82#
   item2# = 69.20# + 0.62#
   IF item1# = item2# then print "Equality!"

This will NOT print "Equality." Why? Because 69.82 cannot be
represented exactly in binary, which causes the value that results
from the assignment to be SLIGHTLY different (in binary) than the
value that is generated from the expression. In practice, you should
always code such comparisons in such a way as to allow for some
tolerance. For example:

   IF (item1# < 69.83#) AND (item1# > 69.81#) then print "Equal"

This WILL print "Equal."

Other Common Floating-Point Errors
----------------------------------
   
The following are common floating-point errors:

1. Round-off error

   This error results when all of the bits in a binary number cannot
   be used in a calculation.

   Example:  Adding 0.0001 to 0.9900 (SINGLE precision)

   Decimal 0.0001 will be represented as follows:

      (1.)10100011011011100010111 * 2^(-14+Bias)  (13 leading zeros in
                                                   binary!)

   0.9900 will be represented as follows:

      (1.)11111010111000010100011 * 2^(-1+Bias)

   Now to actually add these numbers, the decimal (binary) points must
   be aligned. For this they must be unnormalized. Here is the
   resulting addition:

       .000000000000011010001101 * 2^0  (Only 11 of 23 bits retained)
      +.111111010111000010100011 * 2^0
         ________________________________
       .111111010111011100110000 * 2^0

   This is called a round-off error because some computers round when
   shifting for addition. Others simply truncate. Round-off errors are
   important to consider whenever you are adding or multiplying two
   very different values.

2. Subtracting two almost equal values

       .1235
      -.1234
       _____
       .0001
      
   This will be normalized. Note that although the original numbers
   each had four significant digits, the result has only one
   significant digit.

3. Overflow and underflow

   This occurs when the result is too large or too small to be
   represented by the data type.

4. Quantizing error

   This occurs with those numbers that cannot be represented in exact
   form by the floating-point standard.

5. Division by a very small number

   This can trigger a "divide by zero" error or can produce bad
   results, as in the following example:

      A = 112000000
      B = 100000
      C = 0.0009
      X = A - B / C
      
   In QuickBASIC, X now has the value 888887, instead of the correct
   answer, 900000.

6. Output error

   This type of error occurs when the output functions alter the
   values they are working with.


More Information
----------------

For more information on floating-point mathematics, consult the
following references:
      
1. Stark, Peter A. "Introduction to Numerical Methods." McMillan
   Publishing, 1970.

2. Forsythe, George E; Malcolm, Moler. "Computer Methods for
   Mathematical Computations." Prentice-Hall, 1977.

For further information on the topics covered in this article, consult
the following reference books:

1. Hergert, Douglas. "Microsoft QuickBASIC Developing Structured
   Programs in the Microsoft QuickBASIC Environment." Microsoft Press,
   1989.

2. Wilton, Richard. "Programmer's Guide to PC & PS/2 Video Systems."
   Microsoft Press, 1987.
   
3. Norton, Peter. "The New Peter Norton Programmer's Guide to the IBM
   PC & PS/2." Microsoft Press, 1985.

4. Duncan, Ray. "Advanced MS-DOS Programming." Microsoft Press, 1988.

5. Clark Craig, John. "Microsoft QuickBASIC Programmer's Toolbox."
   Microsoft Press, 1988.

