SHADOBOX.DOC ver 0.0  11/21/87

                                 SHADOW BOXES
                      the Donohue&Co. Windowing package
                        for TurboC and some other compilers*
                                 Documentation

Copyright (c) 1987 John G. Donohue
                   Donohue&Co. Computer Services
                   PO Box 255
                   Hannibal, NY  13074
                   (315) 564-6213

      This product is not public domain.  It is the exclusive property
      of John G. Donohue, and may not be used without his consent.
      No translation of the product to any other environment may be made
      in any form without written permission of Donohue&Co.
      This document and the object files used to form programs with
      windowing form a shareware product: You are encouraged to copy it
      and share it with others freely, for disk copying fees up to $3,
      but not for profit.  Dealership arrangements of the Source Code
      product are available.

      Donohue&Co. makes no warranties, expressed nor implied, as to the
      merchantability or fitness of any part of this product for any
      particular purpose.  Further, Donohue&Co. shall not be responsible 
      for damages of any kind, including consequential damages, resulting
      from use of this product.

              --------------------- o  o  o ---------------------

WHAT IS THIS PACKAGE?

This package contains the necessary data structures and functions to allow
a C programmer to construct efficent, visually appealing programs.

Typically, a windowing library sells for $100 to $200.  But other packages
don't give you the truly EXTRAORDINARY control over 

        borders (you can mix ANY combination of styles on ANY of the
        four sides, including no border on one side),

        shadows (REAL SHADOWS that "darken" the text in shadow!),
        [That's why we call it "Shadow Boxes"]

                                      and

        retaining contents (optionally) of windows even when they are closed.

We're distributing this version in shareware for two reasons:

        So you can run WDEMO and be convinced this is the nicest package
        you've seen, without ever investing a cent.  (And if you like it,
        and you have a TurboC compiler, you can use it freely forever.)

        If you want the Source Code, or a version for another popular compiler,
        you can get BOTH for less than half -- less than a fourth! --
        of what other windowing libraries would cost WITHOUT source code --

                         Just $45 for FULL WINDOWS SOURCE CODE!

        PULL-DOWN MENUS available!

        If you want PULL-DOWN (and other) MENUS, you can have those too --
        with an unbelievable array of menu features:

             Horizontal or Vertical or "Wordy," with choices interspersed
             Lotus-style bar menus, (if you want), or use special keys
             Help messages for each choice on the menu
             "Invisible" menu choices possible
             Hang menus off previous choices
             Key menu colors in a hierarchy
             All window attributes apply to menus, even Shadows, if you like.

             and FULL MENU SOURCE CODE!

        If you order the Menu Package at the same time as the
        Window Source Code, you get the Menus Package for just $15!
        Ordered later, it's $25.

        Application consulting is available by phone or in person
        at normal consulting rates.

When you purchase any of the above, you will receive the latest version,
with newer features and expanded documentation, as well as availability
of later versions at very modest charges.
At any time, the Source Code version may have additional features
beyond those of the shareware version.

  This version contains precompiled modules (*.OBJ), a demo file in both
  source and executable form (WDEMO.C and WDEMO.EXE), and instructions.
  The OBJ files are suitable for use with Turbo C or Microsoft C version 3
  or later, but probably not with other compilers.
  (Different compilers use the 8088's registers differently.)
  If you wish to use the modules with another compiler,
  you must purchase the source code version and compile it yourself.
  The price is modest, and you will have an excellent example of 
  highly portable C source code to study.


              --------------------- o  o  o ---------------------

                           How to use "SHADOW BOXES",
                       the Donohue&Co. Windowing package

FEATURES

  You may create any number of overlapping windows, and "lift them off"
  each other to display what they "covered".  There is always a "bottom
  window", which is the screen that appeared when the program was invoked.
  There is no automatic clearing of the screen when execution begins, so
  you may utilize a form which is independent of the windowing system in
  the "standard screen" (bottom window).

  Color may be used functionally or decoratively, and you have a variety 
  of specific control over each window's borders, shadows, and location, 
  and the edge of the screen.

  Your writing is not restricted to the "top" window.
  Although you may not write on a the part of a window which is "covered" 
  by another window, you MAY write on the visible (uncovered) portion of ANY
  window.

  You may scroll windows, either by command or by outputting a '\n' character.

  You may mix borders in one window, individually controlling each of the
  four sides, if you wish:
    (bar across the top, single line on left side, 
     double line on right side, NO BORDER on bottom)
  -- and the corners figure themselves out!
  On a long, top-to-bottom-of-the-screen menu, you might choose to have a
  left and right border, but no top or bottom, so you can scroll it up and
  down off the page.

  The border may be different background and foreground colors from the
  main text area.

  Cursor locations begin at (0,0), the upper left hand corner of the
  WRITEABLE PORTION of the window.  However, you MAY write on the borders,
  or even outside the window, if you insist.

  You cannot write to a defined-but-undisplayed window in this version.

  A window's shadow, if you select one, is always on the left and bottom
  of the window.  It dims characters it covers, and makes their background
  black.

  A window may be displayed in only one place AT A TIME on screen, but
  may be "closed" and "reopened" in a different location.  It RETAINS ITS
  PREVIOUS CONTENTS, unless it was defined with the CLEAR_ON_OPEN bit set.

  You may constantly change the colors of characters, by "setting" a new
  foreground or background color, bright, blinking, or any combination.
  Once a setting is made, it applies to all subsequent characters displayed
  until changed again.  When the window scrolls, the new line is filled with
  the INITIAL DEFAULT BACKGROUND COLOR, not the current color.  If the
  window is "closed" and "reopened", it remembers THAT WINDOW'S last
  color/bright/blinking setting (its "attribute"), and its last 
  cursor position.

  There is a foreground/background color combination called TRANSPARENT,
  designed for a special use.
  Normally, you set a color attribute, then you display text, and the text
  appears in the color combination chosen.  
  However, some people prefer to display an entire "mask" or "form" with
  boxes of various colors already there.  In this case, instead of setting
  the appropriate attribute before displaying characters in each box, you
  may simply set the attribute TRANSPARENT, and subsequently displayed
  character will appear in the color combination that the location ALREADY HAS.
  Therefore, if you overwrite characters that were RED foreground and
  BLUE background, the characters you write will appear in THAT combination
  -- EVEN IF YOU CROSS COLOR BOUNDARIES WITHIN THE TEXT YOU WRITE!
  This is useful for writing a single string, but having it "land" in
  different color "boxes".  They will always be the right color.

  If the window is full-screen in size (or even if it is not), you may
  set the screen edge (outside the largest rectangle) to the
  border background color.


PROCEDURES

  You must initialize the windowing system before using any other
  windowing function.  No visible effect of the initialization occurs.
  (The screen is NOT cleared, but white characters on a black background
  are assumed the default for the "standard screen" unless changed.)

  You must DEFINE a window before using it.  This means setting its
  size (shape), colors, borders, and some of its operational characteristics
  (e.g., whether it should be cleared every time it is opened).
  You do NOT set its location!  This is done when it is OPENED (displayed).
  It may be opened at any location, provided that it fits ENTIRELY on the
  screen.  The window is assigned a "window number" when it is defined.
  It is a good idea to define all windows at the start of your program,
  since this is when memory is allocated for them.  (If you're going to
  run out of memory, you might as well do it right away.)  
  The program allocates only enough memory for the windows you use.
  Note: The order in which windows are DEFINED is insignificant.

  To display a window, you OPEN it, at a particular LOCATION relative to 
  the entire screen (not relative to the currently open window).
  You must have previously DEFINED it.  The area it "covers" (including
  the area changed by the "shadow", if any) is saved, and the window is
  displayed, becoming the "top window" (in a stack).  This also makes it
  the "current window".  All displays, attribute and cursor settings
  affect only the "current window".
  NOTE: You can now make some other (at least partially visible) window
  the "current window", and display to it, but it is a wise policy to
  return to the top window as soon as possible.  This is because the
  ONLY window that can be "closed" is the top window: that is, you must
  "lift off" the windows in the same order in which you "laid them down."
  Your application may require setting up three non-overlapping windows
  on the screen and keeping them open rather permanently.  This is fine,
  but at the end, you must close them in reverse order IF you wish to
  remove them.  If you don't care that they remain on your screen at the
  end of the program, you need not close them.

  To display text, there are three typical steps:
    - set the attribute (for subsequently displayed characters)
    - set the cursor (relative to the writeable [non-border] area of the window)
    - display text (including newlines).
  The attribute setting continues until changed.  Even if the window is
  closed and reopened, the last-set attribute will be remembered for EACH
  WINDOW SEPARATELY!
  The cursor will advance one space after displaying any character except
    - \n, which advances it to the start of the following line, scrolling
          the window if necessary
    - \r, which returns it to the start of the current line
    - \t, which tabs to the next multiple-of-8 column within the window,
          advancing to the next line (and even scrolling) if necessary.
  ALL OTHER CHARACTERS are treated as displayable!

  When you CLOSE a window, its contents are saved, its current cursor and
  attribute settings are saved, the information it "covered"
  when displayed is redisplayed.


The CODE

  With the source code (available at modest cost), the routines are 
  almost totally portable.  The discussion below explains how hardware-
  dependent items like attribute settings, etc. are tailored to individual
  systems.

  The macro LINT, if defined, allows prototypes of the functions
  to be included into your program for type-checking.

  The code provided in the standard version will work with 
  Borland's Turbo C and Microsoft C, which both use register return values
  and register variables the same way.

  In this package, a structure called a _window may be addressed by its
  "window number", which is assigned to it when it is defined.

/*****************************************************************************/
THE WINDOW STRUCTURE
struct _window
{
  /* When defined */
        BITS    wstatus;        /* initially zero if no window defined here. */
        BITS    wbordstyle;
        WATTR   wbordattr;
        RECT    wpane;          /* "writeable" area of window.  May be adjusted
                                   after open by "pane_" functions. */
        RECT    wrectb;         /* possibly bigger than above for borders,
                                   shadow. */
  /* When opened */
        int     wscreen;        /* screen page.  Not necessarily hardware-
                                   related.  Currently force screen 0. */
        SCNCHAR *wunder;        /* pointer to 1st char of block where stuff
                                   covered up is saved. */
  /* When closed */
        WATTR   wdftattr;       /* default attribute in this window (scroll) */
        WATTR   wattr;          /* last set attribute in this window */
        COORD   wrow, wcolumn;  /* 0,0 when w_def()'d, saved cursor value 
                                   when closed. */
        SCNCHAR *wsave;         /* window data, incl border, written to ONLY
                                   when window closed (unless wstatus has
                                   NOSAVE).
                                   IF you later allow writing to memory images
                                   as well as those on screen, or to "hidden"
                                   windows, this may be written to on each
                                   character. */
};

/*****************************************************************************/
THE FUNCTIONS

ERRCODE w_init(void);

        You must invoke this function first.  It figures out what kind of
        video you're using.
        It sets up basic variables, examines hardware by invoking hw_winit(), 
        allocates space, decides which type of output to use, etc.
        The assumption is that windows[] was already defined.

        Returns: an error code
                NO_ERROR        No error.
                COMPAT_ERR      Not a screen type that BIOS recognizes (2,3,7)


WNUM    w_def(WNUM w, BITS status, COORD hgt, COORD wid, 
              WATTR attr, BITS bordstyle, WATTR bordattr);

        Use this function to define the shape, colors, and characteristics
        of a window you want to use.
        This must be done before the window is opened for the first time,
        and needs to be done only once.
        It allocates buffers for storing window images, sets values.
        Window is not "opened" by this procedure.
        If a border is specified, writable portion of window is smaller than
        the size you specify.
        If no border, entire window can be written to.
        NOTE THAT WE DON'T DEFINE THE STANDARD SCREEN: IT IS ALREADY DEFINED!
        Note also that the screens need not be DEFINED in a stack order,
        but when they are OPENED, the order of opening is stacked, and they
        must be CLOSED in the reverse order.

        w       Windows are identified by their WNUM ("window number").
                Typically, you use a -1 here, instructing the function to
                assign the window the next available window number, which
                is returned by the function.  However, if you enter a valid
                window number (0 < w < MAXWIN), it will be used.

        status  bits should be ORed together.  (0 is normal)
                                set by w_def():
                CLEAR_ON_OPEN   Clear window every time window is opened.
                NO_SCROLL       Continue to write in last window position.
                NOSAVE_ON_CLOSE Not used.
                DELETE_ON_CLOSE Not used.
                INVISIBLE       Not used.
                DONT_CLOSE      Not used.
                DONT_ERASE.     Not used.
                                bits set internally:
                DEFINED_, OPENED_, MAYDELETE_.

        hgt and
        wid     dimensions of the window, INCLUDING BORDER, but not including
                shadow, which is attached left and below if required.
                top and left are set when opened somewhere.

        attr    sets background and foreground standard colors, both the
                DEFAULT ATTRIBUTE (which remains permanent for clearing and
                                   scrolling the window), and
                CURRENT ATTRIBUTE (which affects subsequent characters).
                When you close and reopen windows or switch the current
                window, the last-set CURRENT ATTRIBUTE is retained and
                used when you return to that window later.

        bordstyle
                bits which determine which sides have borders, and if so,
                what kind.  The bits should be ORed together (0=no border).
                The low-order 8 bits are
                           +---+---+---+---+---+---+---+---+
                           |  top  | bottom|  left | right |
                           +---+---+---+---+---+---+---+---+
                Note that each "side" of the window requires two bits
                to describe what sort of border it has:
                        0 = no border, no space allocated for one
                        1 = single line border
                        2 = double line border
                        3 = block border
                In addition, if you want a shadow, OR in the following:
                        BORD_SHADOW
                And if you want to set the edge of the screen to the border 
                color, (the outer edge of display, surrounding the 80*25), 
                OR in:
                        BORD_EDGE

                Example: Suppose we want single lines on the left and right
                         sides, a double line on the bottom, NO BORDER on
                         the top, and a shadow.  The bordstyle would be:
                            top     bottom   left    right
                           0 * 64 | 2 * 16 | 1 * 4 | 1 * 1 | BORD_SHADOW
                         Bit values:
                             00       10       01      01  | BORD_SHADOW
                         simplified:
                                                      0x25 | BORD_SHADOW

                Both EDGE and SHADOW are IN ADDITION to other borders.

        bordattr
                Sets background and foreground border colors.
                The border attribute is not changeable later, but you can
                set the current attribute of the window to something else,
                then overwrite the border with w_puts().

        Returns: EITHER an error code, if there is an error, or
                 the window number that will be used from this point on
                 to reference this window.
                Does NOT return NO_ERROR, lest there be confusion.
                All error numbers are assumed to be >= MAXWIN.
                WNUM_ERR        Attempting to define the a window as number 0,
                                which is the already-defined "standard window",
                                                  OR
                                argument w is >= MAXWIN.
                                                  OR
                                you chose a window number w which is already
                                in use.
                MAXWIN_ERR      MAXWIN windows already defined: no room in array.
                SMALL_ERR       Window is so small there are either no rows
                                or no columns in it.
                NOFIT_ERR       Window is too large to fit on screen.
                BUFFER_ERR      Either the wsave or wunder buffer pointer
                                is non-NULL.  This should never happen, as it
                                it initialized to NULL and returned to that
                                status when a window is w_delete()'d.
                OM_ERR          Ran out of memory doing a calloc().


ERRCODE w_open(WNUM w, COORD top, COORD left);

        If the CLEAR_ON_OPEN bit was set when the window w was defined,
        then clear the stored display of this window first.
        Open (display) the indicated window at the indicated location,
        and make it the "current window" (the window which will receive
        subsequent w_cursor() settings, w_attr() settings, and displays).
        The last-used attribute of this window becomes the current attribute,
        and the last-used cursor position becomes the current cursor position.
        Color the outer screen edge if BORD_EDGE bit was set when this
        window was defined.  
        Create the shadow if BORD_SHADOW bit was set when this window
        was defined.

        w       the window number returned by w_def().

        top and 
        left
                Relative to the standard screen.  If the window has upper/left 
                border(s), the upper-left corner of the border will be placed 
                at these coordinates, so the writeable area of the window 
                may be one row down and/or one column to the right.

        Returns: an error code
                NO_ERROR        No error.
                WNUM_ERR        Window w is < 0 or >= MAXWIN.
                WOPND_ERR       Window w is already open.
                WDEFD_ERR       Window w is not defined.
                NOFIT_ERR       Window (or its shadow) cannot fit on screen 
                                in location specified by row, column.
                any scn_saverect() error
                  NO_ERROR        No error.
                any scn_loadrect() error
                  NO_ERROR        No error.
                any w_current() error
                  any w_cursor() error
                    CLIPPED_ERR     row, column cannot be within the current window.
                    any scn_cursor() error
                      NO_ERROR        No error.
                      any hw_cursor() error
                        NO_ERROR        No error.


ERRCODE w_current(WNUM w);

        Make the indicated window the "current window".  You do this when
        you want to write to a window which is NOT the top window.
        This window may have been partially overlaid, so it is the programmer's
        responsibility to insure that reads/writes do not occur on the
        overlaid area.  (A later version may allow writing to overlaid regions.)
        Note that this also prohibits scrolling, if this window is partially
        overlaid.  A "w_open" does a w_current() implicitly.
        This saves the attribute of the previously current window (its
        cursor position is saved continuously), sets the attribute of
        the new current window to be the current attribute, and the cursor
        position in the new current window to be the current cursor position.

        Returns: an error code
                any w_cursor() error
                  CLIPPED_ERR     row, column cannot be within the current window.
                  any scn_cursor() error
                    NO_ERROR        No error.
                    any hw_cursor() error
                      NO_ERROR        No error.


ERRCODE w_close(WNUM w);

        Close the indicated window (i.e., save its contents, remove it
        from the screen, and restore previous overlaid data.  
        Then IF w is the current window, make the next lower window
        the current window.
        w MUST be the top window, but it does NOT have to be the CURRENT WINDOW.
        If w is STDWNUM (the standard screen), it never closes, but does not
        create an error if you attempt to close it.

        Returns: an error code
                NO_ERROR        No error, or w is STDWNUM, which cannot 
                                be closed.
                NOTTOP_ERR      w is not top window.
                any scn_saverect() error
                  NO_ERROR        No error.
                any scn_loadrect() error
                  NO_ERROR        No error.
                any w_current() error, which is exactly...
                any w_cursor() error
                  CLIPPED_ERR     row, column cannot be within the current window.
                  any scn_cursor() error
                    NO_ERROR        No error.
                    any hw_cursor() error
                      NO_ERROR        No error.


ERRCODE w_delete(WNUM w);

        Delete the indicated window, releasing buffer space.  
        It must not be the "standard window" (the full screen).
        It must not be open.
        Avoid this function if possible.  Try to reuse windows rather than
        using a zillion different ones.

        Returns: an error code
                NO_ERROR        No error, or w is STDWNUM, which cannot 
                                be deleted.
                WOPND_ERR       Window w is already open.


ERRCODE w_cursor(COORD row, COORD column);

        Set cursor to indicated coordinates (relative to 0,0 at upper-left
        corner of writeable area of current window).
        If either coordinate is the macro POSITION instead of a row or
        column number, the cursor remains in the SAME row or column,
        respectively, and the OTHER coordinate changes.
        NOTE:  This function sets the coordinates logically, but the 
               visible blinking cursor IS NOT SET by the normal invocation
               of this function.
               If you write directly to ram without using ROM routines, 
               the cursor may blink in one place when you are actually 
               writing somewhere else.
               This is no harm, but it misleads the operator.  Occasionally
               in the code we force it into position, but not enough.
               To set the physical cursor yourself, first set the logical
               cursor, then invoke this function as follows:
                  w_cursor( POSITION, POSITION );
               You MAY physically position hardware cursor, but don't
               if you don't have to, as it slows down displays.

        TECHNICAL:  Sets screen coordinates to correspond, using scn_cursor().

        Returns: an error code
                CLIPPED_ERR     row, column cannot be within the current window.
                any scn_cursor() error
                  NO_ERROR        No error.
                  any hw_cursor() error
                    NO_ERROR        No error.


int     w_putc(int c);

        The standard "display a character" command (used by w_puts()).
        Displays character to current location on current window, 
        using most recently set attribute.
        (Attribute may be TRANSPARENT, in which case it will use
        existing attribute at current location.)

        The cursor will advance one space after displaying any character except
          - \n, which advances it to the start of the following line, scrolling
                the window if necessary
          - \r, which returns it to the start of the current line
          - \t, which tabs to the next multiple-of-8 column within the window,
                advancing to the next line (and even scrolling) if necessary.
        ALL OTHER CHARACTERS are treated as displayable (including control
        characters)!  
        The "current location" advances, scrolling the window if necessary, 
        (unless window was defined with NO_SCROLL bit).
        This works even if you write to last position on screen.
        If cursor WAS within the window, it STAYS within the window.

        LATER, not implemented in this version:
        The window may be INVISIBLE, in which case writing
        can be done to saved image without displaying the window.  Otherwise
        writing is always done to the displayed image (screen itself).

        Returns: an error code
        Currently, the code returns an error code, not the character.
        In future, might be declared as ERRCODE w_putc(int c);
                NO_ERROR        No error.
                any w_cursor() error
                  CLIPPED_ERR     row, column cannot be within the current window.
                  any scn_cursor() error
                    NO_ERROR        No error.
                    any hw_cursor() error
                      NO_ERROR        No error.


ERRCODE w_puts(char *s);

        The standard "display text" command (like "print").
        Displays the NULL-terminated string s in the current attribute
        [or TRANSPARENT] at the current row and column of the current window.
        The text may include \r, \n, \t, which are processed per w_putc().

        The "current location" advances character by character, scrolling the 
        window if necessary, (unless window was defined with NO_SCROLL bit).

        This is the intelligent output for the general case.
        ERRCODE scn_ws(char *s) may be used for greater speed, but 
        it does not check whether you overwrite window boundaries.

        Returns: an error code
                NO_ERROR        No error.


              POSSIBLY ENVIRONMENT-DEPENDENT/OPTIMIZABLE FUNCTION
              This function must exist, but may need to be optimized to the
              specific operating system, screen, etc.

ERRCODE w_setattr(int attrtype, WATTR attr);

        Set a foreground or background color, or 
        set/reset bright or blink attributes of subsequently displayed 
        characters.

        The settings may be done incrementally (e.g., "just change the
        background color, but leave the other settings alone", or
        the entire attribute may be set, removing previous settings.
        If screen is memory-mapped, no output takes place when this 
        function is invoked.  (If a terminal, the function hw_setattr()
        is invoked to register the new setting.)  This function ususally
        only affects the appearance of subsequently output characters.

        The first argument, attrtype, indicates which kind of setting is
        being done.  The second argument, attr, is the specific value
        to which it should be set.  The values for each are limited to
        those defined in WDEF.H.

        attrtype    
                The first argument Must be one of the following:
                SET_    to turn ON  BRIGHT, BLINK, or UNDERLINE
                RESET_  to turn OFF BRIGHT, BLINK, or UNDERLINE
                FGC_    to set foreground color
                BGC_    to set background color
                ENTIRE_ to replace entire attribute (including BLINK, BRIGHT,
                        and UNDERLINE settings)

        attr
                If attrtype is SET_ or RESET_, 
                        this indicates WHICH attribute (among BRIGHT, BLINK, 
                        or UNDERLINE) is being set or reset.
                If attrtype is FGC_,
                        this should be a macro for beginning with "FG_".
                If attrtype is BGC_,
                        this should be a macro for beginning with "BG_".
                If attrtype is ENTIRE_,
                        this should be the ORed value of a foreground color,
                        a background color, and whichever of BRIGHT, BLINK,
                        or UNDERLINE are to be turned ON.  (Of those three,
                        any not named are turned OFF.)
                        If either the foreground or background color is omitted,
                        it defaults to color 0 (black on an IBM PC).

        Examples:
                w_setattr(SET_, BRIGHT);
                w_setattr(RESET_, BLINK);
                w_setattr(FGC_, FG_RED);
                w_setattr(BGC_, BG_CYAN);
                w_setattr(ENTIRE_, FG_RED|BG_CYAN|BRIGHT);

        Note: It would be an error (though it would compile correctly)
        to use
                w_setattr(BGC_, FG_RED);
        since FG_RED is strictly a foreground color.  The effect would
        be to turn the background to color 0 (black on an IBM PC), and 
        change the foreground to the bit combination of the old and new
        foreground colors.

        Returns: an error code
                NO_ERROR        No error.


ERRCODE w_scroll(int dir, int num);

        Scroll the current window text num lines in direction dir.
        dir     Must be either UP or DOWN.
        num     If 0, means "clear the current window".

        This version uses one of the BIOS functions.

        Returns: an error code
                NO_ERROR        No error.


ERRCODE w_err(ERRCODE);

        A function used internally, which you may use also.  It is invoked
        whenever an error code is generated.  It may be used to print a
        message to the operator, or do nothing, or whatever you like.

        Returns: the error code given in its argument.


KEYCHAR getv(void);

        The standard "get a character from the keyboard" function.
        Sets the physical cursor, so operator can see where to enter
        a character.  Does not return until a key is pressed.
        It returns a normal ASCII character when that is pressed.
        For function keys, etc., 0xFE00 is ORed into the extended key value.

        Returns: The (possibly transformed) key value


KEYCHAR getcv(void);

        This function calls getv(), looks up non-ASCII values in a table,
        then returns the lookup value, if any, otherwise the original value.
        It allows designation of certain keys for HELP or LEFT/RIGHT
        or other purposes in a hardware-independent manner.
        The current version is hardcoded to convert only one value:
          the ESCape key returns the KEYCHAR value "CANCEL".

        Returns: The (possibly transformed, then possibly converted) key value


                           Convenience macros

#define w_writerc(row, col, s)  (w_cursor(row, col) ? werrnum : w_puts(s))
#define iswopen(w)              (windows[w].wstatus & WOPENED_)
#define BUG(msg)                printf(msg);
#define w_writexy(col,row,s)    (w_cursor(row, col); w_puts(s))
#define w_gotoxy(x,y)           w_cursor(y,x)
#define w_getcy()               cw->wrow
#define blink()                 w_setattr(SET_, BLINK)
#define noblink()               w_setattr(RESET_, BLINK)
#define bright()                w_setattr(SET_, BRIGHT)
#define nobright()              w_setattr(RESET_, BRIGHT)

A SCNCHAR is the chunk of physical data containing the physical character
and attribute.  It is the thing which, in an array, makes up the physical
screen.




/*****************************************************************************/
         The following information is probably of little use to you.
/*****************************************************************************/

                             Internal functions

ERRCODE scn_ws(char *);
                NO_ERROR        No error.
ERRCODE scn_was(char *);
                NO_ERROR        No error.
ERRCODE scn_cursor(COORD, COORD);
                NO_ERROR        No error.
                any hw_cursor() error
ERRCODE scn_saverect(RECT *, SCNCHAR *);
                NO_ERROR        No error.
ERRCODE scn_loadrect(RECT *, SCNCHAR *);
                NO_ERROR        No error.
ERRCODE scn_edge(WATTR attr);
                NO_ERROR        No error.

int     scn_wc(int c);
SCNCHAR scn_wscnchar(SCNCHAR);
SCNCHAR scn_rscnchar(void);
/*
WATTR   scn_ra(void);
int     scn_wconly(int c);
WATTR   scn_waonly(WATTR);
*/
SCNCHAR ca_to_scnchar(int, WATTR);
ERRCODE hw_initscn(void);
                NO_ERROR        No error.
                COMPAT_ERR      Not a screen type that BIOS recognizes (2,3,7)
ERRCODE hw_cursor(void);
                NO_ERROR        No error.
#ifdef MEMMAPPED
#define hw_setattr() /* Don't send anything to screen when attribute changes. */
#else
#ifdef LINT
ERRCODE hw_setattr(void);
#endif
#endif

                    Functions from the Standard Library

char    *calloc(unsigned int, unsigned int);
void    exit(int);
void    free(char *);
int     printf(char *, ...);
int     sprintf(char *, char *,...);    ???
int     strlen(char *);                 ???
int     toupper(int);                   ???

        Functions that are MS-DOS- (and possibly compiler-) dependent

int             int86(int, struct REGS *, struct REGS *);
unsigned int    peek(unsigned int, unsigned int);
