                                                     Table of Contents   i



Introduction


License\Disclaimer.............................................. 1
Installation.................................................... 2
Contents of disk................................................ 3
Compiling\Linking............................................... 4
Registration\Upcoming features.................................. 5
Technical Support............................................... 6


Library Reference


Chapter 1.     Colors
Overview/Concepts............................................... 8
function List................................................... 10
   v_getcolor................................................... 11
   v_setcolor................................................... 12
   w_setup...................................................... 13


Chapter 2.     Screen
Overview/Concepts............................................... 16
function List................................................... 17
  v_clear....................................................... 18
  v_getcols..................................................... 19
  v_getmode..................................................... 20
  v_getmonitor.................................................. 21
  v_getrows..................................................... 22
  v_prtf........................................................ 23
  v_restscrn.................................................... 24
  v_savescrn.................................................... 25
  v_setmode..................................................... 26
  v_setrows..................................................... 27


Chapter 3.     Windows
Overview/Concepts............................................... 29
function List................................................... 30
   w_clear...................................................... 31
   w_close...................................................... 32
   w_clrscrn.................................................... 33
   w_display_config............................................. 34
   w_errbox..................................................... 35
   w_exit....................................................... 37
   w_getborder.................................................. 38
   w_hscroll.................................................... 39
   w_init....................................................... 40
   w_isopen..................................................... 41
   w_open....................................................... 42
   w_prtf....................................................... 43
   w_setborder.................................................. 44
   w_vscroll.................................................... 45
   w_ynbox...................................................... 46

                                                     Table of Contents   ii



Chapter 4.     Menus
Overview/Concepts............................................... 48
function List................................................... 49
   m_close...................................................... 50
   m_filebox.................................................... 52
   m_listbox.................................................... 54
   m_menu....................................................... 56
   m_scrollmenu................................................. 59

Chapter 5.     Help
Overview/Concepts............................................... 62
function List................................................... 64
   w_help....................................................... 65


Chapter 6.     Data Entry
Overview/Concepts............................................... 67
function List................................................... 75
   g_char....................................................... 76
   g_checkbox................................................... 77
   g_close...................................................... 79
   g_date....................................................... 80
   g_double..................................................... 81
   g_ext_date................................................... 82
   g_ext_time................................................... 83
   g_ext_zip.................................................... 84
   g_filename................................................... 85
   g_float...................................................... 87
   g_int........................................................ 88
   g_long....................................................... 89
   g_password................................................... 91
   g_phone...................................................... 92
   g_read....................................................... 93
   g_soc_sec.................................................... 94
   g_string..................................................... 95
   g_tf......................................................... 96
   g_time....................................................... 97
   g_unchar..................................................... 98
   g_unint...................................................... 99
   g_unlong..................................................... 100
   g_yn......................................................... 101
   g_zip........................................................ 102


Chapter 7.     Keyboard
Overview/Concepts............................................... 104
function List................................................... 105
   k_beep....................................................... 106
   k_flush...................................................... 107
   k_getkey..................................................... 108
   k_putkey..................................................... 109
   k_set........................................................ 113
   k_status..................................................... 114
   k_wait....................................................... 115

                                                     Table of Contents   iii





Chapter 8.     Cursor
Overview/Concepts............................................... 117
function List................................................... 118
   v_curbak..................................................... 119
   v_curdn...................................................... 120
   v_curfwd..................................................... 121
   v_curoff..................................................... 122
   v_curon...................................................... 123
   v_curup...................................................... 124
   v_getcur..................................................... 125
   v_setcur..................................................... 126
   v_setcurtype................................................. 127
   w_curbak..................................................... 128
   w_curdn...................................................... 129
   w_curfwd..................................................... 130
   w_curup...................................................... 131
   w_getcur..................................................... 132
   w_setcur..................................................... 133


Chapter 9.     Time
Overview/Concepts............................................... 135
function List................................................... 136
   t_add........................................................ 137
   t_check...................................................... 138
   t_clock...................................................... 139
   t_curtime.................................................... 140
   t_exttimestr................................................. 141
   t_strexttime................................................. 142
   t_strtime.................................................... 143
   t_sub........................................................ 144
   t_timestr.................................................... 146


Chapter 10.    Date
Overview/Concepts............................................... 148
function List................................................... 149
   d_add........................................................ 150
   d_calendar................................................... 151
   d_check...................................................... 152
   d_curdate.................................................... 153
   d_datestr.................................................... 154
   d_extdatestr................................................. 155
   d_inmonth.................................................... 156
   d_julian..................................................... 157
   d_leapyear................................................... 158
   d_month...................................................... 159
   d_ofweek..................................................... 160
   d_strdate.................................................... 161
   d_strextdate................................................. 162
   d_sub........................................................ 163

                                                     Table of Contents   iv




Chapter 11.    String
Overview/Concepts............................................... 165
function List................................................... 166
   s_strins..................................................... 167
   s_strpad..................................................... 168
   s_strrem..................................................... 169
   s_strsub..................................................... 170
   s_strtok..................................................... 171

Chapter 12.    Files
Overview/Concepts............................................... 173
function List................................................... 174
   f_copy....................................................... 175
   f_delete..................................................... 176
   f_edit....................................................... 180
   f_filebox.................................................... 181
   f_fileio..................................................... 183
   f_fullpath................................................... 185


Chapter 13.    Mouse
Overview/Concepts............................................... 187
function List................................................... 189
   m_button..................................................... 190
   m_copyright.................................................. 191
   m_curoff..................................................... 192
   m_curon...................................................... 193
   m_debounce................................................... 194
   m_double..................................................... 195
   m_getcur..................................................... 196
   m_getpress................................................... 197
   m_getrelease................................................. 198
   m_graphcur................................................... 199
   m_init....................................................... 201
   m_keytrans................................................... 202
   m_motion..................................................... 203
   m_setcnrs.................................................... 204
   m_setcur..................................................... 205
   m_sethor..................................................... 206
   m_setver..................................................... 207
   m_textcur.................................................... 208
   m_version.................................................... 210


Chapter 14.    Printer
Overview/Concepts............................................... 212
function List................................................... 216
   p_char_set................................................... 217
   p_code....................................................... 219
   p_color...................................................... 221
   p_end........................................................ 222
   p_font....................................................... 223
   p_height..................................................... 224
   p_init....................................................... 225
   p_orientation................................................ 226

                                                     Table of Contents    v



   p_pause...................................................... 227
   p_prtchr..................................................... 228
   p_prtf....................................................... 229
   p_quality.................................................... 230
   p_redirect................................................... 231
   p_restore.................................................... 234
   p_set_port................................................... 234
   p_start...................................................... 235
   p_style...................................................... 237

Chapter 15.    Network
Overview/Concepts............................................... 239
function List................................................... 245
  n_bindery_default_server...................................... 246
  n_bindery_object_id........................................... 247
  n_bindery_object_list......................................... 248
  n_bindery_object_name......................................... 250
  n_bindery_object_scan......................................... 251
  n_bindery_property_list....................................... 253
  n_bindery_property_scan....................................... 255
  n_bindery_value_list.......................................... 259
  n_bindery_value_name.......................................... 262
  n_bindery_value_scan.......................................... 264
  n_capture_active.............................................. 266
  n_capture_banner_get.......................................... 267
  n_capture_banner_set.......................................... 268
  n_capture_cancel.............................................. 269
  n_capture_end................................................. 270
  n_capture_file................................................ 272
  n_capture_flush............................................... 273
  n_capture_get................................................. 274
  n_capture_queue............................................... 279
  n_capture_set................................................. 281
  n_capture_start............................................... 282
  n_connection_number........................................... 283
  n_dir_get_effective_rights.................................... 284
  n_dir_get_maximum_rights...................................... 286
  n_dir_get_volume.............................................. 287
  n_dir_handle.................................................. 289
  n_drive....................................................... 290
  n_file_get_ext_attr........................................... 291
  n_file_set_ext_attr........................................... 292
  n_int......................................................... 293
  n_internet_address............................................ 294
  n_IPX......................................................... 296
  n_local_connection_number..................................... 297
  n_long........................................................ 298
  n_NETBIOS..................................................... 299
  n_server_attach............................................... 300
  n_server_detach............................................... 301
  n_server_login................................................ 302
  n_server_logout............................................... 303
  n_SHARE....................................................... 304
  n_SPX......................................................... 305
  n_TTS......................................................... 306
  n_user_name................................................... 307
  n_version..................................................... 308

                                                     Table of Contents    vi



Chapter 16.    Globals
Overview/Concepts............................................... 310
function List................................................... 311
  w_aut_return.................................................. 313
  w_border...................................................... 314
  w_box......................................................... 315
  w_color....................................................... 316
  w_color_data.................................................. 317
  w_color_editor_block.......................................... 318
  w_color_editor_text........................................... 319
  w_color_error................................................. 320
  w_color_help.................................................. 321
  w_color_menu.................................................. 322
  w_color_overall............................................... 323
  w_cur_col..................................................... 324
  w_cur_row..................................................... 325
  w_cursor...................................................... 326
  w_def_INT_09.................................................. 327
  w_DOS......................................................... 328
  w_DPMI........................................................ 329
  w_EMS......................................................... 330
  w_ERROR....................................................... 331
  w_ext_vga_modes............................................... 332
  w_floppy...................................................... 333
  w_funkeys..................................................... 334
  w_get......................................................... 335
  w_get.cur_get................................................. 336
  w_get.num_gets................................................ 337
  w_get.get[w_get.cur_get]->edit_var............................ 338
  w_hard_drive.................................................. 339
  w_help_dat_path............................................... 340
  w_help_ntx_path............................................... 341
  w_last_drive.................................................. 342
  w_lastkey..................................................... 343
  w_max_cols.................................................... 344
  w_max_rows.................................................... 345
  w_monitor..................................................... 346
  w_mouse....................................................... 347
  w_network..................................................... 348
  w_num_floppies................................................ 349
  w_num_parallel_ports.......................................... 350
  w_num_serial_ports............................................ 351
  w_parallelport................................................ 352
  w_pc.......................................................... 353
  w_printer..................................................... 354
  w_printer_dat_path............................................ 355
  w_printer_ntx_path............................................ 356
  w_screen_style................................................ 357
  w_serialport.................................................. 358
  w_setup_path.................................................. 359
  w_shadows..................................................... 360
  w_shd_attr.................................................... 361
  w_sound....................................................... 362
  w_start_c_col................................................. 363

                                                     Table of Contents    vii



  w_start_c_row................................................. 364
  w_start_mode.................................................. 365
  w_start_screen................................................ 366
  w_substring................................................... 367
  w_user........................................................ 368
  w_VCPI........................................................ 369
  w_video_mem................................................... 370
  w_XMS......................................................... 371

Appendix


A. Bibliography................................................. 372
B. Default valid functions...................................... 374
C. Utilities.................................................... 377
   index........................................................ 378
   prt_man...................................................... 379
   prt_stat..................................................... 380
   prt_test..................................................... 381
D. Error messages............................................... 382
E. Custom Error Handlers........................................ 394
   k_Int_09..................................................... 395
   w_fpe_handler................................................ 396
   matherr...................................................... 397
   w_crit_err_handler........................................... 398
F. Printer database format..(For registered users).............. 399

                                                     License\Disclaimer



       This software is being released as shareware.  It is not public domain.
It is not free.  You may use any  and all programs that are part of The C User
Interface Library for a trial period of 40 days, beginning the day you install
the software  on your computer.  At the end of this  40 day trial  period, you
must either register with  Mathware as a user of The C User Interface Library,
or you  must stop using the software and destroy all copies that  you may have
of the software.  This includes any copies that may have been  made for backup
purposes.  You may make backup copies  and distribute  the files that comprise
The C User Interface Library under the following provision. The files can only
be distributed as they appear on this disk, unmodified, and in their entirety,
and that  all files associated with The C User  Interface Library  be provided
on the distribution disk.A list of the files associated with The C User Inter-
face Library can be found under "Contents of disk".

      Only after you have registered as a user of The C User Interface Library
are you  granted a license to distribute and sell programs  created with The C
User Interface  Library royalty free.  That is, after  you have filled out the
registration form and sent in your registration fee, you may sell and distrib-
ute any  and all programs using  The C User Interface  Library without further
remuneration to Mathware.Your registered copy is subject to the same laws that
govern commercial software.  Thus, although you may freely copy and distribute
the shareware version of The C User Interface Library,subject to the aforement
ioned provisions, you may NOT  distribute  the version you receive upon regis-
tering with Mathware.Also, you may only make copies of the registered software
for personal backup copies. You may install the registered version on only one
machine.  The registered software  may not be installed on a network.  You are
granted a single  user license  when you register.  Network and  Site licenses
are also available.

      Although every reasonable effort  has gone into  the preparation of this
manual and software, we can not guarantee it to be completely free from error.
While we  have  extensively beta  tested the  software, we  make no  warranty,
expressed  or  implied,  with  regard  to the effectiveness of  the  software.
Mathware  shall not  be liable in  any event  for incidental  or consequential
damages that arise from the use of this software.  We will however replace any
defective or damaged  diskettes for registered users for  a period of  90 days
after registration.

                                                     Installation



      Provided on the source diskette,is the install utility which will install
The  C User  Interface  Library  onto a  hard  drive.  It  will  create all the
directories for you and unzip the files to their respective directories. If you
don't have a  hard drive, then you will be unable to  install or use The C User
Interface  Library.  The install  program will  let you  choose which  compiler
version you wish  to install.  You may install other  compiler versions of  the
library by either running the install program again, or by using pkunzip.exe to
install the zipped library files  found on the distribution diskette  onto your
hard drive.  If you have any  questions during the installation process, simply
press F1 to get online help.

                                                     Contents of Disk


      The C User Interface Library is composed of the following files:


      1. utility.zip - index.exe, prt_man.exe, prt_stat.exe, prt_test.exe,
                       help.dat, help.ntx, printer.dat, printer.ntx,
                       error.dat, error.ntx, setup.dat

      2. demo.zip    - demo.exe, demo.c , help.dat, help.ntx, setup.dat,
                       printer.dat, printer.ntx, borland.mak, borland.lnk,
                       msc.mak, msc.lnk, quick_c.mak, quick_c.lnk, mix.prj,
                       mix.lnk

      3. include.zip - user_int.h, w_cursor.h, w_date.h, w_file.h, w_get.h,
                       w_global.h, w_keybrd.h, w_menu.h, w_mouse.h,
                       w_netwrk.h, w_printr.h, w_screen.h, w_string.h,
                       w_time.h, w_window.h.

      4. borland.zip - userintl.lib, userints.lib

      5. msc.zip     - userintl.lib, userints.lib

      6. quick.zip   - userintl.lib, userints.lib

      7. mix.zip     - userintl.lib, userints.lib

      8. doc.zip     - manual, register.frm

      9. install.exe - install.exe, help.dat, help.ntx, setup.dat, pkunzip.exe

                                                     Compiling\Linking



      Before anything else, you must make sure that you have DOS 3.0 or later.
Many of the functions, especially  the file functions, use DOS  services found
only in DOS 3.0 and later.

      How do you go about incorporating the C User Interface Library functions
into your own programs? It's easy!  There are just two things that you need to
do.  First, in every C source file, make sure you have the following line:

     #include "user_int.h"

Now you can call  any C User Interface Library function you want.  When you go
to link your program together,make sure to include the userintx.lib along with
the standard list of libraries,where x is replaced with a letter corresponding
to the memory model being used for your program. For example, if you are using
the large memory model, then you need to link in userintl.lib. If you're using
the small  memory model, then  you need to link in  userints.lib.  That's  all
there is to it. For examples of make and link files for your compiler, see the
ones provided with the demo program.

      Also, every program you write you must begin with a call to w_init() and
end with a call to w_end().  w_init() initializes the C User Interface Library
and sets  some globals, while  w_end() restores  the original video  mode  and
screen.

     The libraries were compiled with the following compilers, assemblers, and
operating systems:

Borland: Turbo C++ 1.0, TASM 2.0
Mix....: Power C 2.20
MSC....: MSC 6.0, MASM 5.10
Quick C: Quick C 2.00, MASM 5.10
OS.....: DOS 6.00, MS-Windows 3.1, Netware 3.11

                                                     Registration


     You are currently using the shareware version of the library. In order to
continue using  the library after  the initial 40 day trial  period, you  must
register as a user with Mathware.To do this, simply print out the register.frm
file in the document  directory.  Then, fill it  out and send a check or money
order made payable to Mathware.

You may  also order the manual (This will  save you about 4 hours of printing
time, 200 pages of paper, wear on  your printer ribbon, and the manual will be
printed in letter quality using 7 colors.

After we have received payment, you will receive the following benefits:

      1.  Registered version of  the library.  This will have the file editing
          feature of f_edit enabled so that you may both browse and edit files.
      2.  The registered  libraries sent  to you will be the  latest available
          version.
      3.  All 5 memory model versions of the library.  This includes:
          small, medium, compact, large, and huge models.
      4.  Single User license.  Network and Site licenses  are also available.
      5.  Update notices as to the release of new versions and a reduced rate
          on updates.
      6.  Technical support via telephone.  BBS support will be implemented in
          the future.
      7.  Printer  Database format  which will  allow you  to add  unsupported
          printers to the printer database.

      Upcoming Features for next release

      1.  Movable and resizeable windows, menus
      2.  Functions will work in graphics modes as well as text modes
      3.  Horizontal scrolling in gets
      4.  Vertical scrolling of gets within a window
      5.  Much improved file editor
      6.  File and record locking
      7.  Peer to Peer Communications
      8.  Improved date and time handling functions
      9.  Better modularity of library so .exe sizes are smaller
     10.  Digitized speech support

                                                     Technical Support


     You may receive free technical  support once you have registered with us.
Currently, we have only telephone support.  In the  not so distant  future, we
would  like to establish a  Bulletin board for modeming.  Until  then, you can
receive technical support by calling:

     Mathware: technical support -  (718) 636-8018

We may be reached  Monday through Friday, and possibly on Saturday  or Sunday.
When you call,please have your registration number and version number at hand.
Currently, we are available only during evening hours, from approximately 6:00
pm to 12:00am.

                                                     1 - Colors



                                  Chapter 1

                                   Colors

                                                     1 - Colors



    Overview

    Colors are a useful tool in programming.  Careful use of colors can make
a program stand out  from the others.  With video technology increasing at the
current rate,end users have profited from strong competition which has yielded
higher resolution  monitors with  more color  capability, all at lower prices.
However,because of the necessity for backward compatibility,these new capabil-
ilities are often unused. This is especially true of TUIs. The new 1280 x 1024
resolution with  256 colors Super VGA monitor is quickly becoming the industry
standard.  The TUIs are still limited to the original 16 foreground colors and
8 background colors of the original IBM PC.

    Concepts

    IBM uses a simple scheme to provide color in the text modes.  A  character
is shown in color on the screen by using a 2 byte pair.  The 1st byte contains
the character's color (attribute), and the other the  ascii value of the char-
acter.  Depending on the  monitor,  the  attribute byte is  interpreted in two
distinct ways.  This depends  solely on whether  the monitor is monochrome  or
color.  The attribute bytes for both monitor types is shown below.

Ŀ
 7  6  5  4  3  2  1  0  Attribute byte


Monitor Type     Bits
     

1. Color:        0-2  Foreground color     (values: 0-7)
                 3    Foreground intensity (values: 0 or 1)
                 4-6  Background color     (values: 0-7)
                 7    Blinking bit         (values: 0 or 1)

2. Monochrome:   3    Intensity
                 7    Blink

                   background   foreground
                     (4,5,6)      (0,1,2)
      Normal           000          111
      Reverse video    111          000
      Invisible        000          000
      Underline        000          001


    The C User  Interface Library  extends the  IBM attribute  concept a  step
further.  The extension is the ATTRIBUTE type, defined in windows.h, and shown
below:

    typedef struct
    {
        unsigned standard,
                 enhanced;
    } ATTRIBUTE;

                                                     1 - Colors



    There are seven global  variables declared  to be of type ATTRIBUTE.  They
are:

    w_color_overall
    w_color_menu
    w_color_help
    w_color_data
    w_color_error
    w_color_editor_text
    w_color_editor_block

    Each of these variables  has  the standard  and enhanced fields.  Now, how
and why are they used?  These color globals allow you to store the users color
preferences.  If the user wants the screen to  be blue on a  white background,
then set w_color_overall to blue on white.  If the user wants the help screens
to be black text  on a cyan screen, then  set w_color_help to  black  on cyan.
Using  these globals will lend consistency to your applications.  For example,
every menu  function takes an ATTRIBUTE  parameter to determine what color the
menu will be. By always specifying w_color_menu as the attribute, whenever the
user changes his preference for the color of menus,ie,changes the w_color_menu
global, this change will be reflected in every menu function.  This gives you,
the programmer,the ability to let the end user choose his own color and screen
preferences, which  might be entirely different from  yours.  However, if  you
think menus were always meant to  be white  on blue, then  you can  ignore the
w_color_menu global and use a white on blue (31) attribute for all menu calls.
The standard and enhanced fields have slightly different meanings depending on
the color global.

   The w_color_overall global is  used for the overall screen color.  Only the
standard field is used.  The enhanced  field is ignored.  w_color_menu is used
for menus.  The standard field  is  the color of  the menu  window and the
unselected menu items.  The enhanced field is used for the menu hi  light bar.
w_color_help uses  the standard field for the color of the help screen window.
The help screen text is  displayed  in the  enhanced color.  w_color_error  is
exactly the same. The error box window is in standard color and the text is in
the enhanced  color.  w_color_data  is used for  data input. The  prompts  are
displayed  in the enhanced  color, while the window  and input text are in the
standard color. Finally,w_color_editor_text is used for file browsing\editing.
The standard color specifies the window color and the enhanced color the text.
w_color_editor_block  is used only for editing files, and is ignored by f_edit
when in  browsing  mode.  When  in edit mode, the  standard color  is used  to
delimit text blocked for moving, copying, or deletion. The last line of a file
is marked by an EOF line which is displayed in the enhanced color.

    Besides  the seven ATTRIBUTE  color globals  mentioned  above, the  C User
Interface Library maintains  another global variable, w_color, which holds the
currently active color.  All  screen  output,  via  w_prtf() and  v_prtf(), is
displayed using the attribute specified by w_color.  This global, described in
chapter 14,is not accessed directly. Two functions, v_getcolor and v_setcolor,
give the programmer indirect access.  These two functions are described in the
following pages, so you are referred there for further information.

                                                     1 - Colors



                         Function List


       Routine           Description
               
       v_getcolor        Set the currently active color.
       v_setcolor        Get the currently active color.
       w_setup           Let the user set various screen colors and attributes.


                                                     1 - Colors



Function....: v_getcolor.
Purpose.....: Get the currently active color.
Syntax......: int  v_getcolor(void);
Example call: cur_color=v_getcolor();
Returns.....: Attribute of currently active color.
Common Use..: Save the currently active color so that it may be restored later.
See Also....: v_setcolor,
              w_setup.
Example.....: Save the current color, change it to a white foreground on  a red
              background, print some text  in the new  color, and then restore
              the old color.

              #include "user_int.h"
              void main(void)
              {
              int old_color;

              w_init();
              old_color=v_getcolor();       /* Save current color         */
              v_setcolor(B_RED+F_WHITE);    /* Set new color to white/red */
              v_prtf("This is the new color.\n");
              v_setcolor(old_color);        /* Restore the old color      */
              v_prtf("This is the old color.\n");
              w_exit(0);
              }

                                                     1 - Colors



Function....: v_setcolor.
Purpose.....: Set the currently active color. All subsequent screen output will
              use the new color. A list of foreground and background colors are
              listed in w_window.h.Both v_prtf and w_prtf will use the current-
              ly selected color set by v_setcolor to display text.
Syntax......: void v_setcolor(int color);
Example call: v_setcolor(B_RED+F_BLUE);
Returns.....: None.
Common Use..: Change the active color.
See Also....: v_getcolor,
              w_setup.
Example.....: You may use the defined colors in w_window.h to select new colors
              for printing to windows or to anywhere on the screen. You may mix
              the 8 defined background and 16  foreground colors to achieve any
              of the possible 128 colors.  You select a new color by choosing a
              foreground and a background color.Black is the default if a color
              fore\\background is not specified(see example). Background colors
              are those that start  with as "B_" and the  foreground colors are
              those prefixed with "F_".

              #include "user_int.h"
              void main(void)
              {
              int old_color;

              w_init();
              old_color=v_getcolor();       /* Save current color         */
              v_setcolor(B_GREEN+F_BLUE);   /* New color is blue on green */
              v_prtf("Hello world.\n");     /* Now, make a word blink     */
              v_setcolor(BLINK+B_GREEN+F_BLUE);
              v_prtf("Hello world.\n");     /*                            */
              v_setcolor(B_GREEN);          /* Foreground not specified so*/
              v_prtf("Hello world.\n");     /* black is default.  So, we  */
                                            /* get black on green.        */
              v_setcolor(old_color);        /* Restore the old color      */
              v_prtf("This is the old color.\n");
              w_exit(0);
              }
                                                     1 - Colors



Function....: w_setup.
Purpose.....: Change various screen colors and attributes. w_setup is a built-
              in utility  that allows the user to select his own color prefer-
              ences along with a few other screen effects.  w_setup saves  the
              user's choices in the file setup.dat. The setup.dat file is read
              in by w_init, at the beginning of the application.So even though
              the user finishes with an application, the next time he runs the
              program, his preferences are  read in from setup.dat, preserving
              his color and screen preferences. The user may change any of the
              following screen attributes from within w_setup.

              attribute                      CUI global
                
              Screen color                   w_color_overall
              Menu color                     w_color_menu
              Help color                     w_color_help
              Data Entry color               w_color_data
              Error message color            w_color_error
              File edit\\browse color        w_color_editor_text
              File edit\\browse block color  w_color_editor_block
              Shadows                        w_shadows
              Screen style                   w_screen_style
              Number of rows on the screen   w_screen_rows
              Sound on\\off                  w_sound
              Enter used to end data input   w_aut_return
              Printer type                   w_printer.model[]
              Printer parallel port          w_printer.cur_port

              Note: VGA owners
              If you look at the setup.dat file,you will notice that there are
              7 columns of numbers, followed by a horizontal line of 6 numbers
              and then a line with 3 numbers.  Initially, when you receive The
              C User Interface Library, this row of 3 numbers is all 0's. This
              row holds the extended VGA modes,which is the mode for 25 x 132,
              28 x 132, and 44 x 132 respectively.  These are non-standard VGA
              modes.  If you have a VGA monitor that supports these modes, you
              can replace the 0's with the  hexadecimal codes for  these video
              modes.  For example, if you have an Orchid Pro Designer II, then
              25 x 132 is video mode 23h, 28 x 132 is video  mode 24h, and  44
              x 132  is 22h.  Thus,  you would  replace  the line of 0's  with
              "23 24 22" (Don't include the quotes).  If your monitor supports
              some but not  all of the modes use  00 for any mode  that is not
              supported.  For example, suppose  your monitor supports the 25 x
              132 and 44 x 132 video modes, but not the 28 x 132.  Then, again
              using the Orchid Pro II example, we  would  change this  line to
              "23 00 22" (Again, omit the  quotes).  If you  do choose to  use
              these modes, note that your mouse  will not work correctly since
              the mouse expects an 80 column screen.


                                                     1 - Colors



Syntax......: void w_setup(void);
Example call: w_setup();
Returns.....: None.  Sets various globals.
Common Use..: Let the user  change various  screen  attributes to suit his own
              preferences, and save results to setup.dat file.
See Also....: v_getcolor,
              v_setcolor.
Example.....: See demo program.  The best way  to see how  w_setup works is to
              run the demo program.  The many screen attributes  can be better
              and more quickly explained by running the  demo than can be done
              here with words.  The screen effects are just that, and you will
              have a much better understanding seeing their effects than read-
              ing about them. You can select your printer type, colors, sound,
              shadows, background screen style, and video mode.

              Note: When selecting modes, remember that the  mouse always  uses
                    an 80  column screen.  Thus, the  mouse will  not  function
                    correctly in the 40 column mode or in any of the 132 column
                    modes.

                                                     2 - Screen



                                  Chapter 2

                                   Screen

                                                     2 - Screen



    Overview

    One of the major purposes of the C User Interface Library is to  manipulate
what is displayed on the screen.  There are a  host of functions that allow you
to save and restore areas of the screen,to draw anything anywhere on the screen
and many others.

    Concepts

    The screen for text  modes is based on an n x n coordinate  system with 0,0
being located in the upper left hand corner, as shown below.  Only non-negative
values for row and columns are allowed. The maximum values for rows and columns
are determined by the video mode, number of  scan lines, and font size.  All of
the  details  of implentation  can be  ignored by  you, since  v_setmode()  and
v_setrows() are provided  to handle this for you.  The C User Interface Library
maintains 2 globals  for you, w_max_rows and w_max_cols.  These  globals always
hold the total number of rows and columns on the screen at any given time.  The
C User Interface Library provides full access to the screen, with the functions
listed onthe following pages.


   (0,0)
      cols
     
     
     
     
     
    rows

                                                     2 - Screen



                         Function List


       Routine           Description
               
       v_clear           Clear a region of the screen.
       v_getcols         Get the number of columns on the screen.
       v_getmode         Get the current mode.
       v_getmonitor      Get the monitor type.
       v_getrows         Get the number of rows on the screen.
       v_prtf            Display formatted text on the screen.
       v_restscrn        Restore an area of the screen.
       v_savescrn        Save an area of the screen.
       v_setmode         Set the video mode.
       v_setrows         Set the number of rows on the screen.

                                                     2 - Screen



Function....: v_clear.
Purpose.....: Clear a rectangular region of the screen.
Syntax......: void v_clear(int row,int col,int hgt,int len,int color);
              int row;       Upper left hand row of area
              int col;       Upper left hand col of area
              int hgt;       Number of rows to clear
              int len;       Number of cols to clear
              int color;     Color to clear area with
Example call: v_clear(2,5,10,20,F_GREEN);
Returns.....: None.
Common Use..: Clear a region of the screen.
See Also....: w_clear,
              w_clrscrn.
Example.....: Display some text, and then clear the screen area containing the
              text.


              #include "user_int.h"
              void main(void)
              {
              w_init();

              v_setcur(5,10);
              v_prtf("Hello there");
              v_setcur(6,10);
              v_prtf("We'll clear this area");
              v_setcur(7,10);
              v_prtf("In a minute.");
              k_wait(0);
              v_clear(5,10,3,20,F_BLUE);
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_getcols.
Purpose.....: Get the current number of columns on the screen.
Syntax......: v_getcols(void);
Example call: cols=v_getcols();
Returns.....: Number of columns currently used to display the screen.  This is
              one more than last displayable column.  For example, if the
              number of columns is 80, then 79 is the  last displayable column
              since the displayable columns are 0 - 79.
Common Use..: Find the maximum number of columns the screen is capable of dis-
              playing.
See Also....: v_getrows.
Example.....: Print some text in the last visible column on the screen.


              #include "user_int.h"
              void main(void)
              {
              int cols=v_getcols();

              w_init();
              v_setcur(10,cols-1);
              v_prtf("M");
              v_setcur(11,cols-1);
              v_prtf("a");
              v_setcur(12,cols-1);
              v_prtf("t");
              v_setcur(13,cols-1);
              v_prtf("h");
              v_setcur(14,cols-1);
              v_prtf("w");
              v_setcur(15,cols-1);
              v_prtf("a");
              v_setcur(16,cols-1);
              v_prtf("r");
              v_setcur(17,cols-1);
              v_prtf("e");
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_getmode.
Purpose.....: Get the current video mode.
Syntax......: v_getmode(void);
Example call: mode=v_getmode();
Returns.....: Current video mode.
Common Use..: Determine whether you are in graphics or text mode.
See Also....: v_setmode,
              v_setrows.
Example.....: Find out which mode you are in and display some text if you are
              in text mode.


              #include "user_int.h"
              void main(void)
              {
              int mode;

              w_init();
              mode=v_getmode();
              if (mode==0x03 || mode==0x07)
                 v_prtf("We're in text mode.");
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_getmonitor.
Purpose.....: Detect which type of  monitor and video adapter card is present
              and the highest graphics resolution supported. This information
              is stored  in the global variable  w_monitor, which is  of type
              SCREEN.  The structure  for SCREEN is defined in user_int.h and
              is shown below.

              typedef struct
              {
                  char adapter[20];
                  int  color;
                  int  ver_res;
                  int  hor_res;
                  int  max_colors;
              } SCREEN;

              The adapter will have an ascii string describing the video adap-
              ter.  The color field will be true for color  monitors and false
              for monochrome. The ver_res,hor_res, and max_colors will contain
              the highest graphics and color resolution supported by the adap-
              ter card and monitor.  This global is displayed along with other
              various hardware information by w_display_config().
Syntax......: void v_getmonitor(void);
Example call: v_getmonitor();
Returns.....: Video information detected in the global w_monitor as described
              above.
Common Use..: Detect the end user's monitor and video adapter card.
See Also....: v_setrows().
Example.....: Detect which type of monitor you have and display the information
              in a window.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              v_getmonitor();
              v_prtf("Graphics card...: %s\n",w_monitor.adapter);
              v_prtf("%s monitor:\n",w_monitor.color ? "Color" : "Mono");
              v_prtf("Hor Resolution..: %d\n",w_monitor.hor_res);
              v_prtf("Ver Resolution..: %d\n",w_monitor.ver_res);
              v_prtf("Colors..........: %d",w_monitor.max_colors);
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_getrows.
Purpose.....: Get the current number of rows on the screen.
Syntax......: v_getrows(void);
Example call: rows=v_getrows();
Returns.....: Number of rows currently used to display the screen. This is one
              more than last displayable row.  For example, if the number
              of rows is 50,then 49 is the last displayable row since the dis-
              playable rows are 0 - 49.
Common Use..: Find the maximum  number of rows the  screen is  capable of dis-
              playing.
See Also....: v_getcols,
              v_setrows.
Example.....: Print some text on the last visible row on the screen.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              v_setcur(v_getrows()-1);
              v_prtf("Mathware");
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_prtf.
Purpose.....: Display formatted  text anywhere on the  screen.  The  text will
              start at the screen location  specified by  the global variables
              w_cur_row and w_cur_col.  These are two internal  variables used
              to keep track of where the cursor is on the screen.  After call-
              ing w_init(),  v_setmode(),  v_setrows(),  or  w_clrscrn(),  the
              cursor is positioned in the upper left hand corner of the screen
              at 0,0.  Thereafter, every call to v_prtf() will update the cur-
              sor position.  The  cursor position  can be set to  any location
              on the screen by calling v_setcur(), or any of the screen cursor
              functions (These  are the functions listed in the cursor chapter
              that begin with v_). The text will be displayed in the currently
              selected color, which is set by calling v_setcolor(). Other than
              these two  aspects, v_prtf() behaves exactly  like the  standard
              library's printf() function.
Syntax......: void v_prtf(char *format,...);
Example call: v_prtf("%s %d %f\n","Hello",23,14.765);
Returns.....: None.
Common Use..: Display messages anywhere on the screen,
See Also....: p_prtf,
              w_prtf.
Example.....: Display text at various locations on the screen.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              v_setcolor(F_BLUE + B_GREY);
              v_setcur(0,5);
              v_prtf("The C User Interface Library.\n");
              v_prtf("by \n\n");
              v_prtf("\t\tMathware");
              v_setcur(10,50);
              v_prtf("That's all folks. %f",35.90);
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_restscrn.
Purpose.....: To restore an area of the screen previously saved by v_savescrn.
              If the buffer passed to v_restscrn() is NULL,an error message is
              displayed, otherwise, the area save by v_savescrn() is restored.
Syntax......: int  v_restscrn(int row,int col,int hgt,int len,char *buffer);
              int row;         Upper left hand row of area
              int col;         Upper left hand col of area
              int hgt;         Number of rows in area to restore
              int len;         Number of cols in area to restore
              char *buffer;    Ptr to buffer returned by v_savescrn()
Example call: v_restscrn(5,5,5,30,buffer);
Returns.....: TRUE\FALSE flag indicating whether the area was restored.
Common Use..: Restore a region of the screen that has been written over.
See Also....: v_savescrn().
Example.....: Write  some text in an  area on the screen; Save the area; Over-
              write the area with some new text, and then restore the original
              area.


              #include "user_int.h"
              void main(void)
              {
              char *buffer;

              w_init();
              v_setcolor(F_GREEN+B_GREY);
              v_setcur(10,10);
              v_prtf("This is the");
              v_setcur(11,10);
              v_prtf("Original area");
              buffer=v_savescrn(10,10,2,20);
              if (!buffer)
              {
                 w_errbox(0,"Insufficient memory to save area.");
                 w_exit(1);
              }
              k_wait(0);
              v_clear(10,10,2,20,F_BLACK);
              v_setcur(10,10);
              v_prtf("This is some");
              v_setcur(11,10);
              v_prtf("new text");
              k_wait(0);
              v_restscrn(10,10,2,20,buffer);
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_savescrn.
Purpose.....: Save a rectangular  portion of the screen.  The area  may by re-
              stored with v_restscrn().  v_savescrn() creates a buffer to hold
              the area to be saved.  If there is sufficient memory, the screen
              area is saved and  stored in the buffer.  The buffer  address is
              returned to the user. If there is insufficient memory, then NULL
              is returned and the area is not saved.
Syntax......: char *v_savescrn(int row,int col,int hgt,int len);
              int row;      Upper left hand row of area to save
              int col;      Upper left hand col of area to save
              int hgt;      Number of rows in area to save
              int len;      Number of cols in area to save
Example call: buffer=v_savescrn(5,5,10,50);
Returns.....: If there is  sufficient memory, a pointer  to the buffer holding
              the saved area is returned.  Otherwise, NULL is returned.
Common Use..: Save an area of the screen so that it may be restored later.
See Also....: v_restscrn.
Example.....: See the v_restscrn() example.

                                                     2 - Screen



Function....: v_setmode.
Purpose.....: Switch video modes.  See your video adapter cards valid modes
              since not all modes are available on all monitors.
Syntax......: void v_setmode(int mode);
              int mode;        Mode to switch to
Example call: v_setmode(0x25);
Returns.....: None.
Common Use..: Switch between graphics and text modes.
See Also....: v_getmode.
Example.....: Set the mode to text mode 0x03 if you have a color adapter ot to
              0x07 if you have a monochrome adapter.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              v_prtf("Current mode: %2.2X",v_getmode());
              if (w_monitor.color)
                 v_setmode(0x03);
              else
                v_setmode(0x07);
              v_prtf("New mode: %2.2X",v_getmode());
              k_wait(0);
              w_exit(0);
              }

                                                     2 - Screen



Function....: v_setrows.
Purpose.....: When you  see 25, 28, 30, 33, 43, and 50 lines  on your screen,
              these are not different  modes (They are all in mode 0x03), but
              rather they have a different number of scan lines and different
              fonts. The fonts for 25, 28, 43, and 50 lines are stored in ROM
              and the 30 and 33 line mode fonts are  defined by Mathware  and
              stored in RAM. All monitors do not support all numbers of rows.
              Below is a chart that  lists which rows are  supported by which
              monitors.  After setting the rows, the cursor is  positioned in
              the upper left hand corner of the screen at 0,0.

                                         Monitors
                                        
              Rows      VGA  EGA  CGA  MDA  PGA  MCGA  Hercules  8514/A
                 
              25 x 80    x    x    x    x    x    x       x        x
              28 x 80    x
              30 x 80         x
              33 x 80    x
              43 x 80    x    x
              50 x 80    x                        x

              NOTE: 30\33 line modes are not available under Mix Power C.
Syntax......: int v_setrows(int rows);
              int rows;       Number of rows to display
Example call: v_setrows(28);
Returns.....: TRUE\FALSE flag indicating whether the screen was set to display
              the new number of rows.
Common Use..: Switch between 25, 28, 30, 33, 43, and 50 line text modes.
See Also....: v_getrows.
Example.....: Switch between 28 and 43 line modes and display some text in each

              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (strcmp(w_monitor.adapter,"VGA")!=0
              ||  strcmp(w_monitor.adapter,"SVGA")!=0) {
                 w_errbox(0,"Monitor is not a VGA or SVGA.");
                 w_exit(1);
              }
              v_setrows(28);
              v_prtf("Hello");
              k_wait(0);
              v_setrows(43);
              v_prtf("Hello");
              k_wait(0);
              w_exit(0);
              }

                                                     3 - Windows



                                  Chapter 3

                                   Windows

                                                     3 - Windows



    Overview

    Although the text based user interfaces(TUIs)are giving way to the fancier
graphical user interfaces(GUIs), the window is still an important concept used
in both.  Windows are used to display everything, from error messages to  help
screens, to menus.  The window lies at the very heart of every  user interface
library.  The C User Interface Library is no exception.

    Concepts

    A window is a rectangular region of the screen.  When a window is opened,
the underlying screen is saved so that it may be restored when the window is
no longer needed.  The structure used to open windows is shown below.  All of
the fields  are for internal  use and need not  concern  you, the programmer.
When a window is opened, memory is allocated for the screen underneath.  This
memory is  released  when  the window is  closed.  This makes it possible for
windows to  overlap, ie, lie on  top of each other.  However, when displaying
text in a window, you should always be careful to make  sure you are writing
to the top window.  There are four options  which will allow to spice up your
windows.

typedef struct WIN_DATA
{
   int       row,                      /* Row                  */
             col,                      /* Column               */
             len,                      /* Length               */
             hgt,                      /* Height               */
             bdr,                      /* Border Type          */
             shd,                      /* Shadow present       */
             c_row,                    /* Window cursor row    */
             c_col;                    /* Window cursor column */
   void far *opn;                      /* Window open flag     */
   char     *title;                    /* Window title         */
   ATTRIBUTE color;                    /* Window color         */
   char *screen;                       /* Screen save buffer   */
} WINDOW;
typedef struct WIN_DATA *WIN_PTR;

    These options are:

    1. Border Type - None, Single  line, Double  line, Single  drop  down, and
                     Double drop down (see w_setborder). The window border, if
                     present will be the same color as the window itself.
    2. Shadows     - This option allows you  to  open  windows  with  a shadow
                     along the  right  hand side  and along  the bottom.  This
                     gives the appearance of being viewed from a light  source
                     in the upper left hand corner of your screen.
    3. Color       - The window color can be  any of 128 foreground/background
                     color combinations.  These color combinations can be seen
                     when using the w_setup routine to select colors.
    4. Title       - An optional  title in the  window border color can appear
                     on the top window border.

                                                     3 - Windows



                         Function List


       Routine           Description
                  
       w_clear           Clear the inside of a window.
       w_close           Close a window.
       w_clrscrn         Clear the entire screen.
       w_display_config  Display the computers hardware environment.
       w_errbox          Display a single line error message.
       w_exit            Exit program.
       w_getborder       Get current border style.
       w_hscroll         Scroll a window horizontally.
       w_init            Initialize C User Interface Library.
       w_isopen          Check if a window is currently open or closed.
       w_open            Open a window.
       w_prtf            Print formatted text in a window.
       w_setborder       Set a new border style.
       w_vscroll         Scroll a window vertically.
       w_ynbox           Prompt user for a Yes/No Response.


                                                     3 - Windows



Function....: w_clear.
Purpose.....: Clear the inside of a window and reset the windows cursor to
              the upper left hand corner, at 0,0.
Syntax......: int  w_clear(WIN_PTR window);
              WIN_PTR window;       Window to clear
Example call: w_clear(window);
Returns.....: TRUE\FALSE flag indicating whether window was cleared or not.
Common Use..: Clear a window.
See Also....: w_clrscrn,
              w_close.
Example.....: Open a window, display some text in it, clear it, and display some
              more text.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,0);
              if (!window) w_exit(1);
              w_prtf(window,"Here is some text.\n");
              w_prtf(window," And some more text\n");
              w_ptrf("Now, we will clear the window.");
              k_wait(0);
              w_clear(window);
              w_prtf(window,"Here is some new text\n");
              k_wait(0);
              w_close(window);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_close.
Purpose.....: Close a window and restore the screen underneath.
Syntax......: int  w_close(WIN_PTR);
              WIN_PTR window;         window to close
Example call: w_close(window);
Returns.....: TRUE\FALSE flag indicating whether window was closed.
Common Use..: Close a window.
See Also....: w_open.
Example.....: Open a window, print some text, and then close the window.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              w_prtf(window,"Here is some text.");
              k_wait(0);
              w_close(window);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_clrscrn.
Purpose.....: Clear the entire screen using the style specified by the  global
              w_screen_style.The three screen styles are listed in w_screen.h.
              They  are  CLEAR, TILED, and CHECK.  The screen will be  cleared
              using the standard color of w_color_overall.  After clearing the
              screen, the cursor  is positioned  in the upper left hand corner
              of the screen, at coordinates 0,0.
Syntax......: void w_clrscrn(void);
Example call: w_clrscrn();
Returns.....: None.
Common Use..: Clear the entire screen.
See Also....: w_clear.
Example.....: Print some text on the screen and then clear it.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              v_prtf("This is some text.\n\n\n");
              v_prtf("Hello World.\n\n\n");
              v_prtf("Now we'll clear the entire screen.");
              k_wait(0);
              w_clrscrn();
              k_wait(0);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_display_config.
Purpose.....: Display the user's hardware environment in a window which is from
              13 to 16 rows  high, depending  on the  number of  floppy  drives
              present, and 62 columns wide (not including shadow).   w_display_
              config() displays the contents of global hardware variables.These
              globals are defined in w_global.c,and the structures used by some
              of them can be found in windows.h. These globals are discussed in
              chapter 14 if you  need to  do more than just  display them.  The
              border is a  single line and  shadows are drawn on  the window if
              the global variable w_shadows is TRUE.
Syntax......: w_display_config(int row, int col);
              int row;     Row to display window
              int col;     Column to display window.
Example call: void w_display_config(5,3);
Returns.....: None.
Common Use..: Show the user his hardware environment.
See Also....: None.
Example.....: Display the users hardware environment.See also the demo program.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              w_display_config(5,3);        /* Display hardware globals */
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_errbox.
Purpose.....: Display a 1 line error message at the bottom of the screen.  The
              message is displayed in a bordered window with no shadows,so the
              whole message actually takes up 3 lines. The window is displayed
              one line from the bottom of the page, and spans  the entire with
              of the screen, leaving a space on either side of the window.
              There are 2 forms of w_errbox().  The 1st, is to call w_errbox()
              like you would  printf(), except that the first parameter is the
              number 0, and then  all of the other regular  arguments  are the
              same.  for example, you might call do the following:

              printf("%s  %d  %5f", "Hello", 23, -13.23);

              The analagous w_errbox() call would be:

              w_errbox(0,"%s  %d  %5f", "Hello", 23, -13.23);

              The only difference is that there is that  extra 1st 0, which is
              the 1st parameter.

              Now, most programs, especially large ones, end up doing a lot of
              error  checking.  Thus,  you would have a lot of strings defined
              in you program for error messages for when the user makes a mis-
              take.  This is fine and very easy. However, all of these strings
              are in memory taking up space, even though any particular one is
              only needed when the user  makes that one particular mistake for
              which  the error message  was designed  for.  In large programs,
              there can be as much as 35k in error message strings. Thus, with
              DOS's 640k  limit, sometimes  memory is at a premium.  So, the C
              User  Interface  Library  alternately lets  you keep all of your
              error messages in an  ascii text  file, and reads  in the needed
              error message when it is  needed, and throws it  away when it is
              done being displayed. Thus,instead of your error message strings
              takimg up 35k,they don't take anything(well, 256 bytes actually)
              The C User Interface Library stores error message strings  in an
              ascii text file called error.dat, and like printer.dat and help.
              dat, has an associated index file, error.ntx.  The C User Inter-
              face Library reserves the 1st 500 lines for its own internal use.
              Starting at  line 501, the  rest of the file  is for you to use.
              Take a look at some of the 1st 500 lines for some examples. This
              form of w_errbox() is a little more complicated than the one de-
              scribed above, but it has  many  advantages.  So lets look at an
              example.  Suppose we have the following error message:

              "Printer is out of paper.Please add %d more pieces.";

              Using the 1st method, we could simply do the following:

              w_errbox(0,"Printer is out of paper.Please add %d more pieces.",
                          50);

              Or, using the 2nd method, we would add the message to the error.
              dat file, on the next available line, say 501,if this is our 1st
              error message.  So, the error.dat file would look like:

                                                     3 - Windows



              line    text
                  
              500     Reserver by Mathware
              501     Printer is out of paper.Please add %d more pieces.

              After adding this line,you would have to run index to update the
              associated .ntx  file (See index in  the utility  section in the
              appendix).  Now that the error message is in the error.dat file,
              we can display it using method 2 as follows:

              w_errbox(501, 50);

              Notice that there is no format string in the w_errbox() call. We
              have it stored in our file,and w_errbox() uses the error number,
              (the line the error message is stored at) to retrieve the string
              when you need it.  Thus, when  using method 2, you  only need to
              specify the error number and the arguments that the string takes,
              but not the string.Note that in both cases,any formal parameters
              that the  error message needs, in this  example we had only one,
              the number 50, are  passed  regardless of the method being used.
              The only real difference is that in the 1st method, we specified
              the error number to be 0, which lets w_errbox() know not to look
              in the  error.dat file for the error message  string, but rather
              to look at the next  argument.  Below are some more examples and
              you can look at  the demo program's source  code as well  as the
              error.dat file for even more examples.
Syntax......: unsigned int w_errbox(unsigned int error,...);
              unsigned int error;      Error number
Example call: w_errbox(0, "This is an error message");
Returns.....: Key pressed by the user.
Common Use..: Display an error message to the user.
See Also....: None.
Example.....: Display some error messages using both methods.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              w_errbox(0,"This is error message number %d",1);
              w_errbox(0,"This is error message number 2");
              w_errbox(0,"String - %s,  Char - %c   float - %f",
                       "w_errbox",'A',23.1876);
              w_errbox(522);
              w_errbox(523, 'A', 23.1876);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_exit.
Purpose.....: Exit an application.  Restores the original startup screen. This
              should only be called  after w_init() has  been called.  The DOS
              error level is set to the value of the exit_code parameter.
Syntax......: void w_exit(int exit_code);
              int exit_code;     DOS error code
Example call: w_exit(0);
Returns.....: None.
Common Use..: Exit an application.
See Also....: w_init.
Example.....: Return a DOS error level code of five when done.  This DOS error
              level can be tested for in batch programs.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              w_exit(5);
              }

                                                     3 - Windows



Function....: w_getborder.
Purpose.....: Get the current border style.
Syntax......: int  w_getborder(void);
Example call: old_border=w_getborder();
Returns.....: Current border style.
Common Use..: Save the current border style so that it can be restored later.
See Also....: w_setborder.
Example.....: Save the current border style, change the border style to double
              lines, and then restore the original border style.

              #include "user_int.h"
              void main(void)
              {
              int old_border;
              WIN_PTR window;
                                        /* Open window in original border    */
                                        /* style                             */
              w_init();
              old_border=w_getborder(); /* Save current border style         */
              w_setborder(DOUBLE_LINE); /* Set new border style              */
                                        /* Display window with double border */
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              w_prtf(window,"This is a window with a double border.");
              k_wait(0);
              w_close(window);
              w_setborder(old_border); /* Restore old border style           */
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              w_prtf(window,"This is a window with the old border style.");
              k_wait(0);
              w_close(window);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_hscroll.
Purpose.....: Scroll the contents of a window horizontally. The directions are
              either LEFT or RIGHT and are defined in w_window.h.
Syntax......: void w_hscroll(WIN_PTR window,int dir,int num_cols);
              WIN_PTR window;     Window to scroll
              int     dir;        Direction in which to scroll window
              int     num_cols;   Number of columns to scroll window
Example call: w_hscroll(window,LEFT,1);
Returns.....: None.
Common Use..: Scroll a window left or right.  Used in text editors.
See Also....: w_vscroll.
Example.....: Open a  window and  print  some text  in it.  Then  let the user
              scroll the text horizontally using the arrow keys.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              unsigned int key;

              w_init();
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              w_prtf(window,"This is a scroll window\n");
              w_prtf(window,"Use the left and right arrow keys\n");
              w_prtf(window,"To scroll the text.");

              do
              {
                 key=k_getkey();
                 switch(key)
                 {
                    case LT_ARROW:
                         w_hscroll(window,LEFT,1);
                    break;
                    case RT_ARROW:
                         w_hscroll(window,RIGHT,1);
                    break;
                    default:
                        w_errbox(0,"Invalid key.");
                    break;
                 }
              }  while (key!=ESC);
              w_close(window);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_init.
Purpose.....: Initialize global  variables, read in the  setup.dat,  help.dat,
              help.ntx, printer.dat, and printer.ntx files,and save the start-
              up screen.  This should be the 1st line in all of your programs.
              If w_init() can't  find either  of the  help files, help.dat  or
              help.ntx, then context sensitive  help will not  be available to
              the application.  If w_init() can not find either of the printer
              files, printer.dat or  printer.ntx, or setup.dat, then  printing
              functions will not be available to the application.  If w_init()
              can not find setup.dat, then  default settings will be used  for
              the color  and screen variables,  and any changes  made to these
              global variables(See w_setup() for a list of the affected global
              variables) will be lost when the application exits.
Syntax......: void w_init(void);
Example call: w_init();
Returns.....: None.
Common Use..: Initialize the C User Interface Library.
See Also....: w_exit.
Example.....: See w_exit example.

                                                     3 - Windows



Function....: w_isopen.
Purpose.....: Test to see if a window is open or closed.  Whenever a window is
              opened, it's "opn" flag is set.  The value is unimportant, since
              you can use w_isopen() to see if a window is indeed open or not.
Syntax......: int w_isopen(WIN_PTR window);
              WIN_PTR window;         Window to check
Example call: if (w_isopen(window))   w_close(window);
Returns.....: TRUE\FALSE flag indicating whether the window is open or not.
Common Use..: Check to see if a window is open before writing to it or trying
              to close it.
See Also....: w_close,
              w_open.
Example.....: Open a window and close it, checking it's status each time.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              if (w_isopen(window)) v_prtf("Window is open.");
              else                  v_prtf("Window is not open.");
              w_close(window);
              if (w_isopen(window)) v_prtf("Window is still open.");
              else                  v_prtf("Window is closed.");
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_open.
Purpose.....: Open a window.  Upon being opened,the window cursor is placed in
              the upper  left hand corner of  the window  at  coordinates 0,0.
Syntax......: WIN_PTR w_open(int r,int c,int h,int l,int border,int shadow,
                             ATTRIBUTE color,char *title);
              int r;         Screen row to open window
              int c;         Screen column to open window
              int h;         Window height, excluding border and shadow
              int l;         Window length, excluding border and shadow
              int border;    TRUE\FALSE  flag indicating  whether  the  window
                             should be drawn with a border. If TRUE,the window
                             will have a border in the style specified by  the
                             w_border global. (See w_get/setborder).
              int shadow;    TRUE\FALSE  flag indicating  whether  the  window
                             should be drawn with a shadow. If TRUE,the window
                             will have a shadow drawn  on the right and bottom
                             sides  of the  window.  The global  w_shadows  is
                             commonly used instead of a hard coded TRUE\FALSE.
              ATTRIBUTE color; Color of window. The window will be drawn using
                             the standard field only.  The border, if present,
                             will be the same color as the window.The enhanced
                             field is ignored.
              char *title;   Title to be centered on the top row of the window.
                             The  window  can not have a title unless it has a
                             border.  Specify NULL (0) for no title.
Example call: w_open(5,5,3,25,TRUE,w_shadows,w_color_data,"Title");
Returns.....: Pointer to window structure if the window was opened successfully.
              Otherwise, NULL (0) is returned.
Common Use..: Open a window.
See Also....: w_close.
Example.....: Open a window and display some text.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);

              w_prtf(window,"Hello world\n");
              k_wait(0);
              w_close(window);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_prtf.
Purpose.....: Print formatted text in a window.  The text  will be  printed in
              the currently active color, which is set by v_setcolor. Printing
              in the window will begin at the window cursor coordinates, spec-
              ified by  the windows  c_row and  c_col  fields.  This  function
              behaves exactly like the standard C library function, printf.
Syntax......: void w_prtf(WIN_PTR window,char *format,...);
              WIN_PTR window;     Window to print to
              char *format;       Format of output
Example call: w_prtf(window,"%s %d %f","Hello World",5,90.111);
Returns.....: None.
Common Use..: print formatted output in a window.
See Also....: w_errbox,
              p_prtf,
              v_prtf
Example.....: Open a window and then display various types of formatted output.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,5,30,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              w_prtf(window,"Char: %c Integer: %d Float: %f\n",'A',23,-4.19);
              w_prtf(window,"Control: \t \a \b");
              k_wait(0);
              w_close(window);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_setborder.
Purpose.....: Set the new border style for all subsequent windows.  The valid
              border types are  listed in  w_window.h.  The new  border style
              will be used when drawing bordered windows. It has no effect on
              borderless  windows.  All  subsequently drawn  bordered windows
              will be drawn using the set border style.  The border types are
              shown below.

              SINGLE_LINE     0
              DOUBLE_LINE     1
              SINGLE_DROP     2
              DOUBLE_DROP     3

Syntax......: void w_setborder(int border_type);
              int border_type;     New border style
Example call: w_setborder(SINGLE_LINE);
Returns.....: None.
Common Use..: Change the border style.
See Also....: w_getborder.
Example.....: See w_getborder example.

                                                     3 - Windows



Function....: w_vscroll.
Purpose.....: Scroll the contents of a window vertically. The  directions  are
              either UP or DOWN and are defined in w_window.h.
Syntax......: void w_vscroll(WIN_PTR window,int dir,int num_rows);
              WIN_PTR window;     Window to scroll
              int     dir;        Direction to scroll
              int     num_rows;   Number of rows to scroll
Example call: w_vscroll(window,DOWN,1);
Returns.....: None.
Common Use..: Scroll a window up or down.  Used in text editors.
See Also....: w_hscroll.
Example.....: Open a window and print some text in it.  Then let the user
              scroll the text vertically using the arrow keys.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              unsigned int key;

              w_init();
              window=w_open(5,5,5,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              w_prtf(window,"This is a scroll window\n");
              w_prtf(window,"Use the up and down arrow keys\n");
              w_prtf(window,"To scroll the text.");

              do
              {
                 key=k_getkey();
                 switch(key)
                 {
                    case UP_ARROW:
                         w_vscroll(window,UP,1);
                    break;
                    case DN_ARROW:
                         w_vscroll(window,DOWN,1);
                    break;
                    default:
                        w_errbox(0,"Invalid key.");
                    break;
                 }
              }  while (key!=ESC);
              w_close(window);
              w_exit(0);
              }

                                                     3 - Windows



Function....: w_ynbox.
Purpose.....: Get a user's "Yes\No"  response.  A single  line message box  is
              displayed at the bottom of the screen in the w_color_data color,
              with a prompt message.Appended to the prompt message is a 7 char
              string saying " Y or N". The user can then select one of the two
              choices, press the help key (F1) for help, or press Esc to quit.
              The "Yes\No" box is  immediately cleared after  the user makes a
              selection.
Syntax......: char w_ynbox(char *prompt,char *help_word);
              char *prompt;        Message to display to user
              char *help_word;     Key word to be used to get context sensitive
                                   help whenever the help key is pressed.
Example call: if ('Y'!=w_ynbox("Do you wish to continue",0)) break;
Returns.....: 'Y' if user pressed "Yes".  'N' if the user pressed "No". 'E' if
              the user pressed ESC.
Common Use..: Get a "Yes/No" answer.
See Also....: g_yn.
Example.....: Keep incrementing a variable until the user wants to quit.

              #include "user_int.h"
              void main(void)
              {
              int     count=0;
              WIN_PTR window;

              w_init();
              window=w_open(5,5,1,20,TRUE,w_shadows,w_color_data,"Title");
              if (!window) w_exit(1);
              do                               /* Break out of loop if */
              {                                /* user presses 'N' or  */
               ++count;                        /* Esc.                 */
                 w_prtf(window," count = %d",count);
                 w_setcur(0,0);
              }  while ('Y'==w_ynbox("Do you wish to continue",".cont_prog"));
              w_clear(window);
              w_prtf(window,"The final count was %d",count);
              k_wait(0);
              w_close(window);
              w_exit(0);
              }


                                                     4 - Menus



                                  Chapter 4

                                    Menus

                                                     4 - Menus



    Overview

    Menus provide an easy and effective way to input data. Menus eliminate the
need  for data  validation and provide unparalleled ease  for the user.  The C
User Interface Library  provides  a number of different menu types, which will
make your programs really come alive.

    Concepts

    Menus are  simply  a list  of items  from which the user  may choose  from.
There are many types of menus, such as horizontal menus,vertical menus, drop or
pull down menus, etc.  All of these and many  more are  implemented very easily
using the C User Interface Library menu functions.


                                                     4 - Menus



                         Function List


       Routine           Description
                  
       m_close           Close a menu
       m_filebox         Display a menu list of files.
       m_listbox         List box with multiple selections.
       m_menu            General menu.
       m_scrollmenu      Scrolling menu.

                                                     4 - Menus



Function....: m_close.
Purpose.....: Close a menu left open by m_menu.  Memory allocated for the menu
              is released and the screen underneath the menu is restored.  You
              need only call this function for a menu that has been left open.
Syntax......: void m_close(MEN_PTR *menu);
              MEN_PTR *menu;    Pointer to menu to be closed.
Example call: m_close(&men_ptr);
Returns.....: None.
Common Use..: Clear a menu that has been left open by m_menu.
See Also....: m_filebox,
              m_listbox,
              m_menu,
              m_scrollmenu.
Example.....: Display a list of 3  items in a horizontal menu and let the user
              pick one. Then, leave the menu open and display a drop down menu
              which will automatically close when finished. After the user has
              finished with the drop down menu, close the open parent menu.


              #include "user_int.h"
              void main(void)
              {
              int main_sel,           /* Index of selected items from the */
                  drop_sel;           /* main and drop down menus.        */
              MEN_PTR  main_men_ptr=0;/* Must be initialized to 0         */
              MEN_ITEM main_men_items[3]= /* List of main menu items      */
                       {
                         {0,1 ,"Main 1",".main1_help",1},
                         {0,9 ,"Main 2",".main2_help",1},
                         {0,17,"Main 3",".main3_help",1}
                       };

              MEN_PTR  drop1_men_ptr=0;/* Must be initialized to 0        */
              MEN_ITEM drop1_men_items[2]= /* List of drop menu items     */
                       {
                         {0,0,"Drop 1 - Item 1",".drop11_help",1},
                         {0,0,"Drop 1 - Item 2",".drop12_help",1}
                       };

              MEN_PTR  drop2_men_ptr=0;/* Must be initialized to 0        */
              MEN_ITEM drop2_men_items[3]= /* List of drop menu items     */
                       {
                         {0,0,"Drop 2 - Item 1",".drop21_help",1},
                         {1,0,"Drop 2 - Item 2",".drop22_help",0},
                         {2,0,"Drop 2 - Item 3",".drop23_help",1}
                       };

                                                     4 - Menus



              MEN_PTR  drop3_men_ptr=0;/* Must be initialized to 0        */
              MEN_ITEM drop3_men_items[2]= /* List of drop menu items     */
                       {
                         {0,0,"Drop 3 - Item 1",".drop31_help",1},
                         {1,0,"Drop 3 - Item 2",".drop32_help",0}
                       };

              w_init();
              main_sel=m_menu(5,10,1,25,w_color_menu,HORZ,BORDER,w_shadows,
                              M_OPEN,3,0,&main_men_ptr,main_men_items);
              v_setborder(SINGLE_DROP);
              switch (main_sel)
              {
                 case -1:    /* User pressed ESC. Do nothing.  */
                 break;
                 case 0:
                      drop_sel=m_menu(7,10,2,15,w_color_menu,M_VERT,M_BORDER,
                      w_shadows,M_CLOSE,2,0,&drop1_men_ptr,drop1_men_items);
                 break;
                 case 1:
                      drop_sel=m_menu(7,18,3,15,w_color_menu,M_VERT,M_BORDER,
                      w_shadows,M_CLOSE,3,0,&drop2_men_ptr,drop2_men_items);
                 break;
                 case 2:
                      drop_sel=m_menu(7,24,2,15,w_color_menu,M_VERT,M_BORDER,
                      w_shadows,M_CLOSE,2,0,&drop3_men_ptr,drop3_men_items);
                 break;
              }
              m_close(&main_men_ptr);
              v_setborder(SINGLE);
              if (main_sel==-1) v_prtf("You pressed ESC in the main menu.\n");
              else
              {
                 v_prtf("You selected item %d in the main menu.\n",main_sel+1);
                 if (drop_sel==-1)
                     v_prtf("You pressed ESC in the drop down menu.\n");
                 else
                     v_prtf("You selected item %d in the drop down menu.\n",
                             drop_sel+1);
              }
              w_exit(0);
              }

                                                     4 - Menus



Function....: m_filebox.
Purpose.....: Display a  list of files in a  given directory.  A  list of file
              types is listed in w_file.h. The file types are listed below for
              your convenience.  m_filebox  can display a  maximum of MAX_NUM_
              FILES files, defined to be 512 in w_menu.h.

              1. FA_RDONLY
              2. FA_HIDDEN
              3. FA_SYSTEM
              4. FA_LABEL
              5. FA_DIREC
              6. FA_ARCH

              You may specify more than 1 type of file by bitwise  oring  the
              desired file types.  For example, if you want to display all of
              the hidden files,read only files,and sub-directories of a given
              directory, you would pass the following as the file type:
              FA_HIDDEN | FA_RDONLY | FA_DIREC.
Syntax......: int m_filebox(int row,int col,int num_rows,int num_cols,
                            ATTRIBUTE color,WIN_PTR *window,int shdw,
                            char *title,char *help_word,char *directory,
                            char *file_spec,int file_type,char *sel_file);
              int row;          Screen row at which to display file box
              int col;          Screen column at which to display the file box
              int num_rows;     Number of rows in file box
              int num_cols;     Number of columns in file box
              ATTRIBUTE color;  File box Color
              WIN_PTR *window;  Window to use for file menu
              int shdw;         TRUE\FALSE flag indicating whether to draw a
                                shadow on the filebox.
              char *title;      Title of file box
              char *help_word;  Key word used to retrieve context sensitive
                                help from the help.dat file.
              char *directory;  Directory to search in.  If 0 is specified, then
                                the current directory is searched.
              char *file_spec;  File extensions to search for. If 0 is specified
                                then all files are searched for, ie, "*.*".
              int file_type;    File type.  The file types are listed in dos.h
                                and are prefixed with "FA_".
              char *sel_file;   Pointer to buffer to hold the selected file
Example call: m_filebox(7,33,5,3,w_color_menu,&window,w_shadows,0,".file_box",
                       "*.c","C:\\",FA_ARCH,dir);
Returns.....: The number of the file item selected if Enter was pressed, -1 if
              the user pressed ESC,-2 if there was insufficient memory to dis-
              play the menu,or -3 if the specified directory does not exist or
              no matching files were found.
Common Use..: Let the user pick from a selection of files.

                                                     4 - Menus



See Also....: m_listbox,
              m_menu,
              m_scrollmenu.
Example.....: Display a list of C files and hidden files from the current
              directory and let the user pick one.


              #include "user_int.h"
              void main(void)
              {
              char file[126];             /* Buffer to hold full path name*/
              WIN_PTR file_window;        /* Window to use for file list  */
              int ret_code;               /* Return code from m_filebox   */

              w_init();
              ret_code=m_filebox(7,33,5,3,w_color_menu,&file_window,w_shadows,
                                 0,".file_box",0,"*.c",FA_ARCH | FA_HIDDEN,
                                 file);
              switch (ret_code)
              {
                 case -3:
                      v_prtf("Invalid directory or no matching files found");
                 break;
                 case -2:
                       v_prtf("Insufficient memory to display menu.");
                 break;
                 case -1:
                       v_prtf("You pressed ESC.\n");
                 break;
                 default:
                       v_prtf("You selected %s.\n",file);
                 break;
              }
              w_close(file_window);       /* Close file menu window      */
              w_exit(0);
              }

                                                     4 - Menus



Function....: m_listbox.
Purpose.....: Display a  list of items and lets the user select 1 or more.  By
              pressing the space bar, an item is toggled on/off.  A check mark
              will appear next to an item that has been selected. When you are
              done selecting items, press ENTER  to confirm  the selections or
              ESC to quit.
Syntax......: int  m_listbox (int row,int col,int num_rows,int num_cols,
                             ATTRIBUTE color,int num_items,int item_len,
                             char *items[],int shdw,char *title,char *help_word,
                             char selected[]);
              int row;          Screen row at which to display list box
              int col;          Screen column at which to display the list box
              int num_rows;     Number of rows in list box
              int num_cols;     Number of columns in list box
              ATTRIBUTE color;  List box Color
              WIN_PTR list_wndw;Window to use for list menu
              int num_items;    Number of items in list
              int item_len;     Length of each item
              char *items[]     Array of items to display
              int shdw;         TRUE\FALSE flag indicating whether to draw a
                                shadow on the list box.
              char *title;      Title of list box
              char *help_word;  Key word used to retrieve context sensitive help
                                from the help.dat file
              char selected[];  Array of bytes.  Upon  entry, nonzero  elements
                                of  this array mark  the corresponding item  as
                                selected. Thus, it should be initialized to 0s.
                                Upon return, this  array will contain a nonzero
                                value if the corresponding item  was  selected.
Example call: m_listbox(7,33,5,3,w_color_data,&window,35,12,items_ptr,w_shadows,
              "List box",".list_box",selected);
Returns.....: -1 if user pressed ESC, -2 if the menu could not be set, or the
              index of the last item selected.
Common Use..: Let the user pick from a selection of files.
See Also....: m_filebox,
              m_menu,
              m_scrollmenu.
Example.....: Display a list of items and let the user pick a couple.

                                                     4 - Menus



              #include "user_int.h"
              void main(void)
              {
              WIN_PTR list_wndw;
              char items[36][13]={
                    {"item1.txt"}, {"item2.txt"}, {"item3.txt"}, {"item4.txt"},
                    {"item5.txt"}, {"item6.txt"}, {"item7.txt"}, {"item8.txt"},
                    {"item9.txt"}, {"item10.txt"},{"item11.txt"},{"item12.txt"},
                    {"item13.txt"},{"item14.txt"},{"item15.txt"},{"item16.txt"},
                    {"item17.txt"},{"item18.txt"},{"item19.txt"},{"item20.txt"},
                    {"item21.txt"},{"item22.txt"},{"item23.txt"},{"item24.txt"},
                    {"item25.txt"},{"item26.txt"},{"item27.txt"},{"item28.txt"},
                    {"item29.txt"},{"item30.txt"},{"item31.txt"},{"item32.txt"},
                    {"item33.txt"},{"item34.txt"},{"item35.txt"},{"item36.txt"}
                    },
                   *items_ptr[36],     /* Array to hold pointers to items    */
                    selected[36];      /* Array to hold selections           */
               int i,                  /* Loop variable                      */
                   ret;                /* List box return code               */

               w_init();
               for (i=0;i<36;++i)      /* Initialize selected items to 0     */
               {                       /* ie, all unselected                 */
                    items_ptr[i]=items[i];
                    selected[i]=0;
               }
               ret=m_listbox(7,33,5,3,w_color_data,&list_wndw,35,12,items_ptr,
                   w_shadows,"List box",".list_box",selected);
               if (ret==-1) v_prtf("You pressed ESC.");
               else if (ret==-2) w_errbox(0,"Unable to set up List box.");
               else
               {
                  for(i=0;i<36;++i)
                      if (selected[i]) v_prtf("You selected %s\n",
                                              items[i]);
               }
               w_close(list_wndw);
               w_exit(0);
               }

                                                     4 - Menus



Function....: m_menu.
Purpose.....: Display a horizontal or vertical menu.  This type  of menu does
              not provide scrolling.
Syntax......: int  m_menu(int row,int col,int hgt,int len,ATTRIBUTE color,
                          int menu_type,int border,int shdw,int open,
                          int num_items,int index,MEN_PTR *menu_ptr,
                          MEN_ITEM menu_item[]);
              int row;              Screen row to display menu
              int col;              Screen column to display menu
              int hgt;              Height of menu window
              int len;              Length of menu window
              ATTRIBUTE color;      Color  of menu window and hi lite bar.
              int menu_type;        Menu type.  This can  be one of  the three
                                    menu types(M_HORZ,M_VERT,or M_BOTH) listed
                                    in w_menu.h
              int border;           TRUE\FALSE flag indicating whether  border
                                    should be drawn.
              int shdw;             TRUE\FALSE flag indicating whether shadows
                                    should be drawn.
              int open;             TRUE\FALSE flag indicating whether to leave
                                    the menu open.  If  FALSE, the menu will be
                                    closed automatically once  the user selects
                                    a menu item or presses ESC.  If TRUE,  then
                                    the  user  must close  the  menu by calling
                                    m_close when he is finished.See the m_close
                                    example.  M_OPEN and M_CLOSE are defined in
                                    w_menu.h.
              int num_items;        Number of items in the menu
              int index;            Starting menu item.  This  specifies where
                                    the  menu's hi lite bar  will be initially
                                    positioned.
              MEN_PTR *menu_ptr;    Menu pointer
              MEN_ITEM menu_item[]; List of menu items
Example call: sel=m_menu(2,2,1,26,w_color_menu,HORZ,BORDER,w_shadows,M_OPEN,
              0,&men_ptr,men_items);
Returns.....: Index of selected  menu item if  Enter is pressed, -1 if ESC was
              pressed, -2 if there  is insufficient memory to create the menu,
              or -3 if  none of the menu items are selectable.
Common Use..: Display a list of choices.
See Also....: m_close,
              m_filebox,
              m_listbox,
              m_scrollmenu.
Example.....: Display a list of 3 items and let the user pick one.

                                                     4 - Menus



The MEN_ITEM structure used by the m_menu routine is shown below and is defined
in w_menu.h.

typedef struct MEN_ITEM
{
   int   row;                           /* Row of menu item                   */
   int   col;                           /* Col of menu item                   */
   char *text;                          /* Text of menu item                  */
   char *help;                          /* Help key word                      */
   char  sel;                           /* If menu item is selectable         */
}  MEN_ITEM;

    Each menu item is comprised of the above fields. The row and column fields
are relative to the menu window.  The text field is the actual menu  text that
will be  displayed for the menu  item.  The help field is the key word used to
retrieve context sensitive help from the help.dat file(See chapter 4). The sel
field is a  TRUE\FALSE flag specifying whether or not the menu item is select-
able or not. If  FALSE is specified, the  menu text will be displayed, but the
user will not be able to select that menu item.

    To create a menu, you need two things:  A menu pointer, and a list of menu
items.  All menu pointers  must be  initialized to 0.  Otherwise,  the  m_menu
routine will  think  that the menu is already  on the screen  and garbage will
result.

    To select a menu item, use the arrow keys. Depending on the menu type, the
arrow keys will have a different meaning. The menu types and the corresponding
actions of the arrow keys are shown below.

Menu       Right               Left              Up               Down
Type       Arrow               Arrow            Arrow             Arrow
                                               
M_HORZ   Move right          Move left           Quit              Quit
M_VERT      Quit                Quit            Move up          Move down
M_BOTH  Move right\up     Move Left\down     Move right\up     Move Left\down

    Pressing Enter will select the menu item. Pressing ESC will quit the menu.
You may  also select  a menu item by pressing the 1st  letter of the text.  If
there are two items which both start  with the same letter, only  the 1st item
will be selected.

    You may also use the mouse to select a menu item, if one is installed. The
left   mouse  button  translates  to an "ENTER" key press  and the right mouse
button translates to an "ESC" key press.

    The row, col, len and hgt  parameters  are used  to open a window  for the
menu.You must ensure that the window dimensions are large enough to accommodate
the number of menu items specified.

                                                     4 - Menus



    If you wish to separate items in a menu with a line, use the defined word
M_LINE for the text field,defined in w_menu.h. An example is shown below. The
line will be unselectable and no help word is necessary.

              #include "user_int.h"
              void main(void)
              {
              int sel;               /* Index of selected menu item returned */
                                     /* by m_menu                            */
              MEN_PTR  men_ptr=0;    /* Must be initialized to 0             */
              MEN_ITEM men_items[4]= /* List of menu items                   */
                       {
                         {0,0,"Item 1",".item1_help",1},
                         {1,0,"Item 2",".item2_help",1},
                         {2,0, M_LINE ,  0          ,0},
                         {3,0,"Item 3",".item3_help",1}
                       };

              w_init();
              sel=m_menu(5,10,4,6,w_color_menu,M_VERT,M_BORDER,w_shadows,
                         M_CLOSE,4,0,&men_ptr,men_items);
              switch (sel)
              {
                 case -3:
                       w_errbox(0,"No menu items are selectable.");
                 break;
                 case -2:
                       w_errbox(0,"Unable to menu.");
                 break;
                 case -1:
                       v_prtf("You pressed ESC.");
                 break;
                 default:
                       v_prtf("You selected item %d",sel+1);
                 break;
              }
              w_exit(0);
              }

                                                     4 - Menus



Function....: m_scrollmenu.
Purpose.....: Display a list of menu items and allow the user to scroll through
              them.  Unlike m_menu, m_scrollmenu  does not have the  ability to
              display nonselectable items.  m_scrollmenu is used when  you have
              too many choices to display on the screen at once. For example,if
              you had a picklist of 50 printers, you would  use m_scrollmenu to
              display  maybe ten printers  at a time and  let the  user  scroll
              through the list. The menu is left open after the user selects an
              item or presses Esc to quit.The scrolling menu is closed by call-
              ing  w_close() to  close the menu window, which is stored in  the
              window parameter you pass.  When returning to a  scroll menu that
              was left open,you may change the number of items, the items them-
              selves, title, and help word from the previous call.  If you move
              the menu or change its size, your program will crash.
Syntax......: int m_scrollmenu(int row,int col,int num_rows,int num_cols,
                               ATTRIBUTE color,int num_items,int item_len,
                               char *items[],int shdw,char *title,
                               char *help_word);
              int row;         Screen row of menu
              int col;         Screen column of menu
              int num_rows;    Number of rows in menu
              int num_cols;    Number of columns in menu
              ATTRIBUTE color; Color of menu
              WIN_PTR *window; Scroll menu window
              int num_items;   Number of items in menu
              int item_len;    Length of text in each item
              char *items[];   List of items
              int shdw;        TRUE\FALSE flag indicating whether to draw a
                               shadow on the menu.
              char *title;     Title of menu
              char *help_word; Key word used to retrieve context sensitive
                               help from help.dat file.
Example call: sel=m_scrollmenu(5,5,3,2,w_color_menu,&window,30,10,items,
                  w_shadows,0,0);
Returns.....: Index of selected menu item or -1 if ESC was pressed.
Common Use..: Used instead  of m_menu  when the  number  of  menu items is too
              numerous to display all  at once.  m_scrollmenu  displays only a
              portion of the  menu items at  any given  time.  The rest can be
              scrolled into view as needed.
See Also....: m_filebox,
              m_listbox,
              m_menu.
Example.....: Display a list  of items and  let the  user scroll  through  the
              choices and pick one.

                                                     4 - Menus



              #include "user_int.h"
              void main(void)
              {
              char items[36][13]={
                    {"item1.txt"}, {"item2.txt"}, {"item3.txt"}, {"item4.txt"},
                    {"item5.txt"}, {"item6.txt"}, {"item7.txt"}, {"item8.txt"},
                    {"item9.txt"}, {"item10.txt"},{"item11.txt"},{"item12.txt"},
                    {"item13.txt"},{"item14.txt"},{"item15.txt"},{"item16.txt"},
                    {"item17.txt"},{"item18.txt"},{"item19.txt"},{"item20.txt"},
                    {"item21.txt"},{"item22.txt"},{"item23.txt"},{"item24.txt"},
                    {"item25.txt"},{"item26.txt"},{"item27.txt"},{"item28.txt"},
                    {"item29.txt"},{"item30.txt"},{"item31.txt"},{"item32.txt"},
                    {"item33.txt"},{"item34.txt"},{"item35.txt"},{"item36.txt"}
                    },
                   *items_ptr[36];     /* Array to hold pointers to items    */
              int i,                   /* Loop variable                      */
                  ret;                 /* Scroll menu return code            */
              WIN_PTR window;          /* Scrolling menu window              */

              w_init();
              for (i=0;i<36;++i)       /* Set pointers to items              */
                   items_ptr[i]=items[i];
                                       /* Display items                      */
              ret=m_scrollmenu(7,33,5,3,w_color_menu,&window,35,12,items_ptr,
                               w_shadows,"Scroll Menu",".scroll_menu");
              switch (ret)             /* what did the user do?              */
              {
                 case -2:
                       v_prtf("General error(eg, insufficient memory)");
                 break;
                 case -1:
                       v_prtf("You pressed ESC");
                 break;
                 default:
                       v_prtf("You selected %s",items[ret]);
                 break;
              }
              w_close(window);         /* Close scrolling menu               */
              w_exit(0);
              }


                                                     5 - Help


                                  Chapter 5

                                    Help

                                                     5 - Help



    Overview

    Noone likes  to read  manuals.  At least I've never met anyone personally.
We all buy, or  copy, software, and  try to use it without reading the manual.
We resort to reading the  manual as a last  ditch  effort, once  all else  has
failed. For instance, you probably ran the demo and looked at the source code,
and then went on your way to  starting to write your own programs.  After all,
this is a pretty hefty manual.  This is probably the only section you probably
really do need to read.  This and the data  entry section.  The rest of it you
can pretty much figure out from the demo source code.

    Concepts

   Context Sensitive help is quit easily implemented with the C User Interface
Library.  Context sensitive help is  the ability to give the user some form of
aid while in a wait state.  This means that whenever the user is using a  menu
or performing  data  input, the user has to have  some way to get help and the
application has to have some way of supplying it.  Over the years, a  standard
has developed.  This standard is the F1 key.  Whenever the user presses the F1
key, the application  must display a help  screen with information  related to
what the user is currently doing.  For example, if the user is in a menu, then
the help screens could explain what the menu choices mean,how to select a menu
item, how to quit and get out of the menu, etc. Before we start discussing the
details of how help is implemented in this library, it would  be very  helpful
if you had a copy of the  help.dat file used by the demo program to look at as
we discuss the various parts of the help system.

    The C User Interface Library implements help in the following way.  First,
there is  an  ascii  text file, help.dat, which contains the text for the help
screens.  The help file is broken up into help topics. Each topic has 2 parts.
The first part is the key word.  This key word is what is used to identify and
separate the help text for one topic from another. The format of a key word is
shown below.

keyword format:  .help_word

    The keyword begins with a period, and starts in the very first column.  If
the keyword  does  not start in  the 1st column, it will be ignored,  and will
actually become part of the help text for the previous help topic.

    The second  part  of a  help topic  is the  text which  comprises the help
screens.  This is the actual text that will be displayed when the user presses
the F1 key. The help text for any given help keyword is limited to 3000 lines.
In my lifetime, I have never seen a program with 3000 lines of help text for a
single item and I doubt you will either.

    The last  part of the help system is the index file, help.ntx.  This  file
keeps track of the keywords and  where the corresponding help  text is located
within the help.dat file.  The index  file is created for you by the  hlp_indx
utility  provided.  You do not need to understand  anything  about  the  index
file except that you need one to go along with your help  file.  They form  an
inseparable pair.  The index file aids in the  search for the needed help text
when the F1 key is pressed.

                                                     5 - Help



    You must have noticed by now, that  the menu functions and the data  entry
functions  have a help  word as one of their parameters.  This  is the keyword
mentioned  above.  Then, whenever the  menu  hi lite bar is positioned on that
particular menu item, or whenever the cursor is moved to a particular get, and
the F1 key is pressed,it is this keyword that is used to go into the help file
and retrieve the relevant help text.

    Now, how do you add context sensitive help to your own applications? Well,
its easy. First, you should copy the help.dat file provided into the directory
where you are building your application.  If you ran the install program, then
the help.dat file  should be in the  same directory as the utility files.  The
help.dat file found in the utility directory contains the basic help text used
internally by many CUI functions. For example, the help file contains the help
used by w_setup, p_start, and the default  help used by many functions if none
is supplied by the user. For example,if you don't provide a help word and text
for the f_edit function, then f_edit will  use the default help text found  in
this help  stub.  The stub file is a basic building block, the bare minimum of
help that should be provided.  Once you've copied  the help.dat file from  the
utility directory to your own working directory, you are ready to start adding
help specific to your own application.  Simply use your favourite text editor,
move to the very end of the file, and start adding  your own keywords and help
text in the format described above. Once you're done adding your own help, you
have to run the hlp_indx utility to create the help.ntx file. The hlp_indx.exe
file is found in the utility directory if you used the install program. Simply
type hlp_indx, and  the help.ntx file will  be created.  You're done.  See the
appendix for more details on the hlp_indx utility program. Now, when your app-
lication is run,the help.dat and help.ntx files will be read into memory auto-
matically.(This is one of the functions of w_init and also why w_init() should
be the 1st  line of  code in your  applications).  Keeping this information in
memory instead of reading the  file off a disk will speed up  the retrieval of
help text, because a disk read is averted.

    Although the F1  key has become the standard for getting  help, The C User
Interface Library allows you to set up any function key as the help key.  This
is done by calling k_set(),which is described in chapter 6, under the keyboard
section.

    The C User  Interface library looks for  the help.dat\.ntx files  first in
your current  directory, and if not found, along  the DOS path.  If it can not
find them,then your application will still run, but no help will be available.

                                                     5 - Help



                         Function List


       Routine           Description
                  
       w_help            Display context sensitive help screen.

                                                     5 - Help



Function....: w_help.
Purpose.....: Display  context  sensitive  help screens.  This is an internal
              function called by the menu and data entry functions to display
              context sensitive help text from  the help.dat  file.  The help
              window will be displayed in a color specified by the global var-
              iable w_color_help.  The help window is  drawn  using a  single
              border, with  shadows if the global w_shadows is  non-zero, and
              occupies the entire screen.  The help text  width is limited to
              the number of columns on the screen.  Text extending beyond the
              screen width is truncated.
Syntax......: void w_help(char *help_word);
              char *help_word;   Key word to look up in Help index
Example call: w_help(".help_word");
Returns.....: None.
Common Use..: Display a help screen whenever F1 is pressed.
See Also....: None.
Example.....: None.

                                                     6 - Data Entry

                                  Chapter 6

                                 Data Entry


                                                     6 - Data Entry



    Overview

    User input is used in some form or another by most computer programs.  The
standard C library provides many console data input functions, such as getche,
scanf, and gets.  All standard C library data input functions are  similar  in
that they function as a teletype.  After a call to scanf, you are moved to the
next line, and the text that was on the top row of the screen is scrolled off.
Also,  there is  no way to prohibit the user from typing in anything he wants.
For example, suppose you want the user to enter a date in the  form  mm/dd/yy.
Scanf  does  nothing to  prohibit the user from typing in "Hello" instead of a
date.  You have  to do the  error checking after the  user hits return and the
screen is scrolled down 1 row.  These problems and many more are solved by the
C User Interface Data Entry routines.

    Concepts

    The C User  Interface Library  provides many built in data types and built
in  error checking.  The "get"  lies at the heart of the data entry functions.
When you want  to get some  input from the user, you use a "get" to say  where
on the screen the input will take place, the type of data the user is supposed
to enter (eg, a phone number, an integer, etc), what the allowed  values  are,
and  a  few  other  details about  how the input will operate.  The data types
supported by the C User  Interface Library are  listed in w_get.h, and to date
total 20 in all.

    Usually, when a user performs an edit on a variable, he must first make an
edit copy of the variable,whose value he transfers to the real variable if and
only if the user did not press ESC to quit the edit.  He must also  reserve an
edit buffer to be used for editing the variable.  For example:

int sales=1000,        /* Variable we want to edit                     */
    edit_copy;         /* Edit copy of variable                        */
char buffer[5];        /* Edit buffer for variable                     */

edit_copy=sales;       /* Copy value into edit copy                    */
g_int(4,4,sales,buffer,/* Say where and what type of edit              */
      ...);            /* Other parameters                             */
g_read();              /* Perform edit                                 */
if (w_lastkey!=ESC)    /* If and only if the user did not press ESC,   */
    sales=edit_copy;   /* should the original variable be updated      */

   The C User Interface  Library takes care of all of this for you.  You don't
need to make a backup copy of  the variable you want to edit, you don't need to
reserve memory for an edit buffer  for  the variable.  All of this is done for
you so you don't have to.

                                                     6 - Data Entry



    To perform data input with the C User Interface Library, you simply set up
the "gets", which say where and what type of  data is expected, and  then call
g_read() to perform the  edit.  So now  that you know the concepts behind data
input, lets see the details of exactly how its implemented.

    The "get" functions are all prefixed with a "g_".  The "get" functions are
identical to each other with two exceptions. First, the general format will be
discussed.  Each "get" function takes the following seven parameters:

1.  WIN_PTR window;
2.  int     row;
3.  int     col;
4.  char   *prompt;
5.  int     display_flag;
6.  char   *help_word;
7.  int (*valid)(void);


1. window       -  Window in which the data input will take place.
2. row          -  Window row where the data input take.
3. col          -  Window column where the prompt will be displayed.  The prompt
                   will be displayed at the row and column coordinates specified
                   by row and col, and the actual edit will begin 1 column after
                   the end of the prompt.
4. prompt       -  Prompt that will be  displayed  directly  in front of the
                   edit.
5. display_flag -  TRUE\FALSE flag indicating whether  or not the  initial value
                   of the edit variable should be displayed.
6. help_word    -  Help key word that will  be used to display context sensitive
                   help screens whenever the F1 key is pressed.
7. valid        -  Pointer to a function that will perform error checking.  This
                   can be a pointer  to your own valid function, or 0 to use the
                   C User Interface Library default valid.


    All of the above parameters are self-explanatory with the exception of the
valid  function.  This is a function which  excepts no  parameters and returns
an integer (TRUE\FALSE). You do not have to call the valid function explicitly
as it will be called automatically for you.  The valid function will be called
every time you move off of a "get".  By this, I mean  the  following.  Suppose
you have set up "gets" for 5 variables,and you are currently entering data for
the 3rd variable. Next, you press an up arrow to move back to the 2nd variable
or a down  arrow to  move  down to the 4th variable.  In either case, you have
moved off of the 3rd "get".  This causes the  valid function for the 3rd "get"
to be executed  automatically.  The valid function will return a TRUE or FALSE
indicating if the  data entered for the 3rd variable is valid or not.  If TRUE
is returned, then everything is OK and you move off of the 3rd "get". However,
if FALSE is returned, then the data entered into the 3rd "get" was not correct
and the user is not allowed to move off of the "get" until valid data has been
re-entered which satisfies the valid function.  This is all pretty abstract so
let's take a look at a real life valid function.

                                                     6 - Data Entry



    Shown below is the default valid function for "g_yn",which gets a 'Y'es or
'N'o input.  Let's take  a look  at exactly  what a valid  function should do.
First, in line 1,we declare a function which accepts no parameters and returns
an integer.  "g_yn" gets a single  character, which is supposed to be a 'Y' or
an 'N'.  Let's skip to line 5 now. The last key pressed by the user can always
be found in the global variable "w_lastkey".  Line 5 checks to see if the user
is trying to move back to a previous get. If he is, the valid function doesn't
even  bother to check what data the user entered for the Yes\No character.  It
simply says everything is OK and returns TRUE.  However, if the last key was a
down arrow, Enter, or Page Down, then the valid function goes ahead and checks
what data the  user entered  for the  Yes\No character.  Line 7 takes the edit
variable and copies it into a temporary variable called "ch".  This is only so
that we don't have to keep using the long  and complicated syntax shown on the
right side of "ch", which will be explained a little later on.  For now, don't
worry about line 7 too much, except that we now have the letter the user typed
in for the Yes\No character in  the variable "ch".  Line 9 tests to see if the
letter entered by the  user was a 'Y' or  an 'N'.  If it wasn't, then the user
made a mistake and entered an  invalid  character.  Line 11  displays an error
message to the user, letting him know that he entered an invalid letter.  Then
FALSE is  returned, indicating  that the  user  entered an  invalid letter and
should  not  be  allowed  to move  off the "get" requesting the Y\N character.
However, if the user  did enter a 'Y' or 'N', then lines 11 an 12 are skipped,
and TRUE is returned on line 14 indicating that everything is OK.

1.  int def_val_yn(void)              /* Default valid function for "g_yn"   */
2.  {
3.  char ch;
4.
5.  if (w_lastkey==UP_ARROW)          /* If user is moving back, then its OK */
6.      return(TRUE);                 /*                                     */
7.  ch=*(char *)w_get.get             /* Else, get the Yes/No edit variable  */
8.      [w_get.cur_get]->edit_var;    /*                                     */
9.  if (ch!='Y' && ch!='N')           /* Did user enter a 'Y'es or 'N'o?     */
10. {                                 /* No  - Then display error message    */
11.     w_errbox(0,"You must enter \'Y\'es or \'N\'o.");
12.     return(FALSE);                /*     - Return FALSE                  */
13. }                                 /* Yes - User entered correct data     */
14. return(TRUE);                     /*     - Return TRUE                   */
15. }

                                                     6 - Data Entry




    Now let's  return and  take a look at line 7.  This line contains a lot of
information.  We need to break up the expression:

    *(char *)w_get.get[w_get.cur_get]->edit_var

and  examine  it  piece by piece. You don't need to have a copy of  w_get.h to
follow the discussion below, but it would help.  Let's break the expression in
line 7 into the following pieces:

    1. w_get.cur_get
    2. w_get.get[]
    3. edit_var

    Although the  GET structure is very complicated and is quite intimidating,
the expression found in line 7 is the only one you need to know.  It should be
memorized.  You  may forget  about  the rest  of  the  fields.  They are  used
internally only.The only field you should ever modify is the one shown in line
7.

    1. w_get.cur_get - This variable contains the number of  the get currently
                       being edited. For example, if you have 5 gets, numbered
                       0 - 4, and you are currently  editing the 3rd get, then
                       w_get.cur_get will be 2.
    2. w_get.get[]   - This is an array of get items. Each get has many inter-
                       nal fields  associated  with it.  These  fields include
                       things such as the prompt for the get, where the get is
                       located on the screen, etc.  Thus, the expression:
                       w_get.get[w_get.cur_get], while very long winded,simply
                       refers to the current get.
    3. edit_var      - This is  the only  field of a get item  that you should
                       ever be concerned with.As was stated early on, normally
                       you have to  make an edit  copy of a  variable, perform
                       an edit on the edit variable, and then if the  user did
                       not press ESC, then, and only then,do you copy the edit
                       variable into  the original variable. We said, however,
                       that this whole process was done for you. You see, when
                       you read the currently  pending  gets, you are actually
                       editing copies of the original variable, stored in  the
                       edit_var field.  Thus, to you the  programmer, this  is
                       the most important field, and actually, the  only field
                       you should ever be concerned with.  This field contains
                       a void pointer to a copy of the variable being edited.


    So, the expression w_get.get[w_get.cur_get]->edit_var is a void pointer to
the variable currently being  edited.  Now,  since this is a void pointer, the
last step is to  type cast this  pointer into the type of variable being read.
In our "Yes\No" example  on  the previous page, we  were reading  in  a single
character.  So  this  is why  we place the "(char *)" typecast in front of the
w_get.get[w_get.cur_get]->edit_var, to  turn it into a pointer to a character.
So now we have (char *)w_get.get[w_get.cur_get]->edit_var, as  being a pointer
to a character.

                                                     6 - Data Entry



    The '*' operator, which officially is the "indirection operator",but which
I call the contents operator, gets the contents of the address pointed to by a
pointer.  So what does  that first asterisk in front of the (char *) type cast
do?  Since (char *)w_get.get[w_get.cur_get]->edit_var is a  pointer to a char,
the '*' simply  gets  the single character  stored at that address.  Thus, the
entire expression  ch=*(char *)w_get.get[w_get.cur_get]->edit_var  copies  the
single "Y/N" character being edited into ch.  Let's test your understanding of
the concepts presented so far.  What if we were reading in an integer variable
instead of  a  char?  How would we modify line 7 to  copy the edit_var into an
integer? It is very simple. Remember, "w_get.get[cur_get]->edit_var" is always
a  void pointer  to  the  variable  currently  being edited.  Since we are now
editing  an  integer,  we  must first type cast the void pointer to an integer
pointer.  This is done by preceding the "w_get.get[cur_get]->edit_var" expres-
sion with "(int *)", making it "(int *)w_get.get[cur_get]->edit_var".  Now, we
have  a  pointer to an  integer.  The last step  to is get the actual integer.
This is done  by  using  the  "contents operator", '*', which makes the entire
expression: *(int *)w_get.get[cur_get]->edit_var. Lets compare the expressions
to get the edit_var for integer and char types.

char: *(char *)w_get.get[cur_get]->edit_var;
int.:  *(int *)w_get.get[cur_get]->edit_var;

Can you guess what the expression would be for a float? an unsigned long int ?
a char pointer, ie, char * ?
The answers are shown below.  Notice  there  is no  asterisk in  front  of the
(char *) type  cast for char *.  Do you know why?  It's because we are getting
a pointer, char *, and not a character, char.

float............: *(float *)w_get.get[cur_get]->edit_var;
unsigned long int: *(unsigned long int *)w_get.get[cur_get]->edit_var;
char *...........:  (char *)w_get.get[cur_get]->edit_var;

    As you can see,although the concepts involved are quite complex,to actual-
ly use them is quite simple.  Let's take a look at one last example. This will
show you how to use the edit_var once you've got its address and contents.

    Suppose we have a "get" for a string. Strings are simply char pointers, of
type char *.  Furthermore, suppose  we  want  the  user  to enter  the type of
printer he has.  We'll write our own valid  function to make sure he entered a
printer that we support, say "IBM", "Epson", or "Okidata".  First, the code to
get the printer, and then the code to do the validating.

                                                     6 - Data Entry




#include <string.h>                    /* Needed by our valid function    */
#include "user_int.h"                  /* Include in every program        */
int our_valid(void);                   /* Declare our own valid function  */

void main(void)
{
WIN_PTR window;                        /* Window to get printer type      */
char    printer[21];                   /* Original printer variable       */

w_init();
window=w_open(5,5,1,40,TRUE,TRUE,      /* Open a 1 line window            */
              w_color_data,0);         /*                                 */
if (!window) w_exit(1);                /* If an error, quit               */
g_string(window,0,1,"Printer Type:",   /* Set up a get for a string       */
  printer,20,FALSE,".printer_type",    /* using our own valid function    */
  &our_valid);                         /*                                 */
g_read();                              /* Perform edit                    */
g_close();                             /* Release memory                  */
w_close(window);                       /* Close the window                */
w_exit(0);
}

1.  int our_valid(void)
2.  {
3.  char *printer;                          /* Temp variable.  Used to copy   */
4.                                          /* edit_var so we don't have to   */
5.                                          /* keep using that long expression*/
6.
7.  printer=(char *)w_get.get               /* Copy the edit variable into our*/
8.          [w_get.cur_get]->edit_var;      /* printer variable.              */
9.  if (strcmp(printer,"IBM")    &&         /* See if the user entered a valid*/
10.     strcmp(printer,"Epson")  &&         /* printer type.                  */
11.     strcmp(printer,"Okidata"))          /* No  - User entered a printer we*/
12.  {                                      /*     - don't support.           */
13.      w_errbox(0,"Invalid printer type.    /*     - Display an error message.*/
14.      Printer will be set to IBM default");
15.      strcpy(printer,"IBM");             /*     - Set the edit_var to "IBM"*/
16.  }                                      /* Even if an invalid printer was */
17.  return(TRUE);                          /* entered, it was corrected. So  */
18.  }                                      /* return TRUE no matter what.    */

                                                     6 - Data Entry



    So. What does our valid function do?  Line 1 is a declaration of a function
which accepts no parameters and returns an integer,as must all valid functions.
Line 3 declares a temporary variable that we use so we don't have to keep using
the long expression shown on lines 7 and 8,which copies the edit_var address to
our temporary  variable.  Notice  that  we  type cast  it.  This is because the
edit_var is actually a void pointer, and must always be type cast.  Lines 9,10,
and 11 check to see if the printer entered by the user is one we support. Lines
13 and 14 display a simple error message. Line 15 is the interesting one. Since
we  always  have the  address  of the edit_var, any changes we make to edit_var
remain even after we leave the valid function. Thus, if an invalid printer type
is entered, we change the contents  of the edit_var to "IBM".  Now, even if the
user  entered an  invalid  printer type, we have  changed it to a valid one, so
everything is OK, and we return TRUE to indicate so.

    An even  better printer valid function would be one that displays a menu of
valid printers,lets the user pick one,and then sets the edit_var to the printer
selected by the user.  The revised printer valid function is shown below.

1.  int our_valid(void)
2.  {
3   int   sel;                              /* Menu selection                 */
4.  char *printer;                          /* Temp variable.  Used to copy   */
5.                                          /* edit_var so we don't have to   */
6.                                          /* keep using that long expression*/
7.  MEN_PTR  prn_men_ptr =0;                /* Menu of printers               */
8.  MEN_ITEM prn_items[3]={{0,1,"IBM    ",".IBM_printer"    ,1},
9.                         {1,0,"Epson  ",".Epson_printer"  ,1},
10.                        {2,0,"Okidata",".Okidata_printer",1}};
11.
12. printer=(char *)w_get.get               /* Copy the edit variable into our*/
13.         [w_get.cur_get]->edit_var;      /* printer variable.              */
14. if (strcmp(printer,"IBM")   &&          /* See if the user entered a valid*/
15.     strcmp(printer,"Epson") &&          /* printer type.                  */
16.     strcmp(printer,"Okidata"))          /* No  - User entered a printer we*/
17.  {                                      /*     - don't support.           */
18.  sel=m_menu(6,3,3,7,w_color_menu,       /*     - Display a pick list of   */
19.      M_VERT,M_BORDER,w_shadows,M_OPEN,  /*     - valid printers.  Let user*/
20.      3,0,&prn_men_ptr,prn_men_items);   /*     - pick one.                */
21.  if (sel!=-1)                           /* Did user quit menu without     */
22.  {                                      /* choosing a printer?            */
23.     strcpy(printer,                     /* No  -Then copy the users choice*/
24.     prn_items[sel]->text);              /*     - into the edit_var        */
25.     return(TRUE);                       /*     - Say everything is OK     */
26.  }                                      /*                                */
27.  else                                   /* Yes - Say user entered an      */
28.     return(FALSE);                      /*     - invalid printer          */
29.  }                                      /*                                */
30.  return(TRUE);                          /* User entered a valid printer   */
31.  }                                      /* to begin with.                 */

                                                     6 - Data Entry



    There's a lot of information here, and it will  take some time before it
really sinks in  and you  become comfortable using it.  When you first start
out, we  recommend  that you  specify a 0 for the valid function.  This will
cause the C  User Interface Library  to use a default valid function.  These
default valid functions  are discussed in Appendix B.  Once you get comfort-
able with the window, get,and menu functions, you should then begin to write
your own valid functions.

    Now,as said before,the "get" functions make an edit copy of the original
variable.  All editing is done on these edit copies.  The original variables
are not updated until all of the following conditions are met.

    1.  The user presses Page Down, or if the user is on the last "get",
        Enter.
    2.  All valid functions return TRUE.

If the user presses ESC, then the edit is aborted and the original variables
are left unchanged.  Below is a  list of  special keys used by g_read() when
performing an edit on the list of pending "get"s.

    1. Page Up     - Move to the 1st pending get.
    2. Page Down   - End the read.  This causes all valids  to be executed.  If
                     any valid fails,the cursor is positioned on the failed get
                     and  valid  data must  be entered.  The original variables
                     will be updated only if all valids return TRUE.
    3. Enter       - Move  to the next get. If the current get is the last get,
                     then this key is converted to the equivalent Page Down key
                     otherwise it is converted to a Down arrow key.
    4. Right Arrow - Move to the next edit character to the right.  This may or
                     may not be the next  column to the right as illustrated in
                     following example:  Suppose  the user  is positioned  on a
                     phone  get.  The  right  and left parentheses for the area
                     code and  the dash  after the  exchange  are  non editable
                     characters.Thus, if the cursor is positioned on the column
                     just  prior  to one of these  characters,  the cursor will
                     actually skip over these  characters and move to  the  1st
                     edit character.  If the cursor is already on the last edit
                     character, a beep will sound.
    3. Left  Arrow - Move to the 1st edit character to the left.  If the cursor
                     is  already positioned  on the 1st edit character, a  beep
                     will sound.
    4. Up    Arrow - Move  to  the  previous  get.  If  the  cursor  is already
                     positioned on the 1st get, a beep will sound.
    5. Down  Arrow - Move to the next get.  If the cursor is already positioned
                     on the last get, a beep will sound.
    8. End         - Move to  the next edit  character in the current get after
                     the last character entered.
    9. Home        - Move to the 1st edit character in the current get.

    The last key pressed by the user is always stored in the global w_lastkey.
This is an "unsigned int" variable and holds  the value returned  by k_getkey.
a complete listing of key values is listed in w_keybrd.h.

                                                     6 - Data Entry



                         Function List


       Routine           Description
                  
       g_char            Get a single character.
       g_checkbox        Get a list of check boxes
       g_close           Clear all gets.
       g_date            Get a date, excluding the century.
       g_double          Get a double floating point value.
       g_ext_date        Get a date, including the century.
       g_ext_time        Get a time, including the seconds.
       g_ext_zip         Get a zip code, including the 4 digit extension.
       g_filename        Get a file name
       g_float           Get a floating point value.
       g_int             Get an integer value.
       g_long            Get a long integer value.
       g_password        Get a password.  Password is not echoed to the screen.
       g_phone           Get a phone number.
       g_read            Edit pending gets.
       g_soc_sec         Get a social security number.
       g_string          Get a string.
       g_tf              Get a TRUE\FALSE answer.
       g_time            Get a time, excluding the seconds.
       g_unchar          Get an unsigned char.
       g_unint           Get an unsigned integer.
       g_unlong          Get an unsigned long integer.
       g_yn              Get a Yes\No answer.
       g_zip             Get a zip code, excluding the 4 digit extension.

                                                     6 - Data Entry



Function....: g_char.
Purpose.....: Get a single character.
Syntax......: int  g_char(WIN_PTR window,int row,int col,char *prompt,
                   char *char_var,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *char_var;      Pointer to character to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the char should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_char(window,2,1,"Char:",&ch,FALSE,".help_char",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a character variable.
See Also....: g_string,
              g_unchar,
              g_yn,
              g_tf.
Example.....: Input a single character.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    ch;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_char(window,0,1,"Char:",&ch,FALSE,".char_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %c\n",ch);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_checkbox.
Purpose.....: Get a  check mark in  a box.  This is usually used to  display a
              list of items  and then to let the user check off one or more of
              the items.  A box is displayed, "[ ]", followed by a blank space
              and then the prompt.  This  is the only  get which displays  the
              prompt on  the  right side of the  get.  All others display  the
              prompt and then the get. The user may then check off the item by
              placing an "x" in the desired box. You may use a valid  function
              to control how  many items are selectable(eg, only one, or mult-
              iple  items).  After you  have called  g_read to do  the read, a
              checked item will have an 'x' in its edit  variable and a  blank
              space if it wasn't selected. g_checkbox is similar in  nature to
              m_listbox, but is used when there  are only a few items that can
              be checked and also is often used as part of a form to be filled
              out by a user.
Syntax......: int  g_checkbox(WIN_PTR window,int row,int col,char *prompt,
                   char *check_var,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *check_var;     Pointer to check character to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the check box should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_checkbox(window,2,1,"Item 1",&chk,FALSE,".help_check",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Provide a check list of items which the user can mark off with an
              "x".
See Also....: m_listbox.
Example.....: Display a list of items and let the user check off some.


                                                     6 - Data Entry



              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              int     i;
              char    checks[5],       /* Items to mark off               */
                     *items[5]={"Item 1","Item 2","Item 3","Item 4","Item 5"};

              w_init();
              window=w_open(5,5,5,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              for (i=0;i<4;++i)
                   g_checkbox(window,i,1,items[i],&checks[i],FALSE,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey==ESC)
                  v_prtf("User pressed ESC\n");
              else
                 for(i=0;i<4;++i)
                     if (checks[i]=='x')
                         v_prtf("User checked off item %d\n.",i+1);
              k_wait(0);
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_close.
Purpose.....: Clear all pending gets  and free  allocated  memory.  g_close()
              should be called immediately after g_read to clear the gets and
              to release the memory allocated by the get functions.
Syntax......: void g_close(void);
Example call: g_close();
Returns.....: None.
Common Use..: Called immediately after g_read to clear all gets.
See Also....: g_read.
Example.....: Set up some gets, read (edit) them, then ask the user if he would
              like to re-edit the variables.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              int   integer;
              char  ch;
              char  phone[15];

              w_init();
              window=w_open(5,5,3,40,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_int(window,0,1,"Number:",&integer,3,FALSE,0,0);
              g_char(window,1,1,"Character:",&ch,FALSE,0,0);
              g_phone(window,2,1,"Phone:",&phone,FALSE,0,0);
              g_read();
              if ('Y'==w_ynbox("Would you like to re-edit the variables.",0))
                  g_read().       /* The gets remain pending until g_close */
              g_close();          /* is called.                            */
              w_close(window);
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_date.
Purpose.....: Get a date in the current century.
Syntax......: int  g_date(WIN_PTR window,int row,int col,char *prompt,
                   W_DATE *date,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              W_DATE *date;        Pointer to date to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the date should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_date(window,2,1,"Date:",&date,FALSE,".help_date",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a date variable, excluding the century.
See Also....: g_extdate,
              g_exttime,
              g_time.
Example.....: Input a date, excluding the century.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_DATE  date;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_date(window,0,1,"Date:",&date,FALSE,".date_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",d_datestr(date));
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_double.
Purpose.....: Get a double floating point value.
Syntax......: int  g_double(WIN_PTR window,int row,int col,char *prompt,
                            double *double_var,int max_char,int disp_flag,
                            char *help_word,int (*valid)(void));

              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              int max_char;        Number of characters to allow for editing.
                                   The max_char must be  1 and  22.
              double *double_var;  Pointer to double variable to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the double variable should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_double(window,2,1,"Double:",&double_var,8,FALSE,".help_double",
              0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a double variable.
See Also....: g_float.
Example.....: Input a double floating point value.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              double double_var;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_double(window,0,1,"Double:",&double_var,8,FALSE,
                       ".double_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %f\n",double_var);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_extdate.
Purpose.....: Get a date, including the century.
Syntax......: int  g_extdate(WIN_PTR window,int row,int col,char *prompt,
                   W_DATE *ext_date,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              W_DATE *ext_date;    Pointer to date to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the date should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_date(window,2,1,"Date:",&ext_date,FALSE,".help_date",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a date variable, including the century.
See Also....: g_date,
              g_exttime,
              g_time.
Example.....: Input a date, including the century.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_DATE  ext_date;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_extdate(window,0,1,"Date:",&ext_date,FALSE,
                        ".extdate_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",d_extdatestr(ext_date));
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_exttime.
Purpose.....: Get a time, including the seconds.
Syntax......: int  g_exttime(WIN_PTR window,int row,int col,char *prompt,
                   W_TIME *ext_time,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              W_TIME *ext_time;    Pointer to time to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the time should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_time(window,2,1,"Time:",&ext_time,FALSE,".help_time",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a time variable, including the seconds.
See Also....: g_date,
              g_extdate,
              g_time.
Example.....: Input a time, including the seconds.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_time  ext_time;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_exttime(window,0,1,"time:",&ext_time,FALSE,
                        ".exttime_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",d_exttimestr(ext_time));
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_extzip.
Purpose.....: Get a 5 digit zip code, including the 4  digit extension.  Since
              the  extended zip code  consists  of 9 digits, a dash and a NULL
              character, you're extended  zip code variables  should always be
              declared for at least 11 characters.
Syntax......: int  g_extzip(WIN_PTR window,int row,int col,char *prompt,
                   char *ext_zip,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *ext_zip;       Pointer to zip code to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the zip code should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_extzip(window,2,1,"Zip Code:",&ext_zip,FALSE,".help_zip",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a 5 digit zip code, including the 4 digit extension.
See Also....: g_zip.
Example.....: Input a 5 digit zip code, including the 4 digit extension.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    ext_zip[11];

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_extzip(window,0,1,"Zip:",ext_zip,FALSE,".extzip_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",ext_zip);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_filename.
Purpose.....: Get a file name.
Syntax......: int  g_filename(WIN_PTR window,int row,int col,char *prompt,
                   char *file,int max_char,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *file;          File name to be edited
              int max_char;        Number of characters to allow for file name
                                   Max_char must be  1
              int disp_flag;       TRUE\FALSE flag indicating if initial file
                                   name should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_filename(window,2,1,"File:",file,70,FALSE,".help_file",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a file name.
See Also....: g_string,
Example.....: Ask the user to enter a file name, and then try to open the file
              for reading.

              #include <stdio.h>
              #include "user_int.h"
              void main(void)
              {
              FILE *handle;
              WIN_PTR window;
              char file_name[80];

              w_init();
              window=w_open(5,2,1,75,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_filename(window,0,1,"file:",file_name,65,FALSE,
                        ".file_input",0);
              g_read();
              g_close();
              w_close(window);

                                                     6 - Data Entry



              if (w_lastkey!=ESC)
              {
                  v_prtf("User entered %s\n",file_name);
                  handle=f_open(file_name,"r");
                  if (!handle)
                      w_errbox(0,"Unable to open file.");
                  else
                  {
                      v_prtf("File opened for reading.\n");
                      fclose(handle);
                  }
              }
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_float.
Purpose.....: Get a floating point value.
Syntax......: int  g_float(WIN_PTR window,int row,int col,char *prompt,
                   float *float_var,int max_char,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              float *float_var;    Pointer to floating point value to be edited
              int max_char;        Number of characters to allow for editing.
                                   Max_char must be  1 and  12.
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the floating point variable should be
                                   displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_float(window,2,1,"Float:",&float_val,FALSE,".help_float",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a floating point value.
See Also....: g_double.
Example.....: Input a floating point value.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              float   float_var;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_float(window,0,1,"Float:",&float_var,7,FALSE,".float_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %f\n",float_var);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_int.
Purpose.....: Get an integer value.
Syntax......: int  g_int(WIN_PTR window,int row,int col,char *prompt,
                   int *int_var,int max_char,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              int *int_var;        Pointer to integer value to be edited
              int max_char;        Number of characters to allow for editing.
                                   Max_char must be  1 and  6
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the integer variable should be displayed.
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_int(window,2,1,"Integer:",&int_val,FALSE,".help_int",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in an integer value.
See Also....: g_long,
              g_unint,
              g_unlong;
Example.....: Input an integer value.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              int     int_var;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_int(window,0,1,"Integer:",&int_var,7,FALSE,".int_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %d\n",int_var);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_long.
Purpose.....: Get a long integer value.
Syntax......: int  g_long(WIN_PTR window,int row,int col,char *prompt,
                   int *long_var,int max_char,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              long *long_var;      Pointer to long integer value to be edited
              int max_char;        Number of characters to allow for editing.
                                   Max_char must be  1 and  11
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the long integer value should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_long(window,2,1,"Long Int:",&long_val,FALSE,".help_long",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a long integer value.
See Also....: g_int,
              g_unint,
              g_unlong;
Example.....: Input a long integer value.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              long    long_var;

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_long(window,0,1,"Long Integer:",&long_var,7,FALSE,
                   ".long_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %ld\n",long_var);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry




Function....: g_password.
Purpose.....: Get a password.  The password entered by the user is not echoed
              to the screen.
Syntax......: int  g_password(WIN_PTR window,int row,int col,char *prompt,
                   char *password,int max_char,char *help_word,
                   int (*valid)(void));
               WIN_PTR window;       Window in which to enter password
               int row;              row in window to get password
               int col;              column in window where prompt will start
               char *prompt;         Prompt for password
               char *password;       password
               int max_char;         Maximum number of characters in password
               char *help_word;      Help word to provide context sensitive help
                                     when F1 key is pressed
               int (*valid)(void);   Valid function.  Password lookup.
Example call: g_password(window,0,1,"Password:",password,15,".password_help",
              password_check);
Returns.....: TRUE\FALSE indicating whether the get was set.
Common Use..: Protect programs and data from unauthorized users.
See Also....: None.
Example.....: Ask the user to enter a password. If it doesn't match, exit the
              program, otherwise allow the user to continue. In this example,
              pretend the password is "Marsupial". Also,we are using a custom
              valid function here, which looks up the password entered by the
              user, and checks if it matches.


              #include <string.h>
              #include "user_int.h"
              #define   NUM_USERS 4
              int (*check_password)(void);

              struct SECURITY
              {
                 char name[10];
                 char password[10];
              };
              struct  SECURITY list[NUM_USERS] /* List of 4 users and their  */
            ={{"Joneric","hello"},             /* passwords                  */
              {"Tia"    ,"dog"  },
              {"Uwe"    ,"pencil"},
              {"Nord"   ,"book"}};

                                                     6 - Data Entry






              void main(void)
              {
              WIN_PTR window;                  /*                            */
              char    pass[10];                /*                            */
              char    user[10];

              w_init();
              window=w_open(5,5,2,40,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_string  (window,0,1,"User....:",user,9,0,0,0);
              g_password(window,1,1,"Password:",pass,9,0,check_password);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey==ESC)
                  v_prtf("User pressed ESC.\n");
              else
                  v_prtf("User entered correct password.\n");
              k_wait(0);
              w_end();
              }

              int check_password(void)
              {
              int i;
              char user_name[10],
                   user_pass[10];

              if (w_lastkey==ESC) return(TRUE);
              strcpy(user_name,(char *)w_get.get[0]->edit_var;
              strcpy(user_pass,(char *)w_get.get[1]->edit_var;
              for(i=0;i<NUM_USERS;++i) /* Check against master list */
                  if (!strcmp(list[i].name,user_name) &&
                     (!strcmp(list[i].pass,user_pass))
                     return(TRUE);

              w_errbox(0,"Invalid password.  Access denied.");
              return(FALSE);
              }
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_phone.
Purpose.....: Get a  phone  number.  Since a  phone  number  consists  of  two
              parentheses, 10  digits, a  dash, a  space  and a NULL character,
              you're phone number variables should be declared for at least 15
              bytes.
Syntax......: int  g_phone(WIN_PTR window,int row,int col,char *prompt,
                   char *phone,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *phone;         Pointer to phone number to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the phone number value should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_phone(window,2,1,"Phone:",phone,FALSE,".help_phone",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a phone number.
See Also....: None.
Example.....: Input a phone number.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    phone[15];

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_phone(window,0,1,"Phone Number:",phone,FALSE,".phone_input",
                      0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",phone);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_read.
Purpose.....: Read all pending gets.
Syntax......: void g_read(void);
Example call: g_read();
Returns.....: None.  If user presses Page  Down or  if on the last get, Enter,
              all valid functions for all gets will be executed.  If any valid
              fails, the cursor will be positioned on the  failed get.  If all
              valids return TRUE, then and only then will the original variab-
              les be updated.  If the  user pressed Esc, the variables  remain
              unchanged.
Common Use..: Edit all pending gets.
See Also....: g_close.
Example.....: Set up some gets and then read (edit) them.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              int   integer;
              char  ch;
              char  phone[15];

              w_init();
              window=w_open(5,5,3,40,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_int(window,0,1,"Number:",&integer,FALSE,3,0,0);
              g_char(window,1,1,"Character:",&ch,FALSE,0,0);
              g_phone(window,2,1,"Phone:",&phone,FALSE,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered:\n %d\n %c\n %s\n",integer,ch,phone);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_socsec.
Purpose.....: Get a  social  security  number.  Since a social security number
              consists of 2 dashes, 9 digits and a NULL character, your social
              security number  variables  should be  declared  for at least 12
              bytes.
Syntax......: int  g_socsec(WIN_PTR window,int row,int col,char *prompt,
                   char *soc_sec,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *soc_sec;       Pointer to soc. sec. number to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the soc. sec. number value should be
                                   displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_socsec(window,2,1,"Prompt:",soc_sec,FALSE,".help_soc_sec",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a soc. sec. number.
See Also....: None.
Example.....: Input a soc. sec. number.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    soc_sec[12];

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_socsec(window,0,1,"Soc. Sec. Number:",soc_sec,FALSE,
                     ".soc_sec_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",soc_sec);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_string.
Purpose.....: Get a string.
Syntax......: int  g_string(WIN_PTR window,int row,int col,char *prompt,
                   char *string,int max_char,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *string;        Pointer to string to be edited
              int max_char;        Number of characters to allow for editing
                                   Max_char must be  1
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the string value should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_string(window,2,1,"String:",string,FALSE,".help_string",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a string.
See Also....: None.
Example.....: Input a string.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    string[50];

              w_init();
              window=w_open(5,5,1,70,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_string(window,0,1,"String:",string,FALSE,".string_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",string);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_tf.
Purpose.....: Get a TRUE\FALSE answer.
Syntax......: int  g_tf(WIN_PTR window,int row,int col,char *prompt,
                   char *t_f,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *t_f;           Pointer to TRUE\FALSE char to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the TRUE\FALSE char  should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_tf(window,2,1,"TRUE\FALSE:",&t_f,FALSE,".help_tf",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a TRUE\FALSE response.
See Also....: None.
Example.....: Input a TRUE\FALSE response.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    t_f;

              w_init();
              window=w_open(5,5,1,70,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_tf(window,0,1,"True\\False:",&t_f,FALSE,".t_f_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %c\n",t_f);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_time.
Purpose.....: Get a time, excluding the seconds.
Syntax......: int  g_time(WIN_PTR window,int row,int col,char *prompt,
                   W_TIME *time,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              W_TIME *time;        Pointer to time to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the time should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_time(window,2,1,"Time:",&time,FALSE,".help_time",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a time, excluding the seconds.
See Also....: None.
Example.....: Input a time, excluding seconds.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_TIME  time;

              w_init();
              window=w_open(5,5,1,70,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_time(window,0,1,"Time:",&time,FALSE,".time_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",t_timestr(time));
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_unchar.
Purpose.....: Get an unsigned character.
Syntax......: int  g_unchar(WIN_PTR window,int row,int col,char *prompt,
                   unsigned char *unchar_var,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              unsigned char *ch;   Pointer to unsigned char to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the  unsigned char  should be  displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_unchar(window,2,1,"Unsigned Char:",&unch,FALSE,".help_char",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in an unsigned char.
See Also....: None.
Example.....: Input an unsigned char.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              unsigned char ch;

              w_init();
              window=w_open(5,5,1,70,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_unchar(window,0,1,"Unsigned Char:",&ch,FALSE,".char_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %uc\n",ch);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_unint.
Purpose.....: Get an unsigned integer.
Syntax......: int  g_unint(WIN_PTR window,int row,int col,char *prompt,
                   unsigned int *unint_var,int max_char,int disp_flag,
                   char *help_word,int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              unsigned int *unint; Pointer to unsigned integer to be edited
              int max_char;        Number of characters allowed for edit
                                   Max_char must be  1 and  5
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the  unsigned int  should  be  displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_unint(window,2,1,"Unsigned Int:",&un_int,FALSE,".help_int",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in an unsigned int.
See Also....: None.
Example.....: Input an unsigned int.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              unsigned int un_int;

              w_init();
              window=w_open(5,5,1,70,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_unint(window,0,1,"Unsigned Int:",&un_int,FALSE,
                    ".un_int_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %ud\n",un_int);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_unlong;
Purpose.....: Get an unsigned long integer.
Syntax......: int  g_unlong(WIN_PTR window,int row,int col,char *prompt,
                   unsigned long int *un_long_int_var,int max_char,
                   int disp_flag,char *help_word,int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              unsigned long *unlng;Pointer to unsigned long integer to be edited
              int max_char;        Number of characters allowed for edit
                                   Max_char must be  1 and  10
              int disp_flag;       TRUE\FALSE flag indicating if initial  value
                                   of the unsigned long int should be displayed
              char *help_word;     Help word to provide context  sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_unlong(window,2,1,"Unsigned Long:",&un_long,FALSE,".help_long",
                       0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in an unsigned long int.
See Also....: None.
Example.....: Input an unsigned long int.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              unsigned long int un_long;

              w_init();
              window=w_open(5,5,1,70,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_unlong(window,0,1,"Unsigned Long:",&un_long,FALSE,
                    ".un_long_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %uld\n",un_long);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_yn.
Purpose.....: Get a Yes\No answer.
Syntax......: int  g_yn(WIN_PTR window,int row,int col,char *prompt,
                   char *y_n,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             Row in window to place get
              int col;             Column in window where prompt will start
              char *prompt;        Prompt
              char *y_n;           Pointer to Yes\No char to be edited
              int disp_flag;       Yes\No flag indicating if the initial value
                                   of the  Yes\No  char  should  be  displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_yn(window,2,1,"Yes\\No:",&y_n,FALSE,".help_yn",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a Yes\No response.
See Also....: None.
Example.....: Input a Yes\No response.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    y_n;

              w_init();
              window=w_open(5,5,1,70,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_yn(window,0,1,"Yes\\No:",&y_n,FALSE,".y_n_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %c\n",y_n);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     6 - Data Entry



Function....: g_zip.
Purpose.....: Get a 5 digit zip code, excluding the 4 digit extension.  Since
              the zip code consists  of 5 digits and a NULL character, you're
              zip code variables should be declared for at least 6 characters.
Syntax......: int  g_zip(WIN_PTR window,int row,int col,char *prompt,
                   char *zip,int disp_flag,char *help_word,
                   int (*valid)(void));
              WIN_PTR window;      Window in which get takes place
              int row;             row in window to place get
              int col;             column in window where prompt will start
              char *prompt;        Prompt
              char *zip;           Pointer to zip code to be edited
              int disp_flag;       TRUE\FALSE flag indicating if initial value
                                   of the zip code should be displayed
              char *help_word;     Help word to provide context sensitive help
                                   when F1 key is pressed
              int (*valid)(void);  Valid function
Example call: g_zip(window,2,1,"Zip:",&zip,FALSE,".help_zip",0);
Returns.....: TRUE\FALSE flag indicating whether the get was set or not.
Common Use..: Read in a 5 digit zip code.
See Also....: g_extzip.
Example.....: Input a 5 digit zip code, excluding the 4 digit extension.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    zip[6];

              w_init();
              window=w_open(5,5,1,30,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              g_zip(window,0,1,"Zip:",zip,FALSE,".zip_input",0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("User entered %s\n",zip);
              else
                 v_prtf("User pressed Esc.");
              w_exit(0);
              }

                                                     7 - Keyboard



                                  Chapter 7

                                  Keyboard



                                                     7 - Keyboard



    Overview

    Determining  what key was  pressed is a function used  in nearly all modern
applications.  Most  programmers  need to interact with  the keyboard much more
closely than is provided by the standard C Library. This collection of keyboard
routines will allow  you to access the keyboard  very easily and should fulfill
all your keyboard needs.


    Concepts

    The keyboard is controlled by the BIOS.  There are two keyboard interrupts,
an interrupt service routine (ISR) and a Device Service Routine (DSR).  The ISR
is invoked by hardware interrupt 09h, which occurs every time a key is pressed.
The DSR is invoked by software interrupt 16h.
    Int 09h  is invoked  each time a key is pressed or released.  On IBM PC and
PC/XT  compatibles, the  Intel 8255A-5 generates an IRQ1 which invokes BIOS int
09h.  On IBM  PC/AT and  compatibles, the  Intel  8042  generates an IRQ1 which
invokes  BIOS Int 09h.  However, because of  differences  between the PC, PC/XT
and PC/AT  keyboards, firmware resident in the Intel 8042 additionally converts
the AT  key codes  into System  Scan codes which are compatible with those pro-
duced by the PC and PC/XT.   Next, if the key pressed was a shift flag, ie, one
of the  following keys, Shift, Caps Lock, Num  Lock, Scroll Lock, Ctrl, Alt, or
Insert,two bytes in the ROM BIOS Data Area, located at 0040:0017 and 0040:0018,
are updated.  Then, certain key sequences, such as Ctrl-Alt-Del, are translated
into  internal  system  requests which are  processed by Int 09h.  Finally, all
other key codes are converted into a 2 byte sequence, which we know as the scan
code and ascii  value.  All special keys, such as the function  keys, who don't
have an  ascii value, have their  ascii value set to 0.  The 2 byte sequence is
then placed in the keyboard buffer.  The keyboard buffer is a 16 word(32 bytes)
circular  buffer used to store the 2 byte codes, and is located in the ROM BIOS
Data Area at 0040:001E.  Associated with  the buffer are 2 pointers, located at
0040:001A and 0040:001C, which contain the starting and ending addresses of the
buffer.  The 1st pointer, at 0040:001A, points to the key  in the  buffer which
will be returned  the next time the BIOS (int 16h) requests a key from the key-
board.  The 2nd pointer, at 0040:001C, points to  the place in the buffer where
the next key will be stored when a key is pressed.  These pointers always point
to a location inside the keyboard buffer (0040:001E - 0040:003C).  The keyboard
buffer  can be  relocated and  enlarged so that it can buffer more than  16 key
strokes, but that is  beyond the scope of this discussion.  When the 2 pointers
are  equal, the buffer is empty, and  when the  2nd pointer is logically 1 less
than the 1st, the buffer is full.
    Now that  the key  presses are in the keyboard buffer, we need a way to get
them out.  The DSR, which uses Int 16h, does just that.  To read a key from the
buffer, Int 16h uses service 00h, which gets the next available key. That's all
there is to it.

                                                     7 - Keyboard



                         Function List


       Routine           Description
                  
       k_beep            Sound a short beep
       k_flush           Clear the keyboard buffer
       k_getkey          Read  a key from the keyboard buffer
       k_putkey          Place a key into the keyboard buffer
       k_set             Assign a routine to a function key
       k_status          Get the status of the keyboard shift flags
       k_wait            Suspend processing until a key is pressed


                                                     7 - Keyboard



Function....: k_beep.
Purpose.....: Sound a short  beep.  If sound is  on, ie, the global variable
              w_sound is TRUE, k_beep() will produce a short beep.  If sound
              is off, ie, w_sound is FALSE, then  we assume the user doesn't
              want  to hear any beeps and therefore k_beep() will ignore the
              command.
Syntax......: void k_beep(void);
Example call: k_beep();
Returns.....: None.
Common Use..: Alert a user to an error or to prompt for input.
See Also....: None.
Example.....: Ask the user to input  an integer between 1 and 10.  Sound a beep
              to let the user know that input  is expected.  If the input value
              is  outside 1 - 10 range, sound another beep and display an error
              message.

              #include "user_int.h"
              void main(void)
              {
              int value;
              WIN_PTR window;

              w_init();
              window=w_open(5,5,1,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_int(window,0,0,"Number:",&value,2,FALSE,0,0);
              k_beep();
              g_read();
              g_close();
              w_close(window);
              if (value<1 || value >10)
              {
                  k_beep();
                  w_errbox(0,"You must enter a number between 1 and 10.");
              }
              w_exit(0);
              }
                                                     7 - Keyboard



Function....: k_flush.
Purpose.....: Flush the keyboard buffer.
Syntax......: void k_flush(void);
Example call: k_flush();
Returns.....: None.
Common Use..: Clear any pending key strokes so that data input starts clean.
See Also....: k_putkey,
              k_getkey.
Example.....: Ask the user if he wants to print some keystrokes or to clear the
              buffer.  If yes, display "Hello" by stuffing keystrokes into  the
              keyboard.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              if ('Y'==w_ynbox("Would you like to see the keystrokes",0))
              {
                  k_putkey('H');
                  k_putkey('e');
                  k_putkey('l');
                  k_putkey('l');
                  k_putkey('o');
                  while (kbhit())
                         v_prtf("%c",k_getkey());
              }
              else
                 k_flush();
              k_wait(0);
              w_exit(0);
              }
                                                     7 - Keyboard



Function....: k_getkey.
Purpose.....: Remove a key  from the  keyboard buffer. w_keybrd.h contains a
              comprehensive list of the keyboard character codes returned by
              k_getkey.
Syntax......: unsigned int k_getkey(void);
Example call: key=k_getkey();
Returns.....: keystroke character code.
Common Use..: Get a single keystroke or to wait until the user presses a key.
See Also....: k_putkey,
              k_flush.
Example.....: Ask the user to press a function key and then tell him what
              key was pressed.

              #include "user_int.h"
              void main(void)
              {
              unsigned int key;

              w_init();
              v_prtf("Press any function key.");
              key=k_getkey();
              if (key>=F1 && key<=F9)
                  v_prtf("You pressed F%d",'1'+key-F1);
              else if (key==F10)
                  v_prtf("You pressed F10");
              else if (key==F11 || key==F12)
                  v_prtf("You pressed F1%d",'1'+key-F11);
              else
                  v_prtf("You did not press a Function key.");
              w_exit(0);
              }
                                                     7 - Keyboard



Function....: k_putkey.
Purpose.....: Stuff a key into the keyboard buffer
Syntax......: void k_putkey(unsigned int key);
              unsigned int key;    Character code of key to place into keyboard
                                   buffer
Example call: k_putkey('A');
Returns.....: None
Common Use..: Automate  a function.  This  function  allows you  to simulate a
              process of keystrokes.  w_keybrd.h contains a comprehensive list
              of the keyboard character codes.
See Also....: k_getkey,
              k_flush.
Example.....: Suppose a program always makes  you type in your name to start
              the program.  You could save yourself the trouble of having to
              do that by using k_putkey() to type your name for you.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    name[31];

              w_init();
              window=w_open(5,5,1,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              k_putkey('R');
              k_putkey('a');
              k_putkey('l');
              k_putkey('p');
              k_putkey('h');           /* When g_read goes to read your name */
              k_putkey(ENTER);         /* it will already have been entered  */

              g_string(window,0,0,"Name:",&name,30,FALSE,0,0);
              g_read();
              g_close();
              w_close(window);
              w_exit(0);
              }

                                                     7 - Keyboard



Function....: k_set.
Purpose.....: Assign a  routine to  a function  key.  Once  you've  assigned  a
              routine to a particular function key, then whenever that function
              key is pressed, the assigned routine will be executed.  Thus, you
              are setting up a function key as a "hot" key.  By default, w_help
              is assigned to the  F1 key.  The other 9  function keys (11 on an
              101 keyboard)are assigned to k_fun_def,which is a default routine
              that simply beeps and returns. The assigned routine may be called
              at any time during a wait state,ie, during a get, a menu, a read,
              or k_wait.  When you no longer want the routine to be linked with
              the function key, you call  k_set with a 0  instead of a  routine
              name.  This resets  the function key to be linked back to the de-
              fault routine.  The assigned routine takes 4  parameters. The 1st
              is the type.  This tells  you from where your assigned routine is
              being called. The five types are listed in w_keybrd.h. They  are:

              K_MENU        From inside m_menu()
              K_READ        From inside g_read()
              K_WAIT        From inside k_wait()
              K_SCRL        From inside m_scrollmenu()
              K_EDIT        From inside f_edit()

              The 2nd  parameter is a  void pointer which  must be type cast to
              the correct  type depending on  the value of the  1st  parameter.
              For example,if type is K_MENU, then the void pointer, ptr, should
              be type cast to be a pointer to a  MENU.  Only the K_MENU, K_SCRL
              and the K_EDIT types void pointer should be  type cast.  The void
              pointer has no meaning for either the K_READ or the K_WAIT types,
              and will be 0.  The type casts for the K_MENU, K_SCRL, and K_EDIT
              types  and  shown below.

              K_MENU    men_ptr=(MEN_PTR)ptr;
              K_SCRL    scrl_ptr=(char *)ptr;
              K_EDIT    scrn_ptr=(char **)ptr;

              In K_READ, since all get variables  are global, you have complete
              access to any part of the GET structure through the w_get global.
              K_WAIT is simply a loop waiting for the user  to press a key or a
              mouse button, and hence you don't have access to any data.  Thus,
              the void pointer is set to 0 in  these two cases.  In the K_MENU,
              K_SCRL, and K_EDIT types,the data relevant to each routine is not
              global.  This is why you are passed a void pointer to them.  Once
              you  type cast the void pointer, you gain full access to the data
              provided by each function.  The 3rd parameter, indx, is the index
              of the current item. In K_MENU types,  this is the  currently hi-
              lited menu item.  In K_READ types, this is the current  get (same
              as the global w_get.cur_get). In K_WAIT,this value has no meaning
              and is set to 0.  In  K_SCRL, this value, like K_MENU, is set  to
              the currently  hi lited item.

                                                     7 - Keyboard


              In K_EDIT, the index  parameter is set to the current  row of the
              file.  The current column is not passed and hence is unknown. The
              4th parameter, help word, is the  help word  associated  with the
              current menu item or get.  For K_EDIT, it is the help word assoc-
              iated with the file.  For  K_WAIT types, this is set to a default
              help word. k_set allows you to set the help key to a function key
              other than F1.  However, the F1 key must be the help key while in
              f_edit.  Your programs may crash if it is not.
Syntax......: void k_set(unsigned int key,void (*k_fun)(int type,void *ptr,
                         int indx,char *help_word));
              unsigned int key;    Character  code of the  function  key  to be
                                   used as a hot  key to invoke  the associated
                                   routine.
              void (*k_fun)        Pointer to a void  function which takes four
              (int type,void *ptr, arguments
              int indx,char *help_word));
Example call: k_set(F2,my_F2_function);
Returns.....: None.
Common Use..: Used as hook  into the menu  and read functions.  Can be  used to
              provide  services to a user while  inside a menu, read, or  wait.
See Also....: None.
Example.....: A pseudo  "standard"  has developed  over the year  for assigning
              routines to  function keys.  F1  is always the Help key.  F10  is
              often used to exit a program. F2 can be used to display picklists
              for reads, etc.  Let's implement an F10 routine that will let the
              user exit the program whenever he wants, and  an F2 routine  that
              will provide a  picklist of 5 names.  We'll do a read in order to
              have a  wait state.  Then, at any time  during the read, the user
              may press the F2 or F10 key to execute their respective routines.
              By default, F1 is set up as the help key by w_init().

              #include "user_int.h"
              void main(void);
              void  F2_function(int type,void *ptr,int indx,char *help_word);
              void F10_function(int type,void *ptr,int indx,char *help_word);

                                                     7 - Keyboard



              /*
              Ŀ
               F2_function                                          
              
              */
              void  F2_function(int type,void *ptr,int indx,char *help_word)
              {
              int sel;
              MEN_PTR  name_ptr=0;
              MEN_ITEM name_items[5]={{0,0,"Howard ",0,1},
                                      {0,0,"Rebecca",0,1},
                                      {0,0,"Cathy  ",0,1},
                                      {0,0,"Dave   ",0,1},
                                      {0,0,"Janine ",0,1}};

              sel=m_menu(15,20,5,7,M_VERT,M_BORDER,w_shadows,M_CLOSE,
                         w_color_menu,5,0,&name_ptr,name_items);

              if (sel!=-1)
                  strcpy(w_get.get[w_get.cur_get]->edit_var,
                         name_items[sel].text);
              }
              /*
              Ŀ
               F10_function                                         
              
              */
              void  F10_function(int type,void *ptr,int indx,char *help_word)
              {
              switch (type)
              {
                 case K_MENU:
                      v_prtf("F10 function called from m_menu().\n");
                      v_prtf("Menu structure: %p\n",(MEN_PTR)ptr);
                 break;
                 case K_READ:
                      v_prtf("F10 function called from g_read().\n");
                 break;
                 case K_WAIT:
                      v_prtf("F10 function called from k_wait().\n");
                 break;
                 case K_SCRL:
                      v_prtf("F10 function called from m_scrollmenu().\n");
                      v_prtf("Scroll Menu items: %p\n",(char *)ptr);
                 break;
              }
              v_prtf("Index: %d\n",indx);
              v_prtf("Help word: %s\n",help_word);
              k_wait(0);
              w_exit(0);               /* Exit program                    */
              }

                                                     7 - Keyboard




              /*
              Ŀ
               Main                                                 
              
              */
              void main(void)
              {
              char     name[21];
              WIN_PTR  window;
              w_init();
              k_set(F2,F2_function);   /* Assign  F2_function to F2 key   */
              k_set(F10,F10_function); /* Assign F10_function to F10 key  */
              window=w_open(5,5,1,30,TRUE,w_shadows,w_color_data,0);
              if (!window) w_exit(1);
              g_string(window,0,0,"Name:",&name,20,FALSE,0,0);
              g_read();
              g_close();
              w_close(window);
              k_set(F2,0);             /* Release  F2 function from F2  key*/
              k_set(F10,0);            /* Release F10 function from F10 key*/
              w_exit(0);
              }

                                                     7 - Keyboard



Function....: k_status.
Purpose.....: Test the state of the shift flags.
Syntax......: int k_status(int Shift_flag);
              int Shift_flag;      Bit pattern of Shift flag to test for
Example call: value=k_status(INSERT);
Returns.....: TRUE or FALSE.
See Also....: None.
Common Use..: Test  whether  a Shift  flag is currently  pressed  or  has been
              toggled on.  The shift flags are comprised of the following keys:

              Insert
              Alt
              Ctrl
              Scroll
              Lock
              Caps Lock
              Num Lock
              Left Shift
              Right Shift

              The values used to test each shift flag are listed in w_keybrd.h.
Example.....: Many text  editors display a big  fat cursor  when in insert mode
              and a thin underline  cursor when in  edit mode.  This is done by
              controlling  how many scan  lines are used to display the cursor.
              The top of the cursor is line 0 and depending on the monitor type
              (CGA,EGA,VGA,etc), the bottom line is 8,14,etc.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (k_status(INSERT))    /* If in insert mode                  */
                  v_setcurtype(0,7);   /* Use 8 scan lines for a big cursor  */
              else
                  v_setcurtype(6,7);   /* Use 1 scan line for a thin cursor  */
              w_exit(0);
              }
                                                     7 - Keyboard



Function....: k_wait.
Purpose.....: Wait for a user to press any key or, if a mouse is present, for
              any mouse button click.  The "help_word" parameter can be one
              of the following:

              0.....: Uses "Press any key to continue" help text.
              1.....: Uses "Press any key to continue or ESC to quit" help text
              string: Your own help text
Syntax......: unsigned int k_wait(char *help_word);
              char *help_word;         Word used to  provide context  sensitive
                                       help while in k_wait
Example call: k_wait(0);   k_wait((char *)1);   k_wait(".Hello");
Returns.....: Key pressed.  Also sets w_lastkey global.
Common Use..: Display a message and then wait for the user to press any key to
              continue.
See Also....: None.
Example.....: Display a message and let the user read it.  When he's done,  he
              can press any key to clear the message and continue on,or ESC to
              quit.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,5,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              w_prtf(window,"This is a sample message.\n");
              w_prtf(window,"When you're done reading it\n");
              if (w_mouse.installed)
                  w_prtf(window,"Press any key or click a mouse button\n");
              else
                 w_prtf(window,"Press any key\n");
              w_prtf(window,"To continue.");
              k_wait(0);
              w_close(window);
              w_exit(0);
              }




                                                     8 - Cursor


                                  Chapter 8

                                   Cursor

                                                     8 - Cursor


    Overview

    C's printf  routine is  excellent  for printing  all sorts  of things,  from
integers  to unsigned  chars  to hexadecimal addresses of variables.  Similarly,
C's scanf performs the same wonders in reverse, allowing us to read in all sorts
of data types from the keyboard. However, after you've printed or read something
in, you are  moved to the next line, whether you want to go there or not.  Well,
say hello  to cursor  control.  These  routines  allow  you to  place the cursor
anywhere  on  the screen, to turn it on or off, and even to change what it looks
like.

    Concepts

    C  reads and writes like a teletype machine, ie, it moves from left to right
1 column at a time, and when it reaches the end, it moves down to the next line,
scrolling the data at the top off the screen and out of view. Also, the hardware
cursor  blinks.  There is no  way to  alter this.  It's built into the hardware,
and that's  the way it's  going to  stay.  The ROM BIOS allows you to access the
cursor  through the video  interrupt, Int 10h.  For most of the C User Interface
cursor functions, there is a routine for the screen cursor, and a  corresponding
routine for  use with a window. The function  pair are identical except that the
video  screen  functions, prefixed  with "v_", use coordinates  relative  to the
screen while the  corresponding window functions, prefixed with "w_", use coord-
inates relative  to the  window.  Neither  function pair  will let you specify a
cursor coordinate outside its allowed range. This means that you can not set the
cursor to  row 26 when  the video  screen has only  25 rows, and similarly, if a
window has only 10 columns, you can not place the cursor at column 11.
    The "v_" cursor functions use a  coordinate system with the origin 0,0 being
located  at the  upper left  hand corner  of the screen.  The coordinate  system
ranges from 0,0 to 24,79, located  in the bottom right hand corner.  This is the
standard  range, but this can  be made to vary  by setting the number of rows on
the screen to a value other than 24 with the w_setup() function.  Similarly, the
"w_" cursor functions use a coordinate system with  the origin 0,0 being located
in the  upper left hand  corner of the  window, and the lower  right hand corner
being the largest  possible coordinate.  For example, if you open a  window that
is 3 rows high and 10 columns wide, then the row  coordinates would range from 0
to 2 while the  column coordinates would range from 0 to 9. If you were to print
text within the window, any  text  that  excedes  the windows boundaries will be
ignored.
    There are a few globals associated with the cursor that the C User Interface
maintains.  They are:

    w_cur_row,
    w_cur_col,
    w_cursor.

    w_cur_row and w_cur_col  contain the row and column coordinate of the cursor
position, and  w_cursor  indicates  whether  the cursor is  on or off.  However,
w_cursor  is Read/Only and w_cur_row  and w_cur_col  are  only  available to the
programmer through  v_getcur().  Thus, none  of these  variables should  ever be
directly modified by you.  They are used internally by all the cursor functions.


                                                     8 - Cursor



                         Function List


       Routine           Description
                  
       v_curbak          Move the screen cursor 1 column to the left.
       v_curdn           Move the screen cursor down 1 row.
       v_curfwd          Move the screen cursor 1 column to the right.
       v_curoff          Turn cursor off.
       v_curon           Turn cursor on.
       v_curup           Move the screen cursor up 1 row.
       v_getcur          Get screen cursor location.
       v_setcur          Set screen cursor location.
       v_setcurtype      Set cursor shape.
       w_curbak          Move the window cursor 1 column to the left.
       w_curdn           Move the window cursor down 1 row.
       w_curfwd          Move the window cursor 1 column to the right.
       w_curup           Move the window cursor up 1 row.
       w_getcur          Get window cursor location.
       w_setcur          Set window cursor location.


                                                     8 - Cursor



Function....: v_curbak.
Purpose.....: Move the cursor 1 column to  the left.  If the  cursor is on the
              1st column, v_curbak is ignored.
Syntax......: int v_curbak(void);
Example call: v_curbak();
Returns.....: True\False flag indicating whether cursor was able to be moved.
Common Use..: If the user pressed the left arrow key, you want to move to the
              previous  column.  If  your are  on column 0, v_curbak  will be
              ignored.
See Also....: v_curfwd,
              v_curup,
              v_curdn,
              v_setcur,
              v_getcur.
Example.....: Every time the user presses the left arrow key, move 1 column to
              the left.


              #include "user_int.h"

              void main(void)
              {
              unsigned int key;

              w_init();
              v_curon();                    /* Turn cursor on               */
              v_setcur(2,79);               /* Start in column 79 of row 2  */
              do
              {
                key=k_getkey();             /* Wait for user to press a key */
                if (key==LT_ARROW) v_curbak();
              } while (key!=ESC);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: v_curdn.
Purpose.....: Move the cursor down 1 row.  If  the cursor  is on the last row,
              v_curdn is ignored.
Syntax......: int v_curdn(void);
Example call: v_curdn();
Returns.....: True\False flag indicating whether cursor was able to  be moved.
Common Use..: If the user pressed the down arrow key, you  want to move to the
              next row.  If your are on the last row, v_curdn will be ignored.
See Also....: v_curup,
              v_curfwd,
              v_curbak,
              v_setcur,
              v_getcur.
Example.....: Every time the user presses the down arrow key, move down 1 row.


              #include "user_int.h"

              void main(void)
              {
              unsigned int key;

              w_init();
              v_curon();                    /* Turn cursor on               */
              v_setcur(0,0);                /* Start at top of screen       */
              do
              {
                key=k_getkey();             /* Wait for user to press a key */
                if (key==DN_ARROW) v_curdn();
              } while (key!=ESC);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: v_curfwd.
Purpose.....: Move the cursor 1 column to the right.  If the cursor  is on the
              last column, v_curfwd is ignored.
Syntax......: int v_curfwd(void);
Example call: v_curfwd();
Returns.....: True\False flag indicating whether cursor was able to  be moved.
Common Use..: If the user pressed the right arrow key, you want to move to the
              next column.  If the cursor is in the last column on the screen,
              v_curfwd is ignored.
See Also....: v_curlft,
              v_curup,
              v_curdn,
              v_setcur,
              v_getcur.
Example.....: Every time the user presses the right arrow key, move 1 column to
              the right.


              #include "user_int.h"

              void main(void)
              {
              unsigned int key;

              w_init();
              v_curon();                    /* Turn cursor on               */
              v_setcur(2,0);                /* Start at left hand side of   */
              do                            /* screen.                      */
              {
                key=k_getkey();             /* Wait for user to press a key */
                if (key==RT_ARROW) v_curfwd();
              } while (key!=ESC);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: v_curoff.
Purpose.....: Turn the cursor off.  The global w_cursor  is set to FALSE.  The
              cursor need not  be on to  reposition  it somewhere  else on the
              screen.
Syntax......: void v_curoff(void);
Example call: v_curoff();
Returns.....: None.
Common Use..: Turn the cursor off.
See Also....: v_curon.
Example.....: Except for  when data input is needed, there is no  reason for the
              cursor to be on. But for our example,  lets turn the cursor on and
              print some text, and then  turn the cursor off and print some more
              text.


              #include "user_int.h"

              void main(void)
              {
              w_init();
              v_curon();                    /* Turn cursor on               */
              v_setcur(20,20);              /* New cursor position          */
              v_prtf("Hello World.");       /* Print a message at new locat */
              v_curoff();                   /* Turn cursor off              */
              v_setcur(15,0);               /* New cursor position          */
              v_prtf("Hello World.");       /* Print a message at new locat */
              w_exit(0);
              }
                                                     8 - Cursor



Function....: v_curon.
Purpose.....: Turn the cursor on.  The global w_cursor is set to TRUE;
Syntax......: void v_curon(void);
Example call: v_curon();
Returns.....: None.
Common Use..: Turn the cursor on.
See Also....: v_curoff.
Example.....: See v_curoff example.

                                                     8 - Cursor



Function....: v_curup.
Purpose.....: Move  the  cursor up  1  row.  If the  cursor is on the 1st row,
              v_curup is ignored.
Syntax......: int v_curup(void);
Example call: v_curup();
Returns.....: True\False flag  indicating whether cursor was able to be moved.
Common Use..: If the user pressed the up  arrow key, you  want to  move to the
              previous row.  If your  are on row 0, v_curup() will be ignored.
See Also....: v_curdn,
              v_curfwd,
              v_curbak,
              v_setcur,
              v_getcur.
Example.....: Every time the user presses the up arrow key, move up 1 row.


              #include "user_int.h"

              void main(void)
              {
              unsigned int key;

              w_init();
              v_curon();                    /* Turn cursor on               */
              v_setcur(24,0);               /* Start at the bottom of the   */
              do                            /* screen.                      */
              {
                key=k_getkey();             /* Wait for user to press a key */
                if (key==UP_ARROW) v_curup();
              } while (key!=ESC);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: v_getcur.
Purpose.....: Get the location of the cursor relative to the video screen.
Syntax......: void v_getcur(int *x,int *y);
              int *x;        Pointer to integer to return x coordinate
              int *y;        Pointer to integer to return y coordinate
Example call: v_getcur(&x,&y);
Returns.....: None.
Common Use..: Save  the current  cursor  position  so that it can  be restored
              later.
See Also....: v_setcur.
Example.....: Save the current cursor position, then display a line of text at
              another  screen  location, and then restore  the original cursor
              location.


              #include "user_int.h"

              void main(void)
              {
              int old_x,old_y;              /* Old cursor location          */

              w_init();
              v_getcur(&old_x,&old_y);      /* Save current cursor position */
              v_setcur(20,20);              /* New cursor position          */
              v_prtf("Hello World.");       /* Print a message at new locat */
              v_setcur(old_x,old_y);        /* Restore cursor position      */
              w_exit(0);
              }

                                                     8 - Cursor



Function....: v_setcur.
Purpose.....: Set the location of the cursor relative to the video screen.
Syntax......: void v_setcur(int x,int y);
              int x;         New row coordinate
              int y;         New column coordinate
Example call: v_setcur(20,12);
Returns.....: None.
Common Use..: Set the location where the next screen print will take place.
See Also....: v_getcur,
              v_curfwd,
              v_curbak,
              v_curup,
              v_cur_dn.
Example.....: Write a message at various screen locations.


              #include "user_int.h"

              void main(void)
              {
              w_init();
              v_setcur(20,20);              /* New cursor position          */
              v_prtf("Hello World.");       /* Print a message at new locat */
              v_setcur(0,15);               /* New cursor position          */
              v_prtf("Hello World.");       /* Print a message at new locat */
              v_setcur(18,0);               /* New cursor position          */
              v_prtf("Hello World.");       /* Print a message at new locat */
              w_exit(0);
              }

                                                     8 - Cursor



Function....: v_setcurtype
Purpose.....: Set the shape of the text mode cursor.  In text modes, the cursor
              hardware causes the cursor to blink.  The cursor is not available
              in graphics modes. On EGA,VGA, and MCGA, the BIOS provides cursor
              emulation.  This  treats  the cursor as an 8x8 cell, and maps the
              8x8 cell into the  appropriate  size (scan lines) for the corres-
              ponding monitor.
Syntax......: void v_setcurtype(int start,int end);
              int start;        Starting scan line
              int end;          Ending scan line
Example call: v_setcur(6,7);
Returns.....: None.
Common Use..: Toggle size  of cursor depending  on whether or not Insert is on.
See Also....: None.
Example.....: Make the cursor a box if insert is on.  Otherwise, make it a thin
              line.  This is actually part of the code for an internal function
              v_curinstoggle().


              #include "user_int.h"

              void main(void)
              {
              w_init();
              v_curon();               /* Turn cursor on             */
              if (k_status(INSERT))    /* If Insert is on            */
                  v_setcurtype(0,7);   /* Make it a big box          */
              else
                 v_setcurtype(6,7);    /* Make it a thin underscore  */
              w_exit(0);
              }

                                                     8 - Cursor



Function....: w_curbak.
Purpose.....: Move the cursor inside a window over 1 column to the left.  If
              the cursor  is on  the 1st  column  of the window, w_curbak is
              ignored.
Syntax......: int w_curbak(WIN_PTR window);
              WIN_PTR window;    Window in which to move cursor
Example call: v_curbak(window);
Returns.....: True\False flag indicating whether cursor was able to be  moved.
Common Use..: If the user pressed the left arrow key, you want  to move over 1
              column to  the  left.  If  your  are on the first column in  the
              window, w_curbak will be ignored.
See Also....: w_curup,
              w_curdn,
              w_curfwd,
              w_setcur,
              w_getcur.
Example.....: Move the cursor inside the window over 1 column to the left every
              time the left arrow key is pressed.


              #include "user_int.h"

              void main(void)
              {
              WIN_PTR window;
              unsigned int key;

              w_init();
              window=w_open(3,10,5,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              v_curon();                    /* Turn cursor on               */
              w_setcur(window,0,19);        /* Move cursor to the right side*/
              do                            /* of the window.               */
              {
                key=k_getkey();             /* Wait for user to press a key */
                if (key==LT_ARROW) w_curbak(window);
              } while (key!=ESC);
              w_close(window);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: w_curdn.
Purpose.....: Move the cursor inside a window down 1 row.  If the cursor is on
              the last row in the window, w_curdn is ignored.
Syntax......: int w_curdn(WIN_PTR window);
              WIN_PTR window;    Window in which to move cursor
Example call: v_curdn(window);
Returns.....: True\False flag indicating whether cursor was able to be moved.
Common Use..: If the user pressed the down arrow key, you want to move to the
              next row. If your are on the last row, w_curdn will be ignored.
See Also....: w_curup,
              w_curfwd,
              w_curbak,
              w_setcur,
              w_getcur.
Example.....: Move the cursor inside the window down 1 row every time the down
              arrow key is pressed.


              #include "user_int.h"

              void main(void)
              {
              WIN_PTR window;
              unsigned int key;

              w_init();
              window=w_open(3,10,5,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              v_curon();                    /* Turn cursor on               */
              do
              {
                key=k_getkey();             /* Wait for user to press a key */
                if (key==DN_ARROW) w_curdn(window);
              } while (key!=ESC);
              w_close(window);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: w_curfwd.
Purpose.....: Move the cursor  inside a window over 1 column to the right.  If
              the cursor  is on the  last  column  in the  window, w_curfwd is
              ignored.
Syntax......: int w_curfwd(WIN_PTR window);
              WIN_PTR window;    Window in which to move cursor.
Example call: v_curfwd(window);
Returns.....: True\False flag indicating whether cursor was able to be  moved.
Common Use..: If the user pressed the right arrow key, you want to move over 1
              column to  the  right.  If  your  are on the last column in  the
              window, w_curfwd will be ignored.
See Also....: w_curup,
              w_curdn,
              w_curbak,
              w_setcur,
              w_getcur.
Example.....: Move the cursor inside the window over 1 column to the right every
              time the right arrow key is pressed.


              #include "user_int.h"

              void main(void)
              {
              WIN_PTR window;
              unsigned int key;

              w_init();
              window=w_open(3,10,5,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              v_curon();                    /* Turn cursor on               */
              do
              {
                key=k_getkey();             /* Wait for user to press a key */
                if (key==RT_ARROW) w_curfwd(window);
              } while (key!=ESC);
              w_close(window);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: w_curup.
Purpose.....: Move the cursor inside a window up 1 row. If the cursor is on the
              1st row of in the window, w_curup is ignored.
Syntax......: int w_curup(WIN_PTR window);
              WIN_PTR window;    Window in which to move cursor
Example call: v_curup(window);
Returns.....: True\False flag indicating whether cursor was able to be  moved.
Common Use..: If  the user pressed  the  up arrow key, you want to move to the
              previous  row.  If  your are  on the  first row, w_curup will be
              ignored.
See Also....: w_curdn,
              w_curfwd,
              w_curbak,
              w_setcur,
              w_getcur.
Example.....: Move  the cursor  inside the window up 1 row every time the down
              arrow key is pressed.


              #include "user_int.h"

              void main(void)
              {
              WIN_PTR window;
              unsigned int key;

              w_init();
              window=w_open(3,10,5,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              v_curon();                    /* Turn cursor on                 */
              w_setcur(window,4,0);         /* Set cursor to bottom of screen */
              do
              {
                key=k_getkey();             /* Wait for user to press a key   */
                if (key==UP_ARROW) w_curup(window);
              } while (key!=ESC);
              w_close(window);
              w_exit(0);
              }

                                                     8 - Cursor



Function....: w_getcur.
Purpose.....: Get the location of the cursor relative to a window.
Syntax......: void v_getcur(WIN_PTR window,int *x,int *y);
Example call: w_getcur(window,&x,&y);
              WIN_PTR window; window to get cursor relative to.
              int *x;         Pointer to integer to return row coordinate
              int *y;         Pointer to integer to return column coordinate
Returns.....: None.
Common Use..: Save the current cursor position so that it can be restored later.
See Also....: w_setcur,
              w_curbak,
              w_curdn,
              w_curfwd,
              w_curup.
Example.....: Save the current cursor position, then display a line of text at
              another  window  location, and then restore  the original cursor
              location.


              #include "user_int.h"

              void main(void)
              {
              int old_x,old_y;                /* Old cursor location          */
              WIN_PTR window;                 /* Window                       */

              w_init();
              window=w_open(5,5,5,50,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);         /* Quit if no window            */
              w_getcur(window,&old_x,&old_y); /* Save current cursor position */
              w_setcur(window,2,20);          /* New cursor position          */
              w_prtf(window,"Hello World.");  /* Print a message at new locat */
              w_setcur(window,old_x,old_y);   /* Restore cursor position      */
              w_prtf(window,"Hello World.");  /* Print message at old locat   */
              w_close(window);                /* Close window                 */
              w_exit(0);
              }

                                                     8 - Cursor



Function....: w_setcur.
Purpose.....: Set the location of the cursor relative to a window.
Syntax......: void v_setcur(WIN_PTR window,int x,int y);
              WIN_PTR window; Window to get cursor relative to.
              int x;          Row coordinate
              int y;          Column coordinate
Example call: w_setcur(window,2,3);
Returns.....: None.
Common Use..: Set the position where the next window print (w_prtf) will start.
See Also....: w_getcur,
              w_curfwd,
              w_curbak,
              w_curup,
              w_curdn.
Example.....: Display a message at various locations within a window.


              #include "user_int.h"

              void main(void)
              {
              WIN_PTR window;                 /* Window                       */

              w_init();
              window=w_open(5,5,5,20,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);         /* Quit if no window            */
              w_setcur(window,2,15);          /* New cursor position          */
              w_prtf(window,"Hello World.");  /* Print a message at new locat */
              w_setcur(window,0,15);          /* New cursor position          */
              w_prtf(window,"Hello World.");  /* Print message at old locat   */
              w_close(window);                /* Close window                 */
              w_exit(0);
              }

                                                     9 - Time


                                  Chapter 9

                                    Time



                                                     9 - Time


    Overview

    The computer  uses time  in various  ways.  It uses the oscillating crystal
frequency  to generate the operating  speed of the  cpu, the bus  speed, and to
decrement counts held in timer chip registers.  It uses time to generate a BIOS
timer tick every 55 ms.  It also keeps track of the  current time  and also the
date. However, the time scale used by computers is much smaller than is  useful
for  the average  human.  We like things  in hours and  minutes, and once  in a
while, we need the seconds also.


    Concepts

    The C User Interface time  routines  are all based  on the W_TIME structure
defined in w_time.h.  This structure is shown below:

typedef struct
{
    unsigned hours,
             minutes,
             seconds;
    char     m;
} W_TIME;

    The time structure uses two 12 hour periods with an am and pm instead of the
24 hour clock. The last field, 'm', stands for meridian, and is a char which can
be either 'a' or 'p', for am or pm, respectively.

                                                     9 - Time



                         Function List


       Routine           Description
                  
       t_add             Add 2 times together.
       t_check           Check if the time is a valid time.
       t_clock           Display the time and date in a window.
       t_curtime         Get the current time from the system clock.
       t_exttimestr      Convert a W_TIME variable to a string, including secs.
       t_strtime         Convert a string to a W_TIME variable, excluding secs.
       t_strexttime      Convert a string to a W_TIME variable, including secs.
       t_sub             Find the difference between 2 times.
       t_timestr         Convert a W_TIME variable to a string, excluding secs.

                                                     9 - Time



Function....: t_add.
Purpose.....: Add 2 times together.
Syntax......: int  t_add(W_TIME time1, W_TIME time2, W_TIME *result);
              W_TIME time1;     1st time
              W_TIME time2;     2nd time
              W_TIME *result;   Result of time1 + time 2
Example call: day=t_add(time1,time2,&result);
Returns.....: Number of days of (result-time1). For example, if time1 is 10:00
              pm, and time2 is 72 hours. Then the number of days returned is 3
Common Use..: Given the current time and the time how long a process takes  to
              complete, the finish time can be determined with t_add.
See Also....: t_sub.
Example.....: Suppose a program takes 6 hours and 13 minutes to run. What time
              will it be when it finishes?


              #include "user_int.h"
              void main(void)
              {
              W_TIME start,
                     duration={6,13,0,' '},
                     end;

              w_init();
              t_curtime(&start);           /* Get the current time           */
              w_add(start,duration,&end);  /* Find what time it will be done */
              v_prtf("The current time is %d:%d:%d: %cm\n",start.hours,
                      start.minutes,start.seconds,start.m);
              v_prtf("The program ran for %d:%d:%d: %cm\n",duration.hours,
                      duration.minutes,duration.seconds,duration.m); );
              v_prtf("The program ended at %d:%d:%d: %cm\n",end.hours,
                      end.minutes,end.seconds,end.m);
              w_exit(0);
              }

                                                     9 - Time



Function....: t_check.
Purpose.....: Check if a time is valid.  t_check will insure the following 4
              rules hold.  If not, t_check will return FALSE.
              1  hours    12
              0  minutes  59
              0  seconds  59
              m = 'a','p', or ' '
Syntax......: int  t_check(W_TIME time);
              W_TIME time;      Time to validate
Example call: if (!w_check(time)) break;
Returns.....: Flag indicating if the time is a valid time.
Common Use..: To check if a user entered a valid time.
See Also....: d_check.
Example.....: Read a time in from the keyboard and check to see that the time is
              valid.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_TIME  time;

              w_init();
              window=w_open(3,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_time(0,0,"Time:",&time,10,FALSE,0,0);
              g_read();
              if (w_lastkey!=ESC)
                  if (!t_check(t_time))
                      v_prtf("Invalid Time.");
                  else
                      v_prtf("Time is OK.");
              g_close();
              w_close(window);
              w_exit(0);
              }

                                                     9 - Time



Function....: t_clock.
Purpose.....: Display the current time and date in a small 3 x 25 window.  The
              clock will be  displayed until a key or mouse button is pressed.
Syntax......: void t_clock(int row, int col);
              int row;      Screen row to display clock
              int col;      Screen column to display clock
Example call: t_clock(5,10);
Returns.....: None.
Common Use..: Let the user see what time and day it is.
See Also....: d_curdate,
              t_curtime.
Example.....: Display the time and date to the user.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              t_clock(10,10);
              w_exit(0);

                                                     9 - Time



Function....: t_curtime
Purpose.....: Get the current system time.  This function uses DOS service 2Ch
              which returns the  hundredths of seconds  as well as the  hours,
              minutes and seconds.However,the hundredths of a second component
              is valid only for those machines with real time clocks.
Syntax......: int  t_curtime(W_TIME *time);
              W_TIME *time;      Time to hold current time
Example call: hundredths=w_curtime(&time);
Returns.....: Hundredths of seconds component of current time.
Common Use..: To get the current time.
See Also....: d_curdate.
Example.....: Get the current time and display it on the screen, ignoring the
              hundredths of seconds component.


              #include "user_int.h"
              void main(void)
              {
              W_TIME  time;
              char    string[15];

              w_init();
              t_curtime(time);
              v_prtf("Current time: %d:%d:%d %cm,",time.hours,time.minutes,
                                                   time.seconds,time.m);
              w_exit(0);
              }

                                                     9 - Time



Function....: t_exttimestr.
Purpose.....: Convert a W_TIME variable into a string, including seconds.
Syntax......: char *t_exttimestr(char *string,W_TIME ext_time);
              W_TIME ext_time;  Time to convert
              char *string;     String to hold result
Example call: t_exttimestr(time,string);
Returns.....: Converted string if the W_TIME variable is a valid time and NULL
              otherwise.
Common Use..: Used to print a W_TIME variable, including the seconds.
See Also....: t_timestr,
              t_strexttime,
              t_strtime.
Example.....: Read in a W_TIME variable and then print it on the screen,
              including the seconds.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    string[12];
              W_TIME  ext_time;

              w_init();
              window=w_open(4,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_exttimestr(window,0,0,"Time:",&ext_time,11,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("You entered %s\n",t_exttimestr(ext_time,string));
              else       v_prtf("You pressed ESC.\n");
              w_exit(0);
              }

                                                     9 - Time



Function....: t_strexttime.
Purpose.....: Convert a string to a W_TIME variable, including seconds.
Syntax......: int  t_strtime(char *string,W_TIME *ext_time);
              char *string;     string to be converted.
              W_TIME *time;     W_TIME variable to hold the result.
Example call: valid=t_strexttime(string,&ext_time);
Returns.....: TRUE\FALSE flag indicating if the string was a valid time.
Common Use..: Used to convert a string into a  W_TIME variable, including the
              seconds.
See Also....: t_timestr,
              t_exttimestr,
              t_strtime.
Example.....: Read in a string and convert it to a W_TIME variable, including
              the seconds.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              int     valid;
              char    string[12];
              W_TIME  ext_time;

              w_init();
              window=w_open(4,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_string(window,0,0,"Time:",string,11,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
              {
                  valid=t_strexttime(string,&ext_time);
                  if (valid)
                  {
                      v_prtf("You entered %2d hours\n",ext_time.hours);
                      v_prtf("            %2d minutes\n",ext_time.minutes);
                      v_prtf("            %2d seconds\n",ext_time.seconds);
                      v_prtf("            %cm\n",ext_time.m);
                  }
                  else       v_prtf("You entered an invalid time.\n");
              }
              w_exit(0);
              }


                                                     9 - Time



Function....: t_strtime.
Purpose.....: Convert a string to a W_TIME variable, setting seconds to 0.
Syntax......: int  t_strtime(char *string,W_TIME *time);
              char *string;     string to be converted.
              W_TIME *time;     W_TIME variable to hold the result.
Example call: valid=t_strtime(string,&time);
Returns.....: TRUE\FALSE flag indicating if the string was a valid time.
Common Use..: Used to convert a string into a  W_TIME variable, excluding the
              seconds.
See Also....: t_exttimestr,
              t_timestr,
              t_strexttime.
Example.....: Read in a string and convert it to a W_TIME variable, excluding
              the seconds.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              int     valid;
              char    string[9];
              W_TIME  time;

              w_init();
              window=w_open(4,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_string(window,0,0,"Time:",string,8,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
              {
                  valid=t_strtime(string,&time);
                  if (valid)
                  {
                      v_prtf("You entered %d hours\n",time.hours);
                      v_prtf("            %d minutes\n",time.minutes);
                      /*                  time.seconds==0       */
                      v_prtf("            %cm\n",time.m);
                  }
                  else       v_prtf("You entered an invalid time.\n");
              }
              w_exit(0);
              }


                                                     9 - Time



Function....: t_sub.
Purpose.....: Find the difference between 2 times.  Only  the 1st time must be
              a  valid time.  time2  is, in most cases, not a time at all, but
              rather  some  amount  of  time  expressed in hours, minutes, and
              seconds.  For example, time2 can be 72 hours, or 200 minutes, or
              36 hours and 15 minutes, etc.
Syntax......: int  t_sub(W_TIME time1, W_TIME time2, W_TIME *result);
              W_TIME time1;     1st time
              W_TIME time2;     2nd time
              W_TIME *result;   Result of time1 - time2
Example call: day=t_sub(time1,time2,&result);
Returns.....: Number of days time1 was less than time2.  For example, if time1
              is 2:00:00 am, and time2 is 48 hrs, than the number of days will
              be 2, since subtracting 48 hours from  time1 will take us back 2
              days.  Also,  since 12:00:00  am is  considered the start of the
              next day, 12:00 am - 1 minute, which is  11:59:00 pm, will  also
              cause t_sub to  return the number  of days  as being 1, since at
              12:00:00 am,we started a new day. Therefore, going back 1 minute
              takes us back to  the previous day, and hence t_sub() returns 1.
Common Use..: Given a starting and ending  time, determine how  long a process
              took to complete.
See Also....: t_add
Example.....: Run a program  to draw a fractal  and determine how long it took
              to run.

              #include "user_int.h"
              void main(void)
              {
              char   time[15];
              W_TIME start,
                     duration,
                     finish;

              w_init();
              t_curtime(&start);           /* Get the starting time          */
              draw_mandelbrot();           /* Draw a fractal                 */
              t_curtime(&end);             /* Get the ending time            */
              t_sub(start,end,&duration);  /* Find how long it took to run   */
              t_timestr(time,start);       /* Convert W_TIME to string       */
              v_prtf("The starting time was %s: \n",time);
              t_timestr(time,end);         /* Convert W_TIME to string       */
              v_prtf("The ending time was %s: \n",time);
              t_timestr(time,duration);    /* Convert W_TIME to string       */
              v_prtf("The program ran for %s: \n",time);
              w_exit(0);
              }

                                                     9 - Time



Example.....: This is another t_sub example. What day and time was it 42 hours
              and 15 minutes ago?

              #include "user_int.h"
              void main(void)
              {
              char   d_buffer[15],
                     t_buffer[15];
              W_TIME time,
                     tm_sub={42,15,00,' '};   /* Time to subtract            */
              W_DATE date,
                     dt_sub={0,0,0};          /* Number of days to subtract  */

              w_init();
              t_curtime(&time);               /* Get the current time        */
              d_curdate(&date);               /* Get todays date             */
              d_datestr(d_buffer,date);       /* Convert W_DATE to a string  */
              t_timestr(t_buffer,time);       /* Convert W_TIME to a string  */
              v_prtf("Today is %s, and the current time is %s\n",
                      d_buffer,t_buffer);
              dt_sub.days=t_sub(time,tm_sub,&time);/* Get the time/num_days  */
              d_sub(date,dt_sub,&date);       /* Get the date                */
              d_datestr(d_buffer,date);       /* Convert W_DATE to a string  */
              t_timestr(t_buffer,time);       /* Convert W_TIME to a string  */
              v_prtf("42 hours and 15 minutes ago was: %s, %s\n",
                      d_buffer,t_buffer);
              w_exit(0);
              }

                                                     9 - Time



Function....: t_timestr.
Purpose.....: Convert a W_TIME variable into a string, excluding seconds.
Syntax......: int  t_exttimestr(W_TIME time,char *string);
              W_TIME time;      Time to convert
              char *string;     string to hold result
Example call: valid=t_timestr(string,time);
Returns.....: String with the converted time if the W_TIME variable is a valid
              time and NULL otherwise.
Common Use..: Used to print a W_TIME variable, excluding the seconds.
See Also....: t_exttimestr,
              t_strtime,
              t_strexttime.
Example.....: Read in a W_TIME variable and then print it on the screen,
              excluding the seconds.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    string[9];
              W_TIME  time;

              w_init();
              window=w_open(4,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_time(window,0,0,"Time:",&time,8,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  v_prtf("You entered %s\n",t_timestr(time,string));
              else  v_prtf("You pressed ESC.\n");
              w_exit(0);
              }


                                                     10 - Date



                                  Chapter 10

                                    Date

                                                     10 - Date



    Overview

    We all need to know  what day it is for  one reason or another.  Certainly,
we need to know if we have  to go to work or school today or not.  Or maybe we
want to know what day our birthday will be on next year. In any case,  we need
to be able to find out what day it is today,and to be able to add and subtract
days to and from a date and find out what day that will be and so on.



    Concepts

    The C User Interface date  routines  are all based  on the W_DATE structure
defined in w_date.h.  This structure is shown below:


typedef struct
{
    unsigned month,
             day,
             year;
} W_DATE;

    The standard C Library has no functions whatsoever that work  on dates, and
DOS can only  work with  dates  from  1980 to 2099.  So, the C  User  Interface
Library provides you with all the date functions you'll ever likely to need.

                                                     10 - Date



                         Function List


       Routine           Description
                  
       d_add             Add 2 dates together
       d_calendar        Display a calendar
       d_check           Make sure a date is a valid date.
       d_curdate         Get todays date.
       d_datestr         Convert a W_DATE variable to a string, excluding the
                         century.
       d_extdatestr      Convert a W_DATE variable to a string, including the
                         century.
       d_inmonth         Get the number of days in a month.
       d_julian          Convert a W_DATE variable to a julian date.
       d_leapyear        Determine if a year is a leap year.
       d_month           Get the name of a month.
       d_ofweek          Get the name of the day of the week on  which a date
                         falls.
       d_strdate         Convert a string  to a W_DATE variable, setting  the
                         century to the current century.
       d_strextdate      Convert a string to a W_DATE variable, including the
                         century.

                                                     10 - Date



Function....: d_add.
Purpose.....: Add two  dates together.  Only the first date, date1, must be  a
              valid date.  The 2nd date  can be anything.  For example,  date2
              can be 60 days, or it can be 2 months, or it can be 2 months and
              50  days.  Date2 is in fact usually not a valid date, but rather
              some amount of time specified in days, months, and years.
Syntax......: int  d_add(W_DATE date,W_DATE add,W_DATE *result); );
              W_DATE date1;     Date to be validated.
              W_DATE date2;     Date to be added
              W_DATE *result;   Date to hold the result
Example call: d_add(date1,date2,&result);
Returns.....: TRUE\FALSE  flag indicating if the first  date was valid or not.
Common Use..: Given a starting date  and a duration time, find  the completion
              date.
See Also....: d_sub.
Example.....: Suppose we have 90 days to complete a project.  What is  the due
              date?


              #include "user_int.h"
              void main(void)
              {
              W_DATE cur_date,
                     duration={0,90,0},
                     completion_date;
              buffer[9];

              w_init();
              d_curdate(&cur_date);
              d_add(cur_date,duration,&completion_date);
              v_prtf("Today is: %s\n",d_datestr(cur_date,buffer));
              v_prtf("Due date: %s\n",d_datestr(completion_date,buffer));
              w_exit(0);
              }

                                                     10 - Date



Function....: d_calendar.
Purpose.....: Display a calendar.  Use the  page up\down keys to  flip through
              the months,and Ctrl-Page up\down keys to flip through the years.
              The left mouse button flips through the calendar by months,while
              the right mouse button goes by years.  The calendar is displayed
              in a 9 x 35 window using the w_color_data global attributes, not
              including the border and shadow.
Syntax......: void d_calendar(int row,int col);
              int row;        Screen row to display calendar
              int col;        Screen col to display calendar
Example call: d_calendar(5,10);
Returns.....: None.
Common Use..: Display a calendar.
See Also....: t_clock.
Example.....: Display a calendar.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              d_calendar(5,10);
              w_exit(0);
              }

                                                     10 - Date



Function....: d_check.
Purpose.....: Make sure a date is a valid date.
Syntax......: int  d_check(W_DATE date);
              W_DATE date;      Date to be validated.
Example call: if (!d_check(date)) break;
Returns.....: TRUE\FALSE flag indicating if the date  was a valid  date or not.
Common Use..: Check the validity of  a date before using it. Usually used after
              a user enters a date.
See Also....: t_check.
Example.....: Ask a user to enter a date and then check that he entered a valid
              date.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_DATE  date;

              w_init();
              window=w_open(5,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_date(window,0,0,"Date:",&date,8,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  if (d_check(date))
                      v_prtf("You entered a valid date.");
                  else
                      v_prtf("You entered an invalid date.");
              w_exit(0);
              }

                                                     10 - Date



Function....: d_curdate.
Purpose.....: Get the current system date.
Syntax......: void d_curdate(W_DATE *date);
              W_DATE *date;    W_DATE variable to return current date in.
Example call: d_curdate(&date);
Returns.....: None.
Common Use..: To get the current date.
See Also....: t_curtime.
Example.....: Get the current date and display it on the screen.


              #include "user_int.h"
              void main(void)
              {
              W_DATE  date;

              w_init();
              d_curdate(&date);
              v_prtf("Todays date is : %2d/%2d/%2d\n",date.day,date.month,
                                                      date.year % 100);
              w_exit(0);
              }

                                                     10 - Date



Function....: d_datestr.
Purpose.....: Convert a W_DATE variable to a string, excluding the century.
Syntax......: char *d_datestr(W_DATE date,char *string);
              W_DATE date;    Date to convert.
              char *string;   String to return converted W_DATE variable in.
Example call: d_datestr(date,string);
Returns.....: String holding converted date if the W_DATE variable was valid
              and NULL otherwise.
Common Use..: To print a W_DATE variable, excluding the century.
See Also....: d_extdatestr,
              d_strdate,
              d_strextdate.
Example.....: Print a W_DATE variable on the screen.


              #include "user_int.h"
              void main(void)
              {
              W_DATE  date={5,22,1992};
              char    string[9];

              w_init();
              v_prtf("Date : %s\n",d_datestr(date,string));
              w_exit(0);
              }

                                                     10 - Date



Function....: d_extdatestr.
Purpose.....: Convert a W_DATE variable to a string, including the century.
Syntax......: char *d_extdatestr(W_DATE ext_date,char *string);
              W_DATE ext_date;     Date to convert.
              char *string;        String to return converted W_DATE variable in.
Example call: d_extdatestr(string,ext_date);
Returns.....: String holding converted date if the W_DATE  variable was valid
              and NULL otherwise.
Common Use..: To print a W_DATE variable, including the century.
See Also....: d_datestr,
              d_strdate,
              d_strextdate.
Example.....: Print a W_DATE variable on the screen.


              #include "user_int.h"
              void main(void)
              {
              W_DATE  ext_date={5,22,1992};
              char    string[12];

              w_init();
              v_prtf("Date : %s",d_extdatestr(string,ext_date));
              w_exit(0);
              }

                                                     10 - Date



Function....: d_inmonth;
Purpose.....: Get the number of days in a month.
Syntax......: int  d_inmonth(W_DATE date);
              W_DATE date;    Date whose number of days in the month is needed.
                              One would expect  that only a month  number, from
                              1 - 12 would  be needed.  However, since February
                              can have 28 or 29 days, a factor which depends on
                              the year, the year must also  be passed.  The day
                              component of the W_DATE variable is ignored.
Example call: num_days=d_inmonth(date);
Returns.....: Number of days in the month if the date is a valid date,
              otherwise it returns 0.
Common Use..: Get the last day in a given month.
See Also....: None.
Example.....: Print the last date in November.


              #include "user_int.h"
              void main(void)
              {
              W_DATE date={11,01,1992};      /* Month is November */

              w_init();
              v_prtf("The last date in November is : November %2d\n",
                      d_inmonth(date));
              w_exit(0);
              }

                                                     10 - Date



Function....: d_julian.
Purpose.....: Convert a W_DATE variable to a julian date.
Syntax......: int  d_julian(W_DATE date);
              W_DATE date;    Date to convert.
Example call: jul_day=d_julian(date);
Returns.....: The julian date.This is the number of days elapsed since January
              1st of the current year.  If the date is invalid, 0 is returned.
Common Use..: Get the julian day.
See Also....: None.
Example.....: Convert a few dates into their corresponding julian dates.


              #include "user_int.h"
              void main(void)
              {
              W_DATE date1={01,01,1991},       /* Jul date: 1         */
                     date2={02,12,1992};       /* Jul date: 43        */

              w_init();
              v_prtf("January 1,1991 = %d\n",d_julian(date1));
              v_prtf("February 12,1992 = %d\n",d_julian(date2));
              w_exit(0);
              }

                                                     10 - Date



Function....: d_leapyear.
Purpose.....: Determine if a year is a leap year.
Syntax......: int  d_leapyear(int year);
              int year;     Year to be tested.
Example call: leap_year=d_leapyear(date.year);
Returns.....: TRUE\FALSE flag indicating if year is a leap year or not.
Common Use..: Determine if a year is a leap year.
See Also....: None.
Example.....: Check a few dates to see if they are leap years.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (d_leapyear(1991))
                  v_prtf("1991 is a leap year.\n");
              else
                  v_prtf("1991 is not a leap.\n");
              if (d_leapyear(1992))
                  v_prtf("1992 is a leap.\n");
              else
                  v_prtf("1992 is not a leap.\n");
              w_exit(0);
              }

                                                     10 - Date



Function....: d_month;
Purpose.....: Get the month name.
Syntax......: char *d_month(int month,char* string);
              int month;       Month whose name is desired.
              char *string;    String to return month name in.
Example call: d_month(date.month,string);
Returns.....: Sets the string to the name of the month if the month number is
              valid, ie, between 1 and 12, or NULL otherwise.  The address of
              the string is also returned.
Common Use..: Used in printing the date in a fancy manner.
See Also....: d_ofweek.
Example.....: Print the date with the name of the month.


              #include "user_int.h"
              void main(void)
              {
              W_DATE date;
              char   string[10];

              w_init();
              d_curdate(&date);
              d_month(date,string);
              v_prtf("Date: %s %2d, %4d\n",string,date.day,date.year);
              w_exit(0);
              }

                                                     10 - Date



Function....: d_ofweek.
Purpose.....: Get the name of the day on which a date falls.
Syntax......: int  d_ofweek(W_DATE date,char *string);
              W_DATE date;     Date on which you wish the name of the day.
              char *string;    String to return name of the day in.
Example call: d_ofweek(date,string);
Returns.....: TRUE\FALSE flag indicating whether date was valid.  If the date
              was  valid, it  also sets  the string to the name of the day on
              which the date falls.  If the date is invalid, 0 is returned.
Common Use..: Used in printing the date in a fancy manner.
See Also....: d_month.
Example.....: Print the date with the name of the day and month.


              #include "user_int.h"
              void main(void)
              {
              W_DATE date;
              char   day[10]
                     month[10];

              w_init();
              d_curdate(&date);
              d_ofweek(date,day);
              d_month(date,month);
              v_prtf("Today is %s, %s %2d, %4d\n",day,month,date.day,date.year);
              w_exit(0);
              }

                                                     10 - Date



Function....: d_strdate.
Purpose.....: Convert a string to a W_DATE variable, excluding the century.
              The century is set to the current century.
Syntax......: int  d_strdate(char *string,W_DATE *date);
              char *string;    String to convert.
              W_DATE *date;    Date variable to return converted string in.
Example call: valid=d_strdate(string,&date);
Returns.....: TRUE\FALSE flag indicating if converted W_DATE variable is valid.
Common Use..: To convert an input string to a W_DATE variable, excluding the
              century.
See Also....: d_datestr,
              d_extdatestr,
              d_strextdate.
Example.....: Convert a user input date string into a W_DATE variable.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_DATE  date;
              char    string[9];

              w_init();
              window=w_open(5,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_string(window,0,0,"Date:",string,8,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  valid=d_strdate(string,&date);
                  if (valid)
                     v_prtf("The converted date string is : %2d/%2d/%4d\n",
                             date.day,date.month,date.year);
                  else
                     v_prtf("You entered an invalid date string.");
              w_exit(0);
              }

                                                     10 - Date



Function....: d_strextdate.
Purpose.....: Convert a string to a W_DATE variable, including the century.
Syntax......: int  d_strextdate(char *string,W_DATE *ext_date);
              char *string;      String to convert.
              W_DATE *ext_date;  W_Date variable to return converted string in.
Example call: valid=d_strextdate(string,&ext_date);
Returns.....: TRUE\FALSE flag indicating if converted W_DATE variable is valid.
Common Use..: To convert  an input string to a  W_DATE variable, including  the
              century.
See Also....: d_datestr,
              d_extdatestr,
              d_strdate.
Example.....: Convert a user input date string into a W_DATE variable.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              W_DATE  ext_date;
              char    string[11];

              w_init();
              window=w_open(5,5,1,30,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_string(window,0,0,"Date:",string,10,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  valid=d_strdate(string,&ext_date);
                  if (valid)
                     v_prtf("The converted date string is : %2d/%2d/%4d\n",
                             date.day,date.month,date.year);
                  else
                     v_prtf("You entered an invalid date string.");
              w_exit(0);
              }


                                                     10 - Date



Function....: d_sub.
Purpose.....: Subtract one date from another.  Only the  1st date, date1, must
              be a  valid date.  The 2nd  date can be  anything.  For example,
              date2 can be 6 years,or it can be 9 months,or it can be 7 months
              and 53 days.Date2 is in fact usually not a valid date,but rather
              some amount of time specified in days, months, and years.
Syntax......: int  d_sub(W_DATE date,W_DATE add,W_DATE *result); );
              W_DATE date1;     Date to be validated.
              W_DATE date2;     Date to be added
              W_DATE *result;   Date to hold the result, date1-date2
Example call: d_sub(date1,date2,&result);
Returns.....: TRUE\FALSE flag indicating whether date1 was valid or not.
Common Use..: Find the date some amount of days ago.
See Also....: d_add.
Example.....: What day of the week was it 3 years, 2 months, and 43 days ago?


              #include "user_int.h"
              void main(void)
              {
              W_DATE date,
                     sub={2,43,3};
              char   buffer[10];

              w_init();
              d_curdate(&date);
              v_prtf("Today is: %s\n",d_datestr(date,buffer));
              d_sub(date,sub,&date);
              v_prtf("3 years, 2 months, and 13 days ago was: %s\n",
                     d_datestr(date,buffer));
              v_prtf("This was a %s\n",d_ofweek(date,buffer));
              k_wait(0);
              w_exit(0);
              }


                                                     11 - String



                                  Chapter 11

                                   String

                                                     11 - String



    Overview

    One of the  most  important  abilities  of the  computer  is the ability to
manipulate text.  Whether  it be names, addresses, or even a  whole story book,
operations  such  as extracting  a substring, adding two  strings  together, or
comparing two strings, are very, very useful.  The standard C library  contains
a large set of functions toward that end.

    Concepts

    The string in C is simply a linear array of consecutive bytes. The end of a
string is marked with a 0, and hence are called asciiz strings.  Although the C
library contains many string routines,there are a few which they forgot to add.
The C User  Interface Library  adds only 5 new string  functions, but  they are
very useful and will be used often.


                                                     11 - String



                         Function List


       Routine           Description
                  
       s_strins          Insert a character into another string
       s_strpad          Pad a string with blanks to a given length
       s_strrem          Remove blanks from a string
       s_strsub          Get a substring of a string
       s_strtok          String tokenizer


                                                     11 - String



Function....: s_strins.
Purpose.....: Insert a character into a string.
Syntax......: char *s_strins(char *string,char ch,int pos_ins);
              char *string;      Destination string in which insertion will be
                                 made.
              char  ch;          Source character to insert.
              int   pos_ins;     Position in destination string to insert
                                 character.
Example call: s_strins(string,'A',3);
Returns.....: Inserts the source character into the destination  string at the
              specified byte.  Returns the address of the destination  string.
              If the  position parameter is less than zero or greater than the
              length of  the string, s_strins  ignores the command and NULL is
              returned.  Otherwise, the  string with the inserted character is
              returned.
Common Use..: To embed 1 string within another.
See Also....: None.
Example.....: Insert blanks between the words Hello and World.


              #include "user_int.h"
              void main(void)
              {
              int i;
              char string[20]={"Hello World"};

              w_init();
              for(i=0;i<5;++i)
                  s_strins(string,' ',5+i);
              w_exit(0);
              }

                                                     11 - String



Function....: s_strpad.
Purpose.....: Pad a character with blanks.
Syntax......: char *s_strpad(char *string,int side,int length);
              char *string;      String to pad.
              int   side;        Side of string to pad.
              int   length;      Length padded string should be.
Example call: s_strpad(string,TRAILING,20);
Returns.....: Pads the source string with blanks on the specified side.  The
              side can be  either LEADING or TRAILING (which  are defined in
              w_string.h).  The padded string is returned.
              IMPORTANT:  Length must be less than or equal to the length of
                          the string buffer. If it is greater, then a memory
                          overwrite will occur.
Common Use..: To pad a string field to a standard length.
See Also....: s_strrem.
Example.....: Suppose you have a list of names, each of which should be 50
              bytes long.  Let a user enter 5 names and then pad each to a
              uniform length of 50 bytes.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    names[5][51];
              int i;

              w_init();
              window=w_open(5,5,1,60,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              for(i=0;i<5;++i)
                  g_string(window,i,0,"Name:",names[i],50,FALSE,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
              {
                  for(i=0;i<5;++i)
                      s_strpad(names[i],TRAILING,50);
              }
              w_exit(0);
              }


                                                     11 - String



Function....: s_strrem.
Purpose.....: Remove blanks from a string.  You may remove LEADING, TRAILING,
              or ALL blanks from a string.  The three  constants named  above
              are all defined in w_string.h.
Syntax......: char *s_strrem(char *string,int operation);
              char *string;      String to pad.
              int   operation;   Where to remove blanks.
Example call: s_strrem(string,ALL);
Returns.....: Removes the  blanks specified by operation.  The  address of the
              modified string is returned.  The valid operations are listed in
              w_string.h, and are LEADING, TRAILING,and ALL. If string is NULL
              or  an  invalid  operation is specified, s_strrem is ignored and
              NULL is returned.  Otherwise, the  trimmed  string is  returned.
Common Use..: To remove any unwanted blanks from a user input string.
See Also....: s_strpad.
Example.....: Get the name of a file from a user and remove all blanks from
              the name.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              char    file[51];

              w_init();
              window=w_open(5,5,1,60,TRUE,TRUE,w_color_data,0);
              if (!window) w_exit(1);
              g_string(window,0,0,"Name:",file,50,0,0,0);
              g_read();
              g_close();
              w_close(window);
              if (w_lastkey!=ESC)
                  s_strrem(file,ALL);
              w_exit(0);
              }

                                                     11 - String



Function....: s_strsub.
Purpose.....: Get a portion of a larger string.
Syntax......: char *s_strsub(char *string,int start,int num_char);
              char *string;      Source string.
              int   start;       Starting byte.
              int   num_char;    Length of substring.
Example call: s_strsub(string,10,8);
Returns.....: Returns the  address of the substring.  If the starting position
              excedes the length string or is less than zero,Null is returned.
              Otherwise, the substring will start at the starting point speci-
              fied by start,and continue until the number of characters speci-
              fied by num_char is reached or until the source string ends.
Common Use..: To obtain a subportion of a string.
See Also....: s_strins,
              s_strpad,
              s_strrem.
Example.....: Suppose a 40  character  name  string has 2 fields, a first name
              which is 20 characters long and is in chars 0-19,and a last name
              which is  also  20  chars  long, and stored in chars 20-39.  Use
              s_strsub to separate  the name string into its 2 constituent
              parts.


              #include <string.h>
              #include "user_int.h"
              void main(void)
              {
              char name[41]={"Walter              Cronkite"};
              char first_name[21],
                   last_name[21];

              w_init();
              strcpy(first_name,s_strsub(name,0,20));
              strcpy(last_name ,s_strsub(name,20,20));
              v_prtf("The first name is %s\n",first_name);
              v_prtf("The last  name is %s\n",last_name);
              w_exit(0);
              }

                                                     11 - String



Function....: s_strtok.
Purpose.....: Tokenize a string.  That is, parse  a string in successive  calls.
              This is a replacement for the standard C library  strtok function,
              which  has a  lot of quirks  that render it  almost useless.  This
              replacement functions the way the standard library routine should.
              This function is very useful in parsing strings.  In the 1st call
              to s_strtok, the string  to be parsed  should be passed as the 1st
              argument.  In  subsequent  calls, use NULL as the first parameter.
              This  NULL informs  s_strtok to  continue parsing the same string.
              The 2nd argument is a list of separator  characters.  These separ-
              ator characters are what is used to delimit  the string.  s_strtok
              searches the source string to find the 1st matching character from
              the separator list.  s_strtok then returns the substring marked by
              the delimited character. If no separator characters are found, the
              entire  string is returned.  If the end of the string is  reached,
              a NULL is returned. If the 1st character is a separator character,
              "" is returned. The source string is destroyed, so it is advisable
              to do the tokenizing on a copy string.
Syntax......: char *s_strtok(char *string,char *sep);
              char *string;      String to be tokenized
              char *sep;         List of delimiting characters
Example call: sub_dir=s_strtok(path,"\\ ");
Returns.....: Substring delimited by  separator characters, or 0 if  the  end of
              the string has been reached.
Common Use..: To parse a full path into its corresponding directory parts.
See Also....: None.
Example.....: Separate a path name into its constituent parts.

              #include <dir.h>
              #include "user_int.h"
              void main(void)
              {
              char *token;
              char path[81];

              w_init();
              getcwd(path,80);               /* Get full path to cwd         */
              token=s_strtok(path,"\\ ");    /* 1st call use string to parse */
              v_prtf("Drive: %s\n",token);
              while(token=s_strtok(0,"\\ ")) /* All Subsequent calls use NULL*/
                    v_prtf("Sub dir: \\%s\n",token);
              k_wait(0);                     /* (0) to continue parsing the  */
              w_exit(0);                     /* original string.             */
              }

                                                     12 - Files



                                  Chapter 12

                                    Files



                                                     12 - Files



    Overview

    Files are an important part of modern computing. Database applications use
intensive file I/O operations. Many Operating Systems treat devices as if they
files (DOS,UNIX,etc). The standard C library comes with an excellent supply of
  basic  building blocks for  file operations.  The C User Interface Library
adds a few more.  Included is a file\text  editor and a routine to open a file
for I/O.

    Concepts

    Files can be opened for reading, writing,reading and writing,and in binary
mode  or translated.  Also, if the file  resides on a removable media, (floppy
drive) then there exists the possibility that the disk is not inserted. If you
want to  write to a  file, then it  can't be write protected.  If  you're on a
network, you have to have the rights to open files.  All of these problems are
handled for  you by the  C User Interface Library f_fileio function.  Whenever
you want to open a file for reading or writing, use the f_fileio routine to do
it for you. What if you only have a hard drive C and the user specifies D. All
of these possible  problems are handled for you.  Another thing to consider is
the mode in  which the  file is  opened.  In  addition to opening  a file  for
reading  or writing, you  must also  consider the  way in which  ascii 0Ah  is
treated.  In translated mode, ascii 0Ah, the Line Feed character '\n', is con-
verted to a LF\CR pair, ascii  0Ah and 0Dh.  In binary mode, ascii 0Ah is just
another byte and is not converted.  Thus, a general rule of thumb is  too open
.exe and .com files in  binary mode and all other non-data files in translated
mode.

                                                     12 - Files



                         Function List


       Routine           Description
                  
       f_copy            Copy 1 file to another.
       f_delete          Delete a file.
       f_edit            Edit/Browse a file.
       f_filebox         Browse directories for a file.
       f_fileio          Open a file for I/O.
       f_fullpath        Create the full path name of a relative path name


                                                     12 - Files



Function....: fcopy.
Purpose.....: Copy  1 file  to another.  The file  mode can  be either 'b' for
              binary mode or 't' for translated mode.  See the concept section
              for an explanation of these two modes.
Syntax......: int f_copy(char *source_file,char *dest_file,char mode);
              char *source_file;      Source file to be copied.
              char *dest_file;        Destination file to copy source to.
              char  mode;             Mode in which to perform copy.
Example call: f_copy("O:\\window\\file.c","A:\\file.bak",'t');
Returns.....: TRUE\FALSE flag indicating whether file transfer was successful.
              If  either file does  not exist  or can not be  found, FALSE  is
              returned. If the source file can not be opened for reading or if
              the  destination file  can not  be opened  for writing, FALSE is
              returned. If on a network,the user must have read privileges for
              the source  file and write privileges for the destination  file.
              If the destination file does not  exist, the user must also have
              create privileges.  If the destination file does exist, its con-
              tents are destroyed.  No warning is given.
Common Use..: To make a back up copy of a file.
See Also....: f_delete.
Example.....: Make a backup copy of a file before you edit it.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              f_copy("file.c","file.bak","t");
              f_edit(2,2,20,75,75,"file.c",w_color_editor_text,
                     w_color_editor_block,TRUE,FALSE,0,0);
              w_exit(0);
              }

                                                     12 - Files



Function....: f_delete.
Purpose.....: To delete a file.
Syntax......: int   f_delete(char *file);
              char *file;      File to delete.
Example call: f_delete("O:\\window\\file.c");
Returns.....: TRUE\FALSE flag  indicating  whether  file was deleted.  If on a
              network, the user must have delete privileges.
Common Use..: To delete  back up  copies of files or to remove temporary files
              created by your application program..
See Also....: f_copy.
Example.....: Make a backup copy of a file before you edit it.  Then prompt the
              user to see if he wants to save the back up file or to delete it.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              f_copy("file.c","file.bak",'t');
              f_edit(2,2,20,75,75,"file.c",w_color_editor_text,
                     w_color_editor_block,TRUE,FALSE,0,0);
              if ('Y'==w_ynbox("Do you wish to delete the back up copy",0))
                  f_delete("file.bak");
              w_exit(0);
              }

                                                     12 - Files



Function....: f_edit.
Purpose.....: Edit or browse an ascii text file.  f_edit() allows  you to load
              files up  to 3000  lines long.  Also, since  f_edit  dynamically
              allocates memory from  the heap, the maximum allowable size of a
              loadable  file is  determined  by the  amount of free heap space
              remaining. Thus, since the tiny, small, and medium memory models
              use the near heap  while the compact, large, and huge models use
              the far heap, the maximum  loadable file  size  is memory  model
              dependent.  When using a memory model that allows only  a single
              code segment(tiny, small, and medium), you will be restricted to
              file sizes less  than 64k.  All other memory  models allow  file
              sizes  limited only by  available free memory.  Also, file lines
              may contain up to 256 characters per line.If a line excedes this
              length, it  will  be  truncated.  f_edit  functions  differently
              depending  on the  mode specified.  In browse mode, if the  file
              can't be found, an error  message is displayed and f_edit quits.
              When a file is not found in edit mode, f_edit creates a new file
              for you.  Also, many  functions and keystrokes available in edit
              mode, are ignored  in browse  mode.  For a complete list of keys
              for  both modes, see the table on the following page.  If a help
              word is not specified, a default is used in its place. No backup
              is made of a  file to be edited.  Instead, if  any changes  were
              made  to the file being edited, you  will be asked at the end of
              the edit session  whether or not  you want to save your changes.
              The actual file is only updated if you answer yes.  f_edit takes
              2 ATTRIBUTE parameters.  In browse mode, the 2nd color parameter
              is ignored.  There are two globals which you may want to use for
              calls to f_edit.  They are:

              1. w_color_editor_text        These colors may be changed by
              2. w_color_editor_block       calling w_setup.

              If the indicator parameter is specified as TRUE, then the bottom
              row of the  edit window will be used to display various status'.
              This includes:

              1. Insert On\Off
              2. Box drawing mode On\Off
              3. Current line
              4. Current column
              5. DOS memory remaining

                                                     12 - Files



Syntax......: int   f_edit(int row,int col,int hgt,int wth,int vir_wth,
                           char *file_name,ATTRIBUTE text_color,ATTRIBUTE
						   blck_color,int edit,int shad,int indicators,
						   char *title,char *help_word);
              int row;              upper left hand row and column coordinates
              int col;              of edit window.
              int hgt;              Number of rows in edit window.
              int wth;              Number of columns in edit window.
              int vir_wth;          Virtual width of edit window,  This allows
                                    you  to  scroll  files  horizontally which
                                    don't fit on the screen.  All files scroll
                                    vertically.
              char *file_name;      File to edit\browse.
              ATTRIBUTE text_color; Color to use for edit window and text.
              ATTRIBUTE blck_color; Color to use for blocked text.
              int edit;             TRUE\FALSE flag indicating if file is to be
                                    edited or browsed.EDIT and BROWSE constants
                                    are defined in w_window.h.
              int shad;             TRUE\FALSE  flag  indicating  if  a shadow
                                    should be drawn on the edit window.
              int indicators;       TRUE\FALSE flag indicating whether the
                                    screen coordinates should be displayed
              char *title;          Title to place on edit window.
              char *help_word;      Help word used to retrieve context sensitive
                                    help from the help.dat file when the  F1 key
                                    is pressed.

                                                     12 - Files




Ŀ
 f_edit keys        Browse  Edit                Function                  
Ĵ
 Right\Left Arrow     x      x    Move over 1 column to the right\left    
 Up\Down Arrow        x      x    Move up\down 1 row                      
 Page Up\Down         x      x    Move up\down 1 page                     
 Home\End             x      x    Move to the beginning\end of a line     
 Ctrl Arrow keys      x      x    Move the screen instead of the cursor   
 Ctrl Home\End        x      x    Move to the first\last line of the file 
 Ctrl Page Up\Down    x      x    Move to the first\last line of the file 
 Ctrl K-B                    x    Block begin                             
 Ctrl K-C                    x    Block copy                              
 Ctrl K-H                    x    Block ignore                            
 Ctrl K-K                    x    Block end                               
 Ctrl K-P             x      x    Print out the entire file               
 Ctrl K-V                    x    Block move                              
 Ctrl K-Y                    x    Block delete                            
 Ctrl N                      x    Insert a blank line at the current row  
 Ctrl Y                      x    Delete the current line                 
 Enter                x      x    Move to next line                       
 F1                   x      x    Help screen                             
 Alt F1                      x    Select box drawing style                
 Shift F1                    x    Toggle box mode On/Off                  
 F6                          x    Delete to end of line                   
 Esc                  x      x    Quit the edit. If any changes were made 
                                  to the file,you will be prompted whether
                                  or not you want to  save them.          


                                                     12 - Files




Example call: f_edit(2,2,20,75,75,"file.c",w_color_editor_text,
                     w_color_editor_block,EDIT,FALSE,0,0);
Returns.....: True only if changes were made and saved, False otherwise.
Common Use..: To edit or browse large text files.
See Also....: None.
Example.....: Browse a file.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              f_edit(2,2,20,75,75,"file.c",w_color_editor_text,
                     w_color_editor_block,BROWSE,FALSE,0,0);
              w_exit(0);
              }

                                                     12 - Files



Function....: f_filebox.
Purpose.....: Allows a user to select a file and to move to other  directories.
              This  function is analogous to  the m_filebox()  function, except
              that when the user  selects a directory, instead of  quitting the
              file browse and returning the directories name, f_filebox() moves
              to the directory selected and  displays a file list, based on the
              two parameters, file_ext and file_attr, from the  selected direc-
              tory.  f_filebox ends when the user either presses ESC or selects
              a file. Returns -1 if the user presses ESC. Otherwise, the number
              of the file  in the file list is  returned the  full path name of
              the selected file is returned in the file_name parameter.
Syntax......: int f_filebox(int row,int col,int num_rows,int num_cols,
                  char *filename,char *file_ext,int file_attr);
              int row;         Screen row of file window
              int col;         Screen column of file window
              int num_rows;    Number of rows in file window
              int num_cols;    Number of columns in file window
              char *filename;  Variable to hold the selected file's name
              char *file_ext;  Extension used to match files to be displayed
              int file_attr;   Attributes of files to be displayed
Example call: f_filebox(5,5,5,3,filename,"*.*",FA_ARCH);
Returns.....: -1 if user pressed ESC, otherwise, the number of the  file in the
              file list is returned,and the full path name of the selected file
              is returned in the file_name parameter.
Common Use..: To display a list of files and to let the user pick one.  If the
              user does not  see the file  he is looking for, he  can select a
              directory, and view the files in that directory, until  he finds
              the file he is looking for.
See Also....: f_fileio,
              m_filebox.
Example.....: Display a list of all C  files in the current  directory and let
              the user pick one.  If he doesn't see one he likes, allow him to
              move to another directory and view all the C files there.


              #include "user_int.h"
              void main(void)
              {
              int  sel;
              char file_name[128];


                                                     12 - Files



              w_init();
              sel=f_filebox(5,5,5,3,filename,"*.c",FA_ARCH);
              if (sel==-1)
                 w_errbox(0,"User pressed ESC.");
              else
              {
                 v_prtf("User selected %s\n",file_name);
                 k_wait(0);
              }
              w_exit(0);
              }

                                                     12 - Files



Function....: f_fileio.
Purpose.....: Open a file for reading or writing.  This function will prompt the
              user for a file name. It will make sure the drive specified exists
              and if a floppy drive is specified, whether a disk  is inserted or
              not.  Also, when opening a file for writing, it also checks to see
              if the  disk is  write protected.  If the  file already  exists, a
              warning message is  displayed and the user is prompted whether  he
              wishes to continue and overwrite the file, or to quit.  If  a file
              is being opened  for reading  and the specified file is not found,
              then, if the m_file_ext and m_file type are specified, a pick list
              of files of the specified type and extension will be displayed for
              the user by calling f_filebox(). He may then pick one.  This  is a
              useful feature if you have old  files but you can't remember their
              names.  All fields that begin with "m_" (m_row, m_col, m_num_rows,
              m_num_cols, m_file_ext, and m_file_type) will  be  ignored  if the
              mode  for the file to be opened is  not reading ('r').  You should
              therefore simply use 0's for these fields whenever you are opening
              a file  for writing.  The  displayed file  picklist  is simply  an
              f_filebox(). Unless the file is  opened successfully, NULL  is re-
              turned.  If a NULL  help word  is passed,  default  help  will  be
              provided.
              WARNING!: Do not use a literal for the "file_path" parameter. The
                        full path name of  the opened file  is returned in this
                        variable.
Syntax......: FILE *f_fileio(int row,char *file_path,char mode_,
                    char translation,int m_row,int m_col,int m_num_rows,
                    int m_num_cols,char *m_file_ext,int m_file_type,
                    char *help_word);
              int row;            Row at  which user  will input the  filename.
              char *file_path;    Initial name to display.  This will also have
                                  the full path name of the opened  file on re-
                                  turn.
              char mode_;         Mode in which to open file ('r' or 'w').
              char translation;   Translation mode ('b' or 't')
              int  m_row;         Row and column of screen to pop up a picklist
              int  m_col;         of files  if the file  specified to be opened
                                  for reading is not  found.
              int  m_num_rows;    Number of rows in file picklist.
              int  m_num_cols;    Number of columns in file picklist
              char *m_file_ext;   File extension wild card (eg, "*.c", m_?.??")
              int  m_file_type;   File type for picklist  (eg, FA_RDONLY)
              char *help_word;    Help word  used to provide  context sensitive
                                  help
              See the  concept section for a discussion of the mode and  trans-
              lation.

                                                     12 - Files



Example call: handle=f_fileio(17,file,'r','t',5,5,10,1,"f_???.c",FA_ARCH,0);
Returns.....: The handle of the file if it was  successfully opened, otherwise
              Null. Also, the full path name of the opened file is returned in
              the file_path variable. Thus, you should not use a literal here.
              Instead reserve sufficient  room for a DOS file name, 128 bytes,
              and copy the initial file name into this buffer. See the example
              below.
Common Use..: Open a file for reading or writing.
See Also....: None.
Example.....: Open a file for reading in translated mode, process the file,and
              then reopen the file for writing.


              #include <stdio.h>
              #include "user_int.h"
              void main(void)
              {
              FILE *handle;
              char file[128]={"file.c"};       /* File name buffer    */

              w_init();
              handle=f_fileio(17,file,'r','t',5,5,5,3,"*.*",
                              FA_DIREC | FA_ARCH,0);
              if (!handle) w_exit(1);
              else process_file();
              fclose(handle);
              handle=f_fileio(17,file,'w','t',0,0,0,0,0,0,0);
              if (!handle) w_exit(1);
              else process_file();
              fclose(handle);
              w_exit(0);
              }

                                                     12 - Files



Function....: f_fullpath.
Purpose.....: Gets the full path name of a relative  file path.  This function
              will take  any type of  path name, including  the DOS wild  card
              characters '*' and  '?', and expand the  path into  a full  path
              name which includes the drive and full path from the root drive.
              '*' is expanded to an equivalent number of '?'.  If the  path is
              valid, then  the full path is  returned.  Otherwise, NULL is re-
              turned.  The expanded name is returned in the fullpath variable,
              which must be 128 bytes, which is  the DOS maximum  path length.
Syntax......: char *f_fullpath(char *filename, char fullpath[128]);
              char *filename;           Path to expand
              char  fullpath[128];      Hold fully expanded path
Example call: f_fullpath("O:\\window\\*.?", fullpath);
Returns.....: The full path if the path is a valid DOS path,and NULL otherwise
Common Use..: The path specified need not exist. f_fullpath() simply checks to
              see that it could exist, ie, that it is a valid DOS path.  Thus,
              this function  can be  used to test  for invalid file  names and
              directories.
See Also....: None.
Example.....: Get the full path of a few sample paths.

              #include "user_int.h"
              void main(void)
              {
              char fullname[128];

              w_init();
              if (f_fullpath("C:\\..",fullname))
                 v_prtf("%s\n",fullname);
              if (f_fullpath("C:\\DOS\\..\\*.*",fullname))
                 v_prtf("%s\n",fullname);
              if (f_fullpath("O:\\UTILITY\\.\\NORTON\\",fullname))
                 v_prtf("%s\n",fullname);
              if (f_fullpath("?.exe",fullname))
                 v_prtf("%s\n",fullname);
              if (f_fullpath("?.com\\",fullname))
                 v_prtf("%s\n",fullname);
              w_exit(0);
              }

                                                     13 - Mouse


                                  Chapter 13

                                    Mouse



                                                     13 - Mouse



    Overview

    The mouse is the pointing device of choice.  Almost everyone has one. With
the inexpensive price tag and ease of use, the mouse quickly surpassed the joy
stick, light pen and track ball in popularity.  The C User Interface functions
come with  built  in mouse  support.  Whether or not you yourself like using a
mouse, any modern day program must provide support for mice. The C User Inter-
face Library makes adding mouse support to your programs easy.

    Concepts

    The mouse comes in two forms.  Those with three buttons and those with two.
By far, the two button mouse is the more  widely used.  The mouse is controlled
by a dedicated interrupt, int 33h.  This interrupt provides an interface to the
mouses device driver.  The mouse cursor is slightly different from  the  normal
hardware  cursor.  The hardware cursor blinks.  The mouse  cursor doesn't.  The
hardware cursor  is  available  only  in text modes.  The mouse  has a separate
cursor for  text and  graphics modes.  The  text  cursor can not be turned off,
(turning  the  text cursor  off  is  simulated  by setting the cursor to a non-
visible screen coordinate.  The cursor is still on, but you can't see it.)  The
mouse cursor can be turned off and on.   However, the mouse device driver keeps
track of the number  of times the mouse cursor is turned  on and  the number of
times it is turned off. The result of this is that if you turn the mouse cursor
off twice, you must turn it on twice in order to actually turn the mouse cursor
back on.

    Information  about the mouse is kept in the  global variable w_mouse, whose
structure is shown below.

typedef struct MOUSE_DATA
{
   int       installed,           /* Flag if mouse is installed          */
             version,             /* Driver version in BCD               */
             type,                /* Mouse type                          */
             irq,                 /* Interrupt line used                 */
             num_buttons,         /* Number of buttons on mouse          */
             cursor,              /* Cursor On/Off flag                  */
             pix_row,             /* Pixel  row                          */
             pix_col,             /* Pixel  column                       */
             txt_row,             /* Text   row                          */
             txt_col,             /* Text   column                       */
             rht_but,             /* Right  button pressed flag          */
             lft_but,             /* Left   button pressed flag          */
             cnt_but;             /* Center button pressed flag          */
   char far *copyright;           /* Copyright notice in mouse driver    */
} MOUSE;

Note: The mouse functions support Microsoft or fully compatible mouses only.

                                                     13 - Mouse


The various mouse functions  provided by  the C User  Interface  Library return
their information by  updating the various fields of the w_mouse variable.  The
mouse divides the screen  into pixels, usually  640x200, and uses this grid for
its  coordinate system.  Each text space is  composed of an 8x8 pixel box.  The
equivalent  text row and column positions are stored in the txt_row and txt_col
fields.  The cursor field indicates  whether the mouse cursor is on or off, and
the num_buttons contains the number of buttons on the mouse, either 2 or 3. The
rht_but, lft_but, and cnt_but tell  whether a button has  been clicked  or not.
The xxx_but variable  will  be set  to 1 (On)  whenever the corresponding mouse
button is clicked, and reset to 0(Off) when they aren't. An important consider-
ation to note is that when a button click is detected, it must be debounced.The
reason is the following.Whenever you click a mouse button,the button is actual-
ly held down for a few milliseconds.

However, the lines:

m_button();            /* Reset mouse buttons                         */
do
{
    do                 /* Wait for user to click a mouse button       */
    {
      m_button();      /* Detect a mouse click                        */
    } while (!w_mouse.rht_but && !w_mouse.lft_but && !w_mouse.cnt_but);

    do_something();    /* Once a button is clicked, execute some code */
} while(TRUE);

take but a few microseconds to execute.  Thus, if even though the mouse is only
clicked once, since  the entire  loop will  execute in a few microseconds, when
you  return to  the top of  the loop to test for the presence of a mouse click,
the mouse will not have been released yet and the loop will get executed again.
Actually, the loop  will get executed a  number of times, depending on how slow
you click the mouse.  To solve this problem, after detecting a mouse click, you
should wait until the mouse settles before proceeding.The above code should be:

m_button();            /* Reset mouse buttons                             */
do
{
    do                 /* Wait for user to click a mouse button           */
    {
      m_button();      /* Detect a mouse click                            */
    } while (!w_mouse.rht_but && !w_mouse.lft_but && !w_mouse.cnt_but);

    m_debounce();      /* Wait for mouse to settle                        */
                       /* This insures that do_something is executed only */
                       /* once per mouse click                            */
    do_something();    /* Once a button is clicked, execute some code     */
} while(TRUE);

    That's about it for the mouse.  The  examples provided  with  each function
along with the source  code  for the  demo  should provide adequate examples of
how to incorporate the mouse into your programs.

Note: The mouse will only work correctly in the 80 column video modes.

                                                     13 - Mouse



                         Function List


       Routine           Description
                  
       m_button          Get the status of the mouse buttons.
       m_copyright       Get the copyright notice embedded in mouse driver
       m_curoff          Turn the mouse cursor off.
       m_curon           Turn the mouse cursor on.
       m_debounce        Wait for the mouse to settle after a click.
       m_double          Determine if a mouse button was double clicked.
       m_getcur          Get the current mouse cursor location.
       m_getpress        Detect a mouse button press
       m_getrelease      Detect a mouse button release
       m_graphcur        Set graphics mouse cursor
       m_init            Initialize the mouse system.
       m_keytrans        Translate a mouse click into a key press (Internal).
       m_motion          Detect mouse motion
       m_setcnrs         Place a set of mouse click buttons on the corners of a
                         window (Internal).
       m_setcur          Set the current mouse cursor location.
       m_sethor          Set the mouse cursor horizontal limit.
       m_setver          Set the mouse cursor vertical  limit.
       m_textcur         Set the mouse text cursor
       m_version         Get the mouse driver version, IRQ line, and mouse type


                                                     13 - Mouse



Function....: m_button.
Purpose.....: Determine if the user clicked a mouse button and which ones were
              pressed.
Syntax......: void m_button(void);
Example call: m_button().
Returns.....: Sets the lft_but, rht_but, and cnt_but fields of w_mouse to TRUE
              if the corresponding mouse button is clicked, otherwise they are
              set to FALSE.
Common Use..: Determine if the mouse was clicked and if so which button it was
See Also....: m_debounce,
              m_getcur.
Example.....: Wait for the user to click a mouse button and then display which
              button he clicked.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              m_button();       /* Reset mouse buttons                       */
              do                /* Wait for the user to click a mouse button */
              {
                m_button();     /* Detect a mouse click                      */
              } while (!w_mouse.rht_but && !w_mouse.lft_but &&
                       !w_mouse.cnt_but);
              m_debounce();     /* Wait a few ms for mouse to settle         */
              if (w_mouse.rht_but)
                  v_prtf("You clicked the right mouse button.\n");
              if (w_mouse.lft_but)
                  v_prtf("You clicked the left mouse button.\n");
              if (w_mouse.cnt_but)
                  v_prtf("You clicked the center mouse button.\n");
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_copyright.
Purpose.....: The mouse driver  software contains a copyright notice embedded
              within  in its code by  the manufacturer.  This function gets a
              pointer to that copyright notice.
Syntax......: char far *m_copyright(void);
Example call: v_prtf("%s\n",m_copyright());
Returns.....: Returns a far pointer to the copyright notice embedded within the
              mouse device driver.  The mouse must be a Microsoft or fully com-
              patible mouse.
Common Use..: Display the copyright notice.
See Also....: m_init,
              m_version.
Example.....: display the copyright notice in your mouse driver.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              v_prtf("Mouse copyright notice: %s\n",m_copyright());
              k_wait(0);
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_curoff.
Purpose.....: Turn the mouse cursor off.  This will update a  flag used by the
              mouse device  driver which keeps track of the number of calls to
              m_curon and m_curoff.  Thus if  you call m_curon twice, you must
              call m_curoff() twice to turn  the mouse  cursor back  off.  The
              cursor field of the w_mouse variable is set to FALSE.
Syntax......: void m_curoff(void);
Example call: if (w_mouse.cursor) m_curoff();
Returns.....: None.
Common Use..: Turn the mouse cursor off.
See Also....: m_curon,
              m_init.
Example.....: Ask the user if he would like to turn the mouse cursor on or off.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if ('Y'==w_ynbox("Would you like to turn the mouse cursor off",0))
                  if (!w_mouse.cursor) /* If the mouse cursor is already off  */
                      ;                /* do not make another call to m_curoff*/
                  else m_curoff();     /* else turn it off                    */
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_curon.
Purpose.....: Turn the mouse cursor on.  This will update a  flag used by the
              mouse device driver which keeps track of the number of calls to
              m_curon and m_curoff.  Thus if you call m_curon twice, you must
              call m_curoff() twice to  turn the mouse cursor back  off.  The
              cursor field of the w_mouse variable is set to TRUE.
Syntax......: void m_curon(void);
Example call: if (!w_mouse.cursor) m_curon();
Returns.....: None.
Common Use..: Turn the mouse cursor on.
See Also....: m_curoff,
              m_init.
Example.....: Ask the user if he would like to turn the mouse cursor on or off.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if ('Y'==w_ynbox("Would you like to turn the mouse cursor on",0))
                  if (w_mouse.cursor) /* If the mouse cursor is already on   */
                     ;                /* do not make another call to m_curon */
                  else m_curon();     /* else turn it on                     */
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_debounce.
Purpose.....: Wait for the mouse to settle.  See concepts section on page 170.
Syntax......: void m_debounce(void);
Example call: m_debounce();
Returns.....: None.
Common Use..: Wait for the mouse to settle after detecting a mouse click.
See Also....: m_button.
Example.....: Wait for the user to click the mouse, then debounce the mouse,
              and say which button was clicked.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              do                /* Wait for the user to click a mouse button */
              {
                m_button();     /* Detect a mouse click */
              } while (!w_mouse.rht_but && !w_mouse.lft_but &&
                       !w_mouse.cnt_but);
              m_debounce();     /* Wait a few ms for mouse to settle */
              if (w_mouse.rht_but)
                  v_prtf("You clicked the right mouse button.\n");
              if (w_mouse.lft_but)
                  v_prtf("You clicked the left mouse button.\n");
              if (w_mouse.cnt_but)
                  v_prtf("You clicked the center mouse button.\n");
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_double.
Purpose.....: Determine if the user double clicked the mouse.  The available
              buttons to test for are listed in w_mouse.h.
Syntax......: int  m_double(int button);
              int button;     Which button to test for.
Example call: if (m_double(M_RIGHT)) break;
Returns.....: TRUE\FALSE flag if the corresponding mouse button was double
              clicked.
Common Use..: Determine if a user clicked the mouse twice.
See Also....: m_button.
Example.....: Ask the user to click the left mouse button.  Then display how
              many times he clicked the button.

              #include "user_int.h"
              void main(void)
              {
              w_init();
              do                /* Wait for the user to click a mouse button */
              {
                m_button();     /* Detect 1st mouse click                    */
              } while (!w_mouse.rht_but && !w_mouse.lft_but &&
                       !w_mouse.cnt_but);
              if (w_mouse.rht_but)
              {
                  if m_double(M_RIGHT)
                     v_prtf("You double clicked the right mouse button.\n");
                  else
                     v_prtf("You clicked the right mouse button once.\n");
              }
              if (w_mouse.lft_but)
              {
                  if m_double(M_LEFT)
                     v_prtf("You double clicked the left mouse button.\n");
                  else
                  v_prtf("You clicked the left mouse button once.\n");
              }
              if (w_mouse.cnt_but)
              {
                  if m_double(M_CENTER)
                     v_prtf("You double clicked the center mouse button.\n");
                  else
                  v_prtf("You clicked the center mouse button once.\n");
              }
              m_debounce();     /* Wait a few ms for mouse to settle */
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_getcur.
Purpose.....: Determine the location of the mouse cursor.  Both the pixel
              and the text cursor location fields of w_mouse are updated.
              The pixel  location is stored pix_row, pix_col and the text
              location is  stored  in txt_row, txt_col.  See the concepts
              section for a discussion of the relation between the  pixel
              and the text coordinates.
Syntax......: void m_getcur(void);
Example call: m_getcur();
Returns.....: None.
Common Use..: Determine if the mouse clicked on a menu item.
See Also....: m_curon,
              m_curoff.
Example.....: Write a small program to continually display the location of the
              mouse cursor.  Note: The w_prtf and  v_prtf temporarily turn the
              mouse cursor off  while  they are printing. Thus, the mouse will
              seem blurry because of the continuous printing.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=w_open(5,5,2,20,TRUE,FALSE,w_color_data,0);
              if (!window) w_exit(1);
              w_prtf(window,"      Pixel  Text\n");
              w_prtf(window,"        \n");
              w_prtf(window," row:\n");
              w_prtf(window," col:");

              do
              {
                 if (m_motion())
                 {
                    m_getcur();            /* Get mouse cursor location   */
                    w_setcur(window,2,6);  /* Print pixel coordinates     */
                    w_prtf(window,"%3d   %3d\n",w_mouse.pix_row,w_mouse.txt_row);
                    w_setcur(window,3,6);  /* Print text coordinates      */
                    w_prtf(window,"%3d   %3d",w_mouse.pix_col,w_mouse.txt_col);
                 }
              }  (!kbhit());
              w_close(window);
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_getpress.
Purpose.....: Detect if a mouse button was pressed.  This is analogous to the
              keyboard function  kbhit().  m_getpress does not read the mouse
              press(Use m_button() for that),but it detects if a mouse button
              press has occurred since the last call to m_getpress.
Syntax......: int  m_getpress(int button);
              int button;    button to test for
Example call: if (!m_getpress(M_RIGHT)) continue;
Returns.....: TRUE\FALSE flag indicating whether the  button has been pressed
              since the last call to m_getpress.
Common Use..: Wait for a mouse button press to occur.
See Also....: m_button,
              m_getrelease.
Example.....: Wait for the user to press a mouse button.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              m_getpress(M_RIGHT); m_getpress(M_LEFT); m_getpress(M_CENTER);
              v_prtf("Press any mouse button.");
                                       /* Detect a mouse click            */
              while (!m_getpress(RIGHT) && !m_getpress(LEFT) &&
                     && !m_getpress(CENTER));
              m_button();              /* Read in mouse click. m_button   */
              if (w_mouse.rht_but)     /* sets mouse button fields        */
                 v_prtf("You pressed the right mouse button.");
              else if (w_mouse.lft_but)
                 v_prtf("You pressed the left mouse button.");
              else if (w_mouse.cnt_but)
                 v_prtf("You pressed the center mouse button.");
              k_wait(0);
              w_exit(0);

                                                     13 - Mouse



Function....: m_getrelease.
Purpose.....: Detect if a mouse button was released. This is analogous to the
              keyboard function kbhit(). m_getrelease does not read the mouse
              press(Use m_button() for that),but it detects if a mouse button
              was released since the last call to m_getrelease.
Syntax......: int  m_getrelease(int button);
              int button;    Left or Right button to test for.
Example call: if (!m_getrelease(RIGHT)) continue;
Returns.....: TRUE\FALSE flag indicating whether the button has been released
              since the last call to m_getrelease.
Common Use..: Wait for a mouse button to be released.
See Also....: m_button,
              m_getpress.
Example.....: Wait for the user to press and release the left mouse button.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              m_getpress(M_LEFT);
              v_prtf("Press the left mouse button.");
              while (!m_getpress(M_LEFT));
              m_button();
              v_prtf("You pressed the left mouse button.");
              v_prtf("Now release it.");
              while(!m_getrelease(M_LEFT));
              v_prtf("You released the left mouse button.");
              k_wait(0);
              w_exit(0);

                                                     13 - Mouse



Function....: m_graphcur.
Purpose.....: Set the  mouse pointer used in graphics modes.  The  bitmap is a
              32 integer  array, with the 1st  16 integers defining the screen
              mask  and the  2nd 16  integers defining  the  cursor  mask.  In
              the CGA graphics modes (320x200),the mouse cursor is only 8 bits
              wide and 16 bits tall.  In all other modes the mouse cursor will
              be 16 bits x 16 bits.  Each 16 integer  pair  defines  a 256 bit
              mask.  The cursor mask defines the shape of the  graphics cursor
              while  the screen  mask defines  how the  cursor  interacts with
              pixels already on the screen.  See the  description of  the text
              mode mouse cursor. The concept is the same, except that the text
              mode  cursor uses  1 integer  for the  screen mask and 1 for the
              cursor mask instead of 16 integers.The row and column parameters
              specify the coordinates of the hot spot within the mouse graphic
              cursor.  This hot spot will be used to determine where the mouse
              is.
Syntax......: void  m_graphcur(int row,int col,int bitmap[32]);
              int row;         Pixel row hot spot
              int col;         Pixel column hot spot
              int bitmap[32];  32 integer bit map of screen/cursor mask
Example call: m_graphcur(1,5,bitmap);
Returns.....: None.
Common Use..: Define your own graphics mouse cursor.The default graphics mouse
              is an arrow.
See Also....: m_textcur.
Example.....: Change the graphics cursor from the default arrow to a hand. The
              example is shown on the following page.


                                                     13 - Mouse



              #include "user_int.h"
              void main(void)
              {
              int bitmap[32]={
                         0x0000, /* Screen. . . . . . . . . . . . . */
                         0x0000, /* Mask. . . . . . . . . . . . . . */
                         0xCFFF, /* . . . . . . . . . . . . . . . . */
                         0xB7FF, /* . . . . . . . . . . . . . . . . */
                         0xB7FF, /* . . . . . . . . . . . . . . . . */
                         0xB7FF, /* . . . . . . . . . . . . . . . . */
                         0xB7FF, /* . . . . . . . . . . . . . . . . */
                         0xB7FF, /* . . . . . . . . . . . . . . . . */
                         0x4B6C, /* . . . . . . . . . . . . . . . . */
                         0x4C92, /* . . . . . . . . . . . . . . . . */
                         0x4C92, /* . . . . . . . . . . . . . . . . */
                         0x4C92, /* . . . . . . . . . . . . . . . . */
                         0x4002, /* . . . . . . . . . . . . . . . . */
                         0x4002, /* . . . . . . . . . . . . . . . . */
                         0x4002, /* . . . . . . . . . . . . . . . . */
                         0x3FFC, /* . . . . . . . . . . . . . . . . */
                                 /*                                 */
                         0x0000, /* Cursor Mask . . . . . . . . . . */
                         0x0000, /* . . . . . . . . . . . . . . . . */
                         0x3000, /* . . x x . . . . . . . . . . . . */
                         0x4800, /* . x . O x . Hot Spot. (3,3) . . */
                         0x4800, /* . x . . x . . . . . . . . . . . */
                         0x4800, /* . x . . x . . . . . . . . . . . */
                         0x4800, /* . x . . x . . . . . . . . . . . */
                         0x4800, /* . x . . x . . . . . . . . . . . */
                         0x4B6C, /* . x . . x . x x . x x . x x . . */
                         0x4C92, /* . x . . x x . . x . . x . . x . */
                         0x4C92, /* . x . . x x . . x . . x . . x . */
                         0x4492, /* . x . . . x . . x . . x . . x . */
                         0x4002, /* . x . . . . . . . . . . . . x . */
                         0x4002, /* . x . . . . . . . . . . . . x . */
                         0x4002, /* . x . . . . . . . . . . . . x . */
                         0x3FFC};/* . . x x x x x x x x x x x x . . */
              w_init();
              v_setmode(0x0E);         /* Change to a graphics mode       */
              m_graphcur(3,3,bitmap);  /* Set mouse graphics cursor       */
              m_curon();               /* Turn the mouse cursor on        */
              k_wait(0);               /* Move your mouse around          */
              w_exit(0);

                                                     13 - Mouse



Function....: m_init.
Purpose.....: Initialize the mouse system.  The installed field of the w_mouse
              variable will be nonzero if a mouse and its driver are installed
              and 0 otherwise. The number of buttons present on the mouse will
              be stored in the num_buttons field of the w_mouse variable. Also
              the mouse text  cursor  shape and attribute  will be restored to
              their  default values.  The  mouse cursor  will be reset  to the
              middle of  the screen.  This should be  called  before any other
              mouse functions.  However, w_init  calls this function so unless
              you need  to  reset the  mouse  at some other time, you need not
              explicitly call this function.
Syntax......: void m_init(void);
Example call: m_init();
Returns.....: None.
Common Use..: Initialize  the  mouse system.  Should be the 1st mouse function
              called.
See Also....: None.
Example.....: Initialize  the  mouse  system before  calling  any other  mouse
              functions.


              #include "user_int.h"
              void main(void)
              {
              m_init();
              if (!w_mouse.installed) exit(0);
              else v_prtf("Mouse present with %d buttons",w_mouse.num_buttons);
              }

                                                     13 - Mouse



Function....: m_keytrans.
Purpose.....: This is  used internally  by various  other  internal functions.
              Its purpose is to determine if the mouse was clicked on 1 of the
              4 mouse  corners of a  window, and with which button.  If one of
              the  corners  was clicked on, m_keytrans returns  the equivalent
              key stroke. This function is used in conjunction with m_setcnrs.
Syntax......: unsigned int m_keytrans(int mouse_cnrs[4][2]);
              int mouse_cnrs[4][2];   Coordinates of the 4 mouse click buttons
Example call: key=m_keytrans(mouse_cnrs);
Returns.....: The character code of the translated  key press if the mouse was
              clicked on  one of the four window mouse corners.  Otherwise, it
              returns 0.
Common Use..: Determine if a user clicked the mouse on one of  the four window
              mouse corners.  Used internally with m_setcnrs() and  by various
              other functions.
See Also....: m_setcnrs.
Example.....: None.

                                                     13 - Mouse



Function....: m_motion.
Purpose.....: Detect mouse movement.This function is analagous to the standard
              library's kbhit() function. kbhit() detects a keyboard press but
              does not read  in the key.  Similarly,  m_motion() detects mouse
              movement but does not get the new coordinates.
Syntax......: int m_motion(void);
Example call: if (m_motion()) break;
Returns.....: TRUE\FALSE flag indicating whether the mouse has moved since the
              last call to m_motion.
Common Use..: Detect if the mouse has moved.
See Also....: m_getcur.
Example.....: See m_getcur example.

                                                     13 - Mouse



Function....: m_setcnrs.
Purpose.....: This is used internally by various other internal functions. Its
              purpose is to place two or four mouse click buttons,depending on
              the parameter cnrs, at the corners of a window and to return the
              coordinates of these click buttons.This function is used intern-
              ally with m_keytrans and by various other functions.
Syntax......: void m_setcnrs(WIN_PTR window,int mouse_cnrs[4][2],int cnrs);
              WIN_PTR window;        Window on which click buttons are situated
              int mouse_cnrs[4][2];  Array to return the  coordinates of  the 4
                                     mouse click buttons
              int cnrs;              Flag  indicating  whether  to place  mouse
                                     clicks on all 4 corners(cnrs=TRUE) or just
                                     2 on the  side of the window (cnrs=FALSE).
Example call: m_setcnrs(window,mouse_cnrs,M_ALL_CNRS);
Returns.....: None.
Common Use..: Place mouse click buttons on a window.
See Also....: m_keytrans.
Example.....: None.

                                                     13 - Mouse



Function....: m_setcur.
Purpose.....: Set a new location for the mouse cursor. Both the  pixel and the
              text cursor location  fields of w_mouse  are updated.  The pixel
              location is stored in pix_row, pix_col and the text location  is
              stored in txt_row, txt_col.  See the concepts section for a dis-
              cussion  of the relation between the pixel and text coordinates.
              If  either coordinate excedes the physical screen, m_setcur will
              be ignored.
Syntax......: void m_setcur(int txt_row,int txt_col);
              int txt_row;    New mouse cursor text row.
              int txt_col;    New mouse cursor text column.
Example call: m_setcur(5,5);
Returns.....: None.  Updates pix_row, pix_col, txt_row, txt_col fields of
              w_mouse.
Common Use..: Move the mouse cursor to a new location.
See Also....: m_getcur.
Example.....: Move the mouse cursor around the screen to a few different
              locations.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (!w_mouse.cursor) m_curon();
              m_setcur(0,0);             /* Put mouse cursor in upper left */
                                         /* hand corner of screen          */
              m_setcur(30,80);           /* Coordinates exceed the physical*/
                                         /* screen size.  Command ignored. */
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_sethor.
Purpose.....: Set the horizontal limit in pixels that a mouse may traverse.
Syntax......: void m_sethor(int lft_lim,int rht_lim);
              int lft_lim;        Left  hand limit.
              int rht_lim;        Right hand limit.
Example call: m_sethor(160,200);
Returns.....: None.
Common Use..: Limit the horizontal range of the mouse.
See Also....: m_setver.
Example.....: Limit the mouse to the left side of the screen.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              m_sethor(0,320);
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_setver.
Purpose.....: Set the vertical limit in pixels that a mouse may traverse.
Syntax......: void m_setver(int low_lim,int upp_lim);
              int low_lim;      Lower limit.
              int upp_lim;      Upper limit.
Example call: m_setver(0,200);
Returns.....: None.
Common Use..: Limit the vertical range of the mouse.
See Also....: m_sethor.
Example.....: Limit the mouse to the bottom half of the screen.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              m_setver(100,200);
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_textcur.
Purpose.....: Define the text mode mouse cursor.   The cursor  and screen mask
              determine  the mouse character  and attributes.  This is done in
              the  following manner.  The mouse driver saves the character and
              its attribute at  the current screen location.  Then, the 16 bit
              integer (1 byte for the character and 1 byte for its attribute),
              of the character  at the current screen location is "and"ed with
              the 16 bit integer screen mask. Next, the result is "xor"ed with
              the cursor mask.  The result of all this yields a 16 bit integer
              which is the 2 bytes used to describe the mouse cursor character
              and its  attribute.  Pretty simple, huh?  See the example below.
Syntax......: void m_textcur(int screen_mask, int cursor_mask);
              int screen_mask;   Screen attribute mask
              int cursor_mask;   Cursor definition
Example call: m_textcur(0x7F00,0x7F18);
Returns.....: None.
Common Use..: Define a new mouse cursor in text mode.
See Also....: m_graphcur.
Example.....: Set the mouse text mode cursor to a blinking dollar sign.

              #include "user_int.h"
              void main(void)
              {
              /*                          7 6 5 4 3 2 1 0
              Text mode attribute byte,  Ŀ
              where:                     
              bit 7   = blinking bit
                  4-6 = Background color
                  3   = Foreground intensity
                  0-2 = Foreground color

                  Screen   Cursor
                   Mask     Mask      Result
               Ŀ
                   0       0         0    
                   0       1         1    
                   1       0     Unchanged
                   1       1     Inverted 
               

                                                     13 - Mouse



              Lets look at the attribute byte 1st.
              screen mask attribute: 7F = 0111 1111
              cursor mask attribute: FF = 1111 1111
              
              resulting   attribute:    = 1III IIII

              Substituting this result into the text mode attribute byte,
              we see that the blink bit is set, while both the background
              and foreground colors will be inverted.

              Next, the cursor mask.
              screen mask character: 00 = 0000 0000
              cursor mask character: 24 = 0010 0100
              
              resulting   character: 24 = 0010 0100

              Thus, since 24h is the ascii code for a dollar sign, the result
              will be a blinking dollar sign in inverted color.

              You can use the Result table shown above to determine which will
              be set given a screen and cursor mask.
              */

              int screen_mask=0x7F00,
                  cursor_mask=0xFF24;
              w_init();
              m_textcur(screen_mask,cursor_mask);
              m_curon();
              k_wait(0);
              w_exit(0);
              }

                                                     13 - Mouse



Function....: m_version.
Purpose.....: Get the  mouse driver version in BCD format,the interrupt request
              line being used, and the mouse type.  The global variable w_mouse
              has the version, irq, and type fields set by  this function.  The
              mouse types are defined in w_mouse.h and are listed below as well

               Mouse types
              
              M_UNKNOWN  -  0
              M_BUS      -  1
              M_SERIAL   -  2
              M_INPORT   -  3
              M_PS_2     -  4
              M_HP       -  5

Syntax......: int m_version(void);
Example call: m_version();
Returns.....: The mouse version in BCD format if the call is supported.  Other-
              wise, zero is returned.  Also sets the w_mouse global fields men-
              tioned above.
Common Use..: Get some information about the mouse being used.
See Also....: m_copyright,
              m_init.
Example.....: Get information about your mouse.


              #include "user_int.h"
              void main(void)
              {
              char *types[6]={"Unknown","Bus","Serial","Port","PS/2","HP"};

              w_init();
              m_version();                     /* Get mouse info      */
              v_prtf("Mouse driver version: %2d.%1d%1d\n",
              (w_mouse.version & 0x0F00)>>8,
              (w_mouse.version & 0x00F0)>>4,
               w_mouse.version & 0x000F);
              v_prtf("Mouse uses IRQ%d\n",w_mouse.irq);
              v_prtf("Mouse type: %s\n",types[w_mouse.type]);
              w_exit(0);
              }

                                                     14 - Printer



                                  Chapter 14

                                   Printer



                                                     14 - Printer



    Overview

    Whether to print out reports, to capture a graphics screen, or just to get
a hardcopy of a  program  your working on, the  printer is  a pretty  valuable
accessory. Whether you own a color laser printer or the lowliest of dot matrix
printers, you can spice up your printing with these many print commands.

    Concepts

    The C  User Interface  Library provides  printer support through a printer
database.  This  database contains  a list of printer  manufacturers  and  the
models they make.  Along with each printer model is a list of printer specific
information  which includes the  Escape  sequences that  comprise the printers
command  language  and the various  status codes  the printer  returns.  Since
printer status codes are not standardized, each printer is allowed to set it's
own return  codes.  Thus, for  example, when  the printer is  out of paper, an
Epson LQ printer may return a  38h while an IBM pro printer may  return a 28h.
This non-standardization is also seen in the proliferation of printer  command
languages.  Continuing with the Epson\IBM example  above, an Epson  LQ printer
would use the  sequence <Esc w 1> to  turn double high  printing on, while the
IBM pro printer would use  the sequence <Esc [ @ 4 0 0 0 17 0> to  perform the
same task. Thus, to eliminate this printer model dependency, the C User Inter-
face Library maintains  the printer model dependant information in a database,
printer.dat, and loads the command language  and status codes into memory when
a particular printer is selected.  This frees the programmer from any  need to
concern himself with printer specific code. However, this places the burden of
identifying the correct printer type on the end user. This should be of little
inconvenience, since  the printer manufacturer and model are printed right  on
the printer itself.  Then, once the  printer and corresponding port are set by
the end user,the information is saved in setup.dat and the end user never need
worry about the printer again.  Another major advantage of this method is that
it allows any end user who finds that a printer is not listed in  the database
to add his printer information to the database.  This is a  huge bonus for the
programmer.  Several  utilities are  included which  help the  end user  add a
printer to the database.  This includes:

    1. prt_stat - Determine your printer's unique status codes
    2. prt_test - Test your  printer's command language  to make sure that you
                  have correctly added the right information into the database
    3. prt_indx - Create companion index file for printer.dat.

    The format for adding a printer to the database is  provided when you reg-
ister with Mathware.Having the database format will allow you to add printers.
Also, as  part of the  license, you are granted  the right  to distribute  the
database and it's format to your end users along with your  application.  This
will allow  users of your  applications to also add  their own printers to the
database.  When you register, you  will be sent a copy of the printer database
format.

                                                     14 - Printer



      You the programmer, can use the printer commands without worrying if the
user's printer supports the commands. If the printer does support the command,
then  the print  will come  out as  you want it.  If not, the  command will be
ignored  and the text  will be printed out normally.  For example, you may use
the p_color() routine to select a printer color.  Most printers do not support
color.  Thus, in most cases, this command will be ignored. If, by chance, your
program is  run by  someone who does  happen to have a color printer, then the
text  will be printed in  your selected color.  The point is, you have nothing
to lose by specifying these fancy print commands.  It doesn't hurt to add them
in to your programs, with  the exception of  the added memory required for the
function call.

      So let's get down to some details. How does all this work?  First, let's
look at  the PRINTER structure, defined in w_printr.h, and used to define  the
global variable w_printer.


typedef struct                         /* This structure is only used if app  */
{                                      /* is running on a DOS stand alone pc. */
    char  flag;                        /* TRUE if redirected to a disk file   */
    char  path[128];                   /* Name of file                        */
    FILE *handle;                      /* Disk file handle                    */
}   REDIRECT;                          /*                                     */

typedef struct
{
    char            model[3][P_MODEL_LENGTH+1],     /* Name of printer        */
                    emulation[3][P_MODEL_LENGTH+1]; /* Emulation commands     */
    unsigned char   cur_port;          /* Currently selected port             */
    REDIRECT        redirected;        /* Whether printer redirected to file  */
    PRINT_CONTROL   old_capture;       /* Novell capture setup for default LPT*/
    unsigned char **commands;          /* Escape sequence commands            */
    int             num_printers;      /* Number of printers in database      */
    int             num_ports;         /* Number of parallel ports available  */
} PRINTER;


The global variable, w_printer, defined in w_global.c,is of type PRINTER. This
structure is a bit complicated so let's go over it. Since IBM pc's can have up
to three parallel ports, LPT1, LPT2, LPT3, with a  different printer hooked up
to each port, the structure allows for 3 different printer models. The name of
each printer is stored in the model field. For those people who are not hooked
up to a network,all this may seem a bit superfluous, since most pc's come with
only a single  parallel port.  However, those connected to a network know that
you  may set up a  printer on each port and often send print jobs to different
printers through the various ports. If a printer uses emulation, the emulation
command is  stored in the emulation field.  Next, the cur_port field holds the
parallel  port number through  which  all printing  will be  done.  All  print
functions use this field to select a parallel port to send their output. What-
ever printer is connected to the port specified by cur_port will be the one to
receive the printer output.  Thus, although you may have three printers avail-
able to you, only 1 printer is selected at a time.You may change the currently
selected  printer port  by calling  p_set_port(), or by using w_setup().  Only

                                                     14 - Printer



parallel printers  are supported.  The redirected field  is used  internally to
redirect the  printer output to a disk  file rather  than to  a printer.  It is
discussed in  more detail  in the p_redirect() function.  The old_capture field
is  used internally  to disable  the timeout feature of captured  ports on net-
works.  This is strictly an internal field and  should never be modified.  Next
is the commands field.  This is  an array containing the  printer specific com-
mands and status codes.You don't need to understand how this field works unless
you want to add a printer to the database.  Since the setup.dat file saves your
printer types and currently selected port, the commands  field is automatically
loaded with  the printer  specific information from the printer.dat database by
w_init().  Then, whenever a call to a  print function is made,the C User Inter-
face Library passes the needed printer information to the print function  being
called so that the call works properly on the selected printer. The next field,
num_printers, is simply the total number of printers currently supported by the
database. You never need to worry about this field. It is used internally only.
Finally, num_ports contains the  number of parallel ports found on your system.
This is the w_num_parallel_ports global,which is set by w_init() along with the
num_ports field.

     Since we will be continually  adding printers to the database, we can  not
send out  update  notices each time we add another printer.  You should however
order a printer update  disk (10$) once a year, or once every six months or so.
You will  be sent the updated  master  database kept  on file here at Mathware,
with the latest printers supported.  Thus, when you find a  printer that is not
currently  supported, it would  be greatly appreciated  if you would  send us a
copy of  the printer commands and status codes  so that we  can  add it  to our
master list.  This benefits both us here at  Mathware, and you the user. First,
we are able to maintain  a comprehensive list of  printers and include as  much
support for the various printers  as possible. This makes the library more use-
full and hence improves it's overall quality. This in turn gives your applicat-
ions the same printer  support.  No single  person has access to every  printer
type.  By everyone adding  the commands and status codes  to the database them-
selves when  they find an unsupported printer, everyone gains support  for that
printer,without ever having to read that particular printer manual  and without
ever having  to test  and debug the command language and codes.  Also, when you
send in  a new printer to be  added to the database, you will  automatically be
sent the latest copy of the printer database FREE. This is a small incentive, I
know, but by doing so everyone profits. The draw back  to this is that Mathware
can not test the printer  commands since we won't  have access to the  printer.
Therefore, do your  best to  make sure  the printer  commands and  status'  are
indeed correct  before you forward a copy to us.  However, should you  discover
an  error in any  printer language, please let us know.  As stated  above, when
you  send in a  new printer  to be supported, if it  is indeed  an  unsupported
printer, you will be  sent  the latest  copy of the printer database FREE.  If,
however, we already have that  printer on  file, you will not  receive any word
from us.  This  is because of the frequency with which  this happens.  We would
go out of business if  we sent a response  letter to every person.  So, if  you
do not receive  your free printer update disk within two weeks, you must assume
that we already  had it on file.  While we  thank you for  your efforts, we can
not send you a free disk.  Sorry.  Really.

                                                     14 - Printer



     If you are  going to be using the  various printer commands, you  need to
have the  printer files, printer.dat and  printer.ntx, and  setup.dat, in your
current directory or in a directory located on the DOS path. Otherwise, print-
ing will not be available to your application.

                                                     14 - Printer



                         Function List


       Routine           Description
                  
       p_char_set        Set a character set.
       p_code            Read the printer status byte.
       p_color           Select the print color.
       p_end             End a print job.
       p_font            Select a printer font.
       p_height          Select a character height and width.
       p_init            Initialize\Reset a printer.
       p_orientation     Select Landscape or Portrait paper orientation.
       p_pause           Suspend printing.
       p_prtchr          Print a single character.
       p_prtf            Print a formatted string.
       p_quality         Select the print quality.
       p_redirect        Redirect a parallel port to a disk file.
       p_restore         Restore a redirected parallel port.
       p_set_port        Select a port for printing.
       p_start           Start a print job.
       p_style           Select a print style.

                                                     14 - Printer



Function....: p_char_set.
Purpose.....: Dot matrix  printers support 2 character sets when printing the
              extended ascii  codes (characters  with ascii codes between 128
              and 255).  The valid character sets are P_SET_1 and P_SET_2 and
              are listed in w_printr.h.  Dot Matrix printers vary in how they
              implement these two character sets.On Epson Dot Matrix printers,
              the first character set causes the extended ascii characters to
              duplicate  the normal  ascii (0-127) characters, but  they  are
              printed in italics.  Selecting  the 2nd  set on an  Epson, will
              cause the extended ascii to be printed as they should be. On an
              IBM Dot Matrix printer, the 1st set causes some of the extended
              ascii to be interpreted as control characters (ascii 0-31). The
              2nd set allows the extended  ascii to be printed as they should
              be.  Thus, unless you have some  reason to do so, the 2nd char-
              acter  set should be selected  when using Dot  Matrix printers.
              On HP Laser Printers, this command switches between primary and
              secondary fonts. On HP Laser printers, the printer commands use
              the primary font, so P_SET1 should be selected.
Syntax......: int  p_char_set(int set);
              int set;    1 of 2 character sets to use.
Example call: p_char_set(P_SET1);
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command.
Common Use..: Selecting the 2nd set on Dot Matrix printers allows the printing
              of extended ascii characters.
See Also....: None.
Example.....: Demonstrate how the extended ascii characters are interpreted
              under each character table.  Assume we are using a Dot Matrix
              printer.

              #include "user_int.h"
              void main(void)
              {
              int i;
              WIN_PTR window;

              w_init();
              window=p_start();        /* Get printer ready              */

                                                     14 - Printer



              if (window)              /* If successful, print           */
              {
              p_char_set(P_SET1);      /* Use 1st char set for ext ascii */
              for (i=128;i<256;++i)
                   p_prtf("Ascii: %d   Char: %c\n",i,i);
              p_char_set(P_SET2);      /* Use 2nd char set for ext ascii */
              for (i=128;i<256;++i)
                   p_prtf("Ascii: %d   Char: %c\n",i,i);
              }
              p_end(window);           /* End print job\Clear p_start msg*/
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_code.
Purpose.....: Read the printer status.  This returns  the exact printer status
              byte, using BIOS call 17h, service 02h. According to Novell,they
              have stopped supporting DOS service 0xE0, type 0x06, which  gets
              the printer status for network printers.  Thus, we use  the BIOS
              service 0x02 for both network and local printers. Since printers
              return different status  codes for  the same  situation, you may
              want to see exactly  how your printer responds. For example, IBM
              printers return 0x00 when the printer is  turned on, but is off-
              line. EPSON returns 0x18. The format of the status code is shown
              below.

                                Printer status byte

              bit  description (if set)
                
               7   Printer not busy
               6   Printer acknowledge
               5   Out of paper
               4   Printer selected
               3   I/O error
               2   unused
               1   unused
               0   Printer timed out

Syntax......: unsigned char p_code(int port);
              int  port;   Printer port to test.
Example call: if (p_code(LPT1)!=0x90) break;
Returns.....: Single byte printer status code.
Common Use..: Get the exact printer status code for your particular printer.
See Also....: None.

                                                     14 - Printer



Example.....: Display the printer status codes for your printer.


              #include "user_int.h"
              void main(void)
              {
              v_prtf("Turn your printer on, and make sure it is on_line.\n");
              k_wait(0);
              v_prtf("Status code: %2.2X\n",p_code(LPT1));
              v_prtf("Take you printer off-line.\n");
              k_wait(0);
              v_prtf("Status code: %2.2X\n",p_code(LPT1));
              v_prtf("Bring your printer on-line and take the paper out.\n");
              k_wait(0);
              v_prtf("Status code: %2.2X\n",p_code(LPT1));
              v_prtf("Turn your printer off.");
              k_wait(0);
              v_prtf("Status code: %2.2X\n",p_code(LPT1));
              k_wait(0);
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_color.
Purpose.....: Select a color on  color printers.  This will  be ignored  if the
              printer  is  not  a color printer.  The  valid printer colors are
              listed in w_printr.h.
Syntax......: int  p_color(int color);
              int  color;   Color to print in.
Example call: p_color(P_GREEN);
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command.
Common Use..: Make headings stand out from the normal text.
See Also....: None.
Example.....: Print a line of text in each color.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();        /* Get printer ready             */
              if (window)              /* If successful, print          */
              {
                  p_color(P_BLACK);
                  p_prtf("Hello world.\n");
                  p_color(P_MAGENTA);
                  p_prtf("Hello world.\n");
                  p_color(P_CYAN);
                  p_prtf("Hello world.\n");
                  p_color(P_VIOLET);
                  p_prtf("Hello world.\n");
                  p_color(P_YELLOW);
                  p_prtf("Hello world.\n");
                  p_color(P_ORANGE);
                  p_prtf("Hello world.\n");
                  p_color(P_GREEN);
                  p_prtf("Hello world.\n");
              }
              p_end(window);           /* End print job\Clear p_start msg*/
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_end.
Purpose.....: End a  Print Job.  This  function is the  companion function  to
              p_start().  These 2 functions form an inseparable pair.  Neither
              should be used without the other. p_end() ends a print job. This
              function is  really only  necessary on  networks, but since  you
              usually don't know whether your program will be run on a network
              or not,it is best to write the application for network use to be
              safe.  p_end()  also closes the p_start()  message  window.  All
              printing should be done using a p_start()\p_end() bracket, ie, a
              call to p_start(), then all  printing, then a call to p_end() as
              shown below.

              p_start()
              .
              .      All printing done here
              .
              p_end()

              If the  current port has been  redirected to a file, p_end() re-
              stores the port back to the printer.
Syntax......: void p_end(WIN_PTR window);
              WIN_PTR window;    window returned from p_start().
Example call: p_end(window);
Returns.....: None.
Common Use..: End a print job.
See Also....: p_start().
Example.....: Use p_start() to initialize  the printer,  print a line of text,
              and then call p_end() to close the p_start() message  window and
              to end the print job.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();               /* Initialize the printer      */
              if (window)                     /* If printer ready, send text */
                 p_prtf("Some sample text sent to the printer.\n");
              p_end(window);                  /* Close window, end print job */
              w_exit(0);                      /* Exit program                */
              }

                                                     14 - Printer



Function....: p_font.
Purpose.....: Load a new printer font.  A list of printer fonts  can be found
              in w_printr.h.  All subsequent  text will  be printed using the
              selected  font.
Syntax......: int  p_font(int font);
              int  font;    Font to load.
Example call: p_font(P_ROMAN);
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command.
Common Use..: Separate sections of text.
See Also....: p_height,
              p_style.
Example.....: Print a line of text demonstrating some fonts.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();        /* Get printer ready               */
              if (window)              /* If ready, start print job       */
              {
                  p_font(P_ROMAN);
                  v_prtf("Hello world\n");
                  p_font(P_SANS_SERIF);
                  v_prtf("Hello world\n");
                  p_font(P_COURIER);
                  v_prtf("Hello world\n");
                  p_font(P_PRESTIGE);
                  v_prtf("Hello world\n");
                  p_font(P_SCRIPT);
                  v_prtf("Hello world\n");
                  p_font(P_ORATOR);
                  v_prtf("Hello world\n");
              }
              p_end(window);           /* End print job\Clear p_start msg */
              w_exit(0);
              }


                                                     14 - Printer



Function....: p_height.
Purpose.....: To set the character height and width. A list of valid character
              heights and widths are listed in w_printr.h.  Note:  Quad height
              is not supported by most printers, but single and double  height
              are supported by every printer on the market.
Syntax......: int  p_height(int height,int width);
              int height;   Character height.
              int width;    Character width.
Example call: p_height(P_NORMAL_HEIGHT,P_DOUBLE_WIDTH);
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command.
Common Use..: Print Large headings and small text.
See Also....: p_subscript,
              p_superscript.
Example.....: Print a line of text demonstrating all six possible  combinations
              of text height and width.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();        /* Get printer ready               */
              if (window)              /* If printer ready, print         */
              {
                  p_height(P_NORMAL_HEIGHT,P_NORMAL_WIDTH);
                  p_prtf("Hello World.\n");
                  p_height(P_NORMAL_HEIGHT,P_DOUBLE_WIDTH);
                  p_prtf("Hello World.\n");
                  p_height(P_DOUBLE_HEIGHT,P_NORMAL_WIDTH);
                  p_prtf("Hello World.\n");
                  p_height(P_DOUBLE_HEIGHT,P_DOUBLE_WIDTH);
                  p_prtf("Hello World.\n");
                  p_height(P_QUAD_HEIGHT,P_NORMAL_WIDTH);
                  p_prtf("Hello World.\n");
                  p_height(P_QUAD_HEIGHT,P_DOUBLE_WIDTH);
                  p_prtf("Hello World.\n");
              }
              p_end(window);           /* End print job\Clear p_start msg */
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_init.
Purpose.....: Initialize the  printer and reset  all settings to the default.
              The  initialization  string for printers is  used to  clear all
              settings  and return the  printer to  its initial startup  mode
              using all default settings.
Syntax......: int p_init(void);
Example call: p_init();
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command
Common Use..: Reset  the printer after using various fonts and styles so that
              the printer is  in its default state  at the start of  the next
              print job.
See Also....: None.
Example.....: Print some  text using a  font and  then reset  the printer and
              print the same text.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              window=p_start();          /* Get printer ready              */
              if (window)                /* If successful, print           */
              {
                  p_font(P_SCRIPT);      /* Print Hello in script          */
                  p_prtf("Hello.\n");    /* Now print hello sideways       */
                  p_init();              /* Reset printer settings         */
                  p_prtf("Hello.\n");    /* Print Hello using defaults     */
              }
              p_end(window);             /* End print job\CLear p_start msg*/
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_orientation.
Purpose.....: Choose which direction, Landscape or  Portrait, the printer will
              print in. Portrait is the normal vertical way of printing, while
              Landscape is sideways printing. Landscape is most often used for
              graphs and wide reports. On most printers, changing printer dir-
              ection issues a form feed.
Syntax......: int p_orientation(int direction);
              int direction;     Which direction to print
Example call: p_orientation(P_LANDSCAPE);
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command.
Common Use..: Select Landscape for graphs or wide reports.
See Also....: None.
Example.....: Print some text in both Landscape and Portrait orientations.

              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              window=p_start();          /* Get printer ready              */
              if (window)                /* If successful, print           */
              {                          /* Print Hello normally           */
                  p_orientation(P_PORTRAIT);
                  p_prtf("Hello.\n");    /* Now print hello sideways       */
                  p_orientation(P_LANDSCAPE);
                  p_prtf("Hello.\n");
              }
              p_end(window);             /* End print job\CLear p_start msg*/
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_pause.
Purpose.....: Pause printer.  Give user a chance  to abort printing during the
              print session.  If the  user presses a  key or  clicks the mouse
              while printing is being  done, p_pause will ask the  user if  he
              wishes to  continue or quit.  If the user wants to quit, p_pause
              will return FALSE.
Syntax......: int  p_pause(void);
Example call: if (!p_pause()) exit(0);
Returns.....: TRUE\FALSE flag  indicating  whether the user wishes to continue
              printing or to abort.p_pause returns TRUE unless the user wishes
              to quit the print job, in which case FALSE is returned.
Common Use..: Cancel printing if you made a mistake.
See Also....: None.
Example.....: Print some text and give the user a chance to abort.


              #include "user_int.h"
              void main(void)
              {
              char *word="Hello";
              WIN_PTR window;
              int  i;

              w_init();                /* The user may decide that he's had */
              window=p_start();        /* enough after printing "Hello" 250 */
              if (window)              /* times.  p_pause lets him break out*/
              {                        /* of the loop.                      */
                  for(i=0;i<1500 && p_pause();++i)
                      p_prtf("%s\n",word);
              }
              p_end(window);           /* End print job\clear p_start msg   */
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_prtchr.
Purpose.....: Send a single character to  the printer.  No translation  is per-
              formed.  The character is  sent exactly as it  appears.  p_prtchr
              can be used regardless of whether w_init() was called with a TRUE
              or FALSE.
Syntax......: int  p_prtchr(unsigned char ch);
              unsigned char ch;   Character to print.
Example call: p_prtchr('A');
Returns.....: TRUE\FALSE  flag  indicating  whether the  printer  accepted the
              character.
Common Use..: Send Escape sequences to the printer.
See Also....: p_prtf.
Example.....: Eject the page when printing is done.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();        /* Get printer ready               */
              if (window)              /* If successful, print            */
              {
                  p_prtf("Hello\n");
                  p_prtchr(FORM_FEED);
              }
              p_end(window);            /* End print job\Clear p_start msg*/
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_prtf.
Purpose.....: Print formatted text.  This is the printer  analogy to the video
              v_prtf and window w_prtf.  Note: Some printers don't  handle the
              '\n' character, LINE_FEED, properly.  p_prtf  converts  the '\n'
              character to a LF\CR pair.  Thus, p_prtf should  not be used  to
              send ESC sequences to the printer.  Also, p_prtf prints only non
              zero ascii codes.  Another reason why it can not be used to send
              ESC sequences.
Syntax......: int  p_prtf(char *format,...);
              char *format;    Format string.
Example call: p_prtf("%d %f %c %s\n",23,5.34,'A',"Hello.");
Returns.....: TRUE\FALSE flag indicating whether printer accepted all of the
              characters.
Common Use..: Print formatted output.
See Also....: p_prtchr.
Example.....: Print some text.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();         /* Get printer ready              */
              if (window)               /* If successful, print           */
                  p_prtf("%2d \n %c %s\n",123,'Q',"Squid.");
              p_end(window);            /* end print job\clear p_start msg*/
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_quality.
Purpose.....: Select quality of printer output. Letter quality is better looking
              than  draft  but much  slower.  The  valid qualities are listed in
              w_printer.h.  They are P_LETTER_QUALITY and  P_DRAFT_QUALITY.
Syntax......: int  p_quality(int quality);
              int quality;     Flag indicating Letter Quality of Draft Quality.
Example call: p_quality(P_LETTER_QUALITY);
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command.
Common Use..: Select  Draft  quality  for  faster  speed  when  quality is not
              important. Use Letter quality when appearance is important.
See Also....: p_font.
Example.....: Print some text in both Letter Quality and draft modes.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();          /* Get printer ready       */
              if (window)                /* If successful, print    */
              {
                  p_quality(P_LETTER_QUALITY);
                  p_prtf("Hello.\n");
                  p_quality(P_DRAFT_QUALITY);
                  p_prtf("Hello.\n");
              }
              p_end(window);             /* End print job\CLear p_start msg*/
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_redirect.
Purpose.....: Redirect the  currently selected  parallel  port to a disk file.
              This causes all printing to be sent to a disk file instead of to
              a printer.  Only one parallel port may be  redirected at a time.
              Thus, you can not select port LPT1, redirect it  to a disk file,
              and then select port LPT2 and redirect  that port as well.  When
              a printer is redirected to a file, several pieces of information
              are stored in the w_printer global variable.The redirected field
              has the structure shown below, which is defined in w_printr.h.

              typedef struct
              {
                  char  flag;
                  char  path[128];
                  FILE *handle;
              }   REDIRECT;

              The flag field is set to TRUE (1) when a  parallel port is redi-
              rected to a disk file,and reset to FALSE (0) when it is assigned
              to a printer.  The path field has the name of the disk file. The
              handle  field is reset to 0 also  when the parallel  port is re-
              stored to the printer. Depending on whether you are on a network
              or  not, the handle field  is set differently.  If  you are on a
              network, the handle is simply set to TRUE (1).  If  you are on a
              stand  alone DOS machine, then the  handle  contains the  stream
              handle pointer to the disk file. If the disk file already exists
              its contents are destroyed.
              Note:  Due to a Novell bug, redirection of a  parallel port to a
                     file  does  not work on  networks.  This is  as of  Shell
                     version 3.11.
Syntax......: p_redirect(char *file);
              char *file;     Name of disk file to redirect printer to
Example call: p_redirect("C:\\printer.dmp");
Returns.....: TRUE\FALSE flag indicating whether the port has been redirected.
              Also, the global "w_printer.redirected" field is filled  in with
              the appropriate information.
Common Use..: Save printed output to a disk so that it may be printed out later.
See Also....: p_end,
              p_restore.
Example.....: Redirect the currently selected port to a disk file and then do
              some printing.

                                                     14 - Printer



              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              if (!p_redirect("C:\\print.fil"))/* Select LPT1 as default  */
                  w_exit(1);                   /* Abort if unsuccessful   */
              window=p_start();                /* Get printer ready       */
              if (!window) w_exit(1);          /* Abort if unsuccessful   */
              p_prtf("This text will be sent to the file\n");
              p_prtf("So will this\n");        /* Print text              */
              p_end(window);                   /* Close file and restore  */
              w_exit(0);                       /* parallel port to printer*/
              }

                                                     14 - Printer



Function....: p_restore.
Purpose.....: Restore a parallel  port that has been redirected to a disk file
              back  to the  printer attached to the  port.  This  function  is
              called automatically by p_end(), so it is not necessary to do so
              after you are done printing.
Syntax......: int  p_restore(void);
Example call: p_restore();
Returns.....: TRUE\FALSE flag indicating whether the port has been restored.
Common Use..: Restore a redirected parallel port back to its original printer.
See Also....: p_end().
Example.....: Select parallel port LPT3 as the default port, and redirect it to
              a file.  When you are done  printing, instead of  letting p_end()
              automatically restore the port back to the printer for  us, let's
              do it ourselves explicitly with p_restore.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              p_set_port(LPT3)                /* Select LPT3 as default   */
              if (!p_redirect("C:print.dmp")) /* Redirect LPT3 to a file  */
                  w_exit(1);                  /* Abort if unsuccessful    */
              window=p_start();               /* Initialize printing      */
              if (!window) w_exit(1);         /* Abort if unsuccessful    */
              p_prtf("This text will be printed in the file\n");
              p_prtf("So will this\n");       /* Print text               */
              p_restore();                    /* Close file explicitly and*/
              w_exit(0);                      /* restore LPT3 to printer  */
              }

                                                     14 - Printer



Function....: p_set_port.
Purpose.....: Select a parallel printer port as the default. The port selected
              will  be  used  by all  print  functions.  The  global  variable
              w_printer, whose  structure  is listed in w_printr.h, will  have
              it's cur_port field updated to reflect the newly  selected port.
Syntax......: int  p_set_port(int port);
              int port;            Parallel port to be used as default
Example call: p_set_port(LPT1);
Returns.....: TRUE\FALSE flag indicating whether port has been made the default.
Common Use..: Switch to a printer on another port.
See Also....: None.
Example.....: Print some text on  a printer on  parallel port 1, then switch to
              parallel port 2, and print some text on that printer.



              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              if (!p_set_port(LPT1))          /* Select LPT1 as default  */
                  w_exit(1);                  /* Abort if unsuccessful   */
              window=p_start();               /* Get printer ready       */
              if (!window) w_exit(1);         /* Abort if unsuccessful   */
              p_prtf("This text will be printed on the printer ");
              p_prtf("connected to LPT1.\n"); /* Print text              */
              p_end(window);                  /* End Print Job           */
              if (!p_set_port(LPT2))          /* Select LPT2 as default  */
                  w_exit(2);                  /* Abort if unsuccessful   */
              window=p_start();               /* Get printer ready       */
              if (!window) w_exit(2);         /* Abort if unsuccessful   */
              p_prtf("This text will be printed on the printer ");
              p_prtf("connected to LPT2.\n"); /* Print text              */
              p_end(window);                  /* End Print Job           */
              w_exit(0);
              }

                                                     14 - Printer



Function....: p_start.
Purpose.....: Initialize  the printer system  and determine if the  printer is
              ready to  start printing.  p_start will display a message to the
              user to align the  print head before printing  is begun.  If the
              printer has been redirected to a file,the file name will be dis-
              played. If the printer is not redirected, then if the printer is
              not on or not on-line, p_start() will allow the user to retry by
              pressing any key, or to quit by pressing ESC. If the user quits,
              then the message will be cleared. If the user is able to fix the
              problem, then a message that  the printer is currently  printing
              will be displayed. p_start() forms a function pair with p_end().
              These two  functions  should  always be  used together  whenever
              printing is  done.  All printing  functions should be  used only
              after a successful call to p_start().  p_end() should be  called
              when you have finished printing.  Thus, all your printing should
              be bracketed by calls to p_start()  and p_end() as  shown below.

              p_start()
                 .
                 .  printing done here
                 .
              p_end()

              p_end() will clear the p_start message window as  well as end the
              print job.  If you are on  a network, p_start() will  disable the
              timeout of the  captured port for  the duration of the print job.
              The timeout count is restored by p_end(). If you are on a network
              then p_end() will also end the  print job, and flush the job from
              the print queue and send it to the printer.
Syntax......: WIN_PTR p_start(void);
Example call: window=p_start();
Returns.....: Pointer to a print message window.  If the user  is on-line and
              ready to start  printing, a  valid window  pointer is  returned.
              Otherwise, NULL Is returned.
Common Use..: Make sure the printer is  ready to accept  print and signal the
              start of a print job.
See Also....: p_end,
              p_pause.
Example.....: Make sure the printer is on-line before printing.

                                                     14 - Printer



              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();        /* Wait for user to get printer ready */
              if (window)              /* If printer ready, print some text  */
                  p_prtf("Hello world.\n");
              p_end(window);           /* End print job, clear p_start msg   */
              w_exit(0);               /*                                    */
              }

                                                     14 - Printer



Function....: p_style.
Purpose.....: Select a  print style.  The various print  styles are listed in
              w_printr.h.  The print style remains in effect until you either
              select another print style or turn the current print style off.
Syntax......: int  p_style(int style,int flag);
              int style;           Print style
              int flag;            On or off
Example call: p_style(P_ITALIC,ON);
Returns.....: TRUE\FALSE flag indicating whether printer accepted the command.
Common Use..: Make text stand out.
See Also....: p_font.
Example.....: Display a line of text in some sample styles.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              window=p_start();          /* Get printer ready              */
              if (!window) w_exit(1);    /* Abort if not ready             */
              p_style(P_ITALIC,ON);      /* Else print                     */
              p_prtf("Hello World.\n");
              p_style(P_ITALIC,OFF);
              p_prtf("Hello World.\n");
              p_style(P_EMPHASIZED,ON);
              p_prtf("Hello World.\n");
              p_style(P_EMPHASIZED,OFF);
              p_prtf("Hello World.\n");
              p_end(window);             /* End print job\Clear p_start msg*/
              w_exit(0);
              }

                                                     15 - Network



                                  Chapter 15

                                   Network

                                                     15 - Network



    Overview

    Today's applications have to be network aware.  Nearly every business uses
networks to increase  productivity and  to cut  costs  (Mainframes  cost  huge
amounts of money).  Since  Novell has evolved as the main PC network supplier,
capturing nearly 60% of the market, only Netware specific network commands are
available.  It  just isn't worth  the time, money, and effort  to develop  the
commands for the rest of the network manufacturers.

    Every aspect of  computer programming becomes  much more complicated  when
done on a LAN (as opposed to a  standalone pc).  Issues such as  file locking,
shared printers, resource management, etc, all take  on added responsibilities
when performed on a network.

    Concepts

    Let's begin with a discussion of Netware basics.  Netware stores all  it's
information in a structure called the Bindery.  This Bindery is located in two
hidden files, NET$BIND.SYS and NET$BVAL.SYS.  The Bindery holds all the infor-
mation about the  user's, the file  servers, print servers, print queues, etc.
The  information  stored in  the Bindery  is broken down  into  things  called
objects.  Thus, every file server is stored in the Bindery as an object, as is
the default Print  Server, etc.  Each object has 6 fields associated  with it.
These fields are:

     Object fields
     
     1. Object id
     2. Object name
     3. Object type
     4. Object flag
     5. Object security
     6. Properties flag

     Now, we'll discuss  each field in detail.  To start, the  object id  is a
unique 4 byte number assigned to each object.  No two objects have the same id
number.  Think of the object id as  a fingerprint.  Just as no two people have
the same fingerprints, no  two objects may have the same object id.  Thus, al-
though "Erik" and "Tia" may both be users, they are guaranteed to have differ-
ent object ids.  Next is the object name.  This may or may not be unique.  For
example, there may  be two users  named "Axel".  However, object names usually
are unique in that network managers  rarely give two  different  Print Servers
the same name, etc.  The object name may be up to 47 characters long.  Next is
the object type.  The object  type is a 2 byte field which describes what kind
of object the object is. Netware has defined several object types,and some are
listed below and on the following page.

     Object types
     
     1.  Unknown
     2.  User
     3.  User group
     4.  Print Queue
     5.  File Server

                                                     15 - Network



     Object types (cont)
     
     6.  Job server
     7.  Gateway
     8.  Print Server
     9.  Archive Queue
     10. Archive Server
     11. Job Queue
     12. Administration
     13. Remote bridge
     14. Reserved
     15. Wild card

     All Print Queues are stored in objects of type Print Queue. All users are
stored in objects  of type User.  These object types have all  been defined in
w_netwrk.h, so  don't worry about the 2 byte number associated with each type.
The next field is  object flag.  The object flag field is a 1 byte field which
indicates whether an object is static or dynamic.  Static objects always exist
once they are created, until they are explicitly deleted. Dynamic objects  are
usually created by the network administrator.  For  example, the user's of the
network are most definitely static objects. A dynamic object exists only until
the File  Server is rebooted, or the until the  object  is deleted.  Thus, you
might create a dynamic object (used id) for a repair technician to use for the
day until he fixes your problem.  Then, his user  id is  automatically deleted
when you reboot the machine.  The object security field is very important.  It
is a 1 byte field which controls access to the object.  The object security is
broken into 2  nibbles (4 bits).  The 1st nibble  controls who  may  read  the
object, and the 2nd nibble controls who may modify the object. Each nibble has
the same format, which is shown below.

      Access level       Object security (nibble)
             
      Anyone             0 0 0 0
      Logged in          0 0 0 1
      Object itself      0 0 1 0
      Supervisor         0 0 1 1
      Netware only       0 1 0 0

As an example of how the object security byte is encoded,  suppose we  have an
object that is allowed to be read (viewed) by anyone who is logged in, but may
only be modified by Netware or the supervisor.  The object security byte would
then be: 0 0 0 1 0 1 1 1 = 0x17.  Finally, the last field of an object is it's
property field. This 1 byte field will be non-zero(0xFF) if the object has any
properties, and zero otherwise.  If the object  has  properties, then they are
stored in a sub structure which has the following fields:

      Property Fields
      
      1. Property name
      2. Property flags
      3. Property security
      4. Property value

                                                     15 - Network



     First, the  property name, is a 16 byte  field which can  hold a 15  byte
property  name and a  NULL terminator.  Netware  has some predefined  property
names, but you are allowed to create your own as well.  Some of the predefined
names are shown below.

      Property Names
      
      1.  ACCOUNT_BALANCE
      2.  ACCOUNT_SERVERS
      3.  GROUPS_I'M_IN
      4.  GROUP_MEMBERS
      5.  IDENTIFICATION
      6.  LOGIN_CONTROL
      7.  NET_ADDRESS
      8.  OPERATORS
      9.  PASSWORD
      10. SECURITY_EQUALS

The property flags field is 1 byte long and tells whether the object is static
or dynamic, and whether it is an item or a set.  The format is shown below:

      Property Flag
      
      . . . . . . . 0    Static
      . . . . . . . 1    Dynamic
      . . . . . . 0 .    Item
      . . . . . . 1 .    Set
      x x x x x x . .    Reserved

Next is the  property security.  This field  is exactly the same as the object
security, except that it applies to the object's properties. The field is also
a single byte long,and has the exact same format as the object security field.
The last property  field is the property values flag.  Also  a 1 byte field, a
0x00 indicates  that the property  has no  value, and a  0xFF indicates that a
value is present.  Property values are stored in 128 byte records.  A property
may have more than 1 value.

      Now that you know how and where Netware stores its information, lets see
what we can do with this information.  Let's start  by looking at how printing
changes  when done on  a network printer.  BIOS  service 17h is  used to  send
characters to the printer.  On a stand alone pc, this is no big deal. However,
things get complicated very quickly when done on a network printer.  A network
printer is shared by multiple users.  First, suppose you print out a document,
and use different printer  fonts and sizes, and  maybe even colors.  Now, when
the next person comes along, the printer is no longer in its default state,but
instead is still in the state that you left it in,with whatever size and fonts
you  happen to have used last. This  can easily be fixed by each new print job
sending a setup  string to place the printer back in  its default state.  Now,
suppose, you start printing out a document.Hans in the next office over starts
printing out his document.  Both of  you send your documents to be printed out
on the laser printer.  When you both go to get  your documents, you  find that
lines of your document are interspersed with his, ruining both your documents.
One solution is  for Hans to wait  for you to finish printing, and then he can
send his  document to the printer.  However, every  time you wanted  to  print

                                                     15 - Network



something, you would have to  call every single person in your  office to make
sure  noone else  is going to use the printer.  Not a very realistic solution.
Netware gets around both of these problems by capturing the ports used to send
data to the printer.  Netware redirects the data  you send to the printer to a
Print Queue on  a Print Server.  This Print Server determines which  print job
gets control of the printer and who has to wait.  The only  problem that still
remains is how Netware knows when a print job is finished. For example,suppose
you print out  a heading, then do  some very time  consuming math computations
which take a few seconds, say 10 seconds, and then you print out your results.
How does Netware know when your done printing. The normal way to do this is by
setting the Timeout feature of each captured printer port.The standard timeout
is 2 seconds.  Thus, when you first start sending data to the printer(eg,using
any of The C User Interface Library print routines, ie, p_prtf, p_style, etc.)
Netware takes the print stream data and stores it in a buffer.So lets say your
program is  humming along, printing out things, doing some computations,  then
printing out more things, and continuing  along this way until your program is
finished. The Timeout(2 seconds in our example) tells Netware that if there is
ever a time  period of 2 seconds or more where the  printer does  not  receive
data,then the program must have finished, so send the buffered print stream to
the Print Queue for printing.  This is a good method for printing uninterrupt-
able print jobs (ie, the print data is continuous and can not be interrupted).
However, what if  you are printing  out a document, this  manual for  example,
which takes  about 4 hours to  print.  The prt_man utility  uses the p_pause()
function to allow the user to pause the printing if  something goes wrong (ie,
a paper jam or running out of paper,etc). Then, if the user pauses the printer
for more than 2 seconds, Netware will think that the program is done, and send
his document to the printer,even if the printer was paused right in the middle
of a page.  Obviously, this is no good. The best way around this, and the best
way to print out a document, is to disable the Timeout by setting it to 0. But
how does Netware know when you are done  printing? Well, it doesn't.  With the
Timeout disabled, it has no way of knowing. This is why you have to explicitly
tell Netware that you are done, by canceling the capture on the port, Luckily,
you don't need to worry about any of this.  The C User Interface  Library pro-
vides 2 functions, p_start() and p_end(),which handle all of these details for
you, and operates appropriately, depending  on whether you are on a network or
on a stand alone pc.  Thus, just prior to printing, you should call p_start().
p_start() will make sure the printer is on and online, and disable the timeout
of the captured port through which your printing will be done. As soon as your
done, call p_end() to  flush the print stream  and to send  it to the printer.
The concept is shown below.

      p_start()
      .
      .  Do your printing here
      .
      p_end()

                                                     15 - Network



Although network printing can get pretty ugly,The C User Interface Library has
tried to make  it as  easy for you as  possible.  One last word  about Netware
printing.  Each printer  has many Netware options associated  with  it.  These
options include  the number of  copies, the type of  form (paper) used, banner
name, etc. These options are not very important, and you will rarely ever need
to be concerned with them.  However, should you want to play around with them,
you may use the functions n_capture_get()\set() to do so.  These functions use
a  structure type  called PRINT_CONTROL, which is defined in  w_netwrk.h.  See
n_capture_get\set for more information.

     Next, we'll talk about logging in and  out of a  network, something which
doesn't even exist on stand alone pcs.  The first thing everyone has to do, is
to login to the Network.  Several  things happen  when  this  occurs.  Netware
assigns you a connection number, which is a number between 1 and 100.  You are
also assigned a  network number, a workstation  number, and a  socket  number.
The network number identifies the current default File Server on a multiserver
network.  The  workstation  number (node) is a 6 byte address which identifies
each workstation on the network.  Together, these numbers are used so that you
may  communicate with the File Server and also  with other pcs on the network.
Since network communication functions are not provided in this version,we will
not discuss them in detail. They should, however, be available in  version 2.0
of The  C User Interface  Library.  You are  then attached  to a default  File
Server. You may optionally attach yourself to as many as 8 File Servers. The C
User Interface Library  provides functions for you to login in and out, and to
attach and detach from File Servers.

     File and Record locking are also  issues that pertain only to network run
applications.  Since it  is possible for two different  users to open the same
file at  the same time, a problem  arises when one person tries to read a file
while  another is trying to  write to it.  The File Server  gives everyone who
opens the  file a copy  of it.  The original remains on the File Server's hard
drive.  Netware controls who is allowed access to  the file through the file's
attributes, which is an extension of DOS's attributes. Netware adds the Shared
and Created attribute.  If a   file is  allowed to  be opened by more than one
person  at a time, it  is marked as  shared.  Also, the creator (owner) of the
file is also recorded.  DOS 3.0  and later allow a user to lock a file region.
File locking is used in one of  two ways. Either a record  or group of records
is locked, or the entire file is  locked.  Since The C User  Interface Library
does not provide functions  for file  and record locking, we will  not discuss
them further.

                                                     15 - Network



      These are just  some basic facts about  Novell's Netware.  There is much
more to Netware, and we refer you to the Novell manuals for any further infor-
mation you may require. However,do note that some of the fields in the network
functions  are stored in reverse byte  order.  See n_int and  n_long for  more
information.

                                                     15 - Network



                         Function List


       Routine           Description
  
n_bindery_default_server Get the default File Server handle
n_bindery_object_id      Get an objects unique id
n_bindery_object_list    Get a list of all objects of a given object type
n_bindery_object_name    Get an objects name
n_bindery_object_scan    Search the bindery for remaining objects
n_bindery_property_list  Get a list of properties of a given object
n_bindery_property_scan  Search the bindery for an object's properties
n_bindery_value_list     Get a list of values for a given property
n_bindery_value_name     Extract names from a value
n_bindery_value_scan     Search the bindery for a property's values
n_capture_active         Determine if a port has been captured
n_capture_banner_get     Set the banner name for printing
n_capture_banner_set     Get the banner name
n_capture_cancel         Cancel the capturing of the print stream on a port
n_capture_end            End the capturing of the print stream on a port
n_capture_file           Redirect the capturing of a port to a disk file
n_capture_flush          Flush the print stream of a captured port
n_capture_get            Get the capture settings of a port
n_capture_queue          Select a Print Queue for a captured port
n_capture_set            Set the capture settings of a port
n_capture_start          Capture the print stream for a port
n_connection_number      Get the connection number for a given work station
n_dir_get_effective_rights Get effective rights for a directory
n_dir_get_maximum_rights Get maximum rights for a directory
n_dir_get_volume         Get the volume name of an associated directory
n_dir_handle             Get a directory's handle
n_drive                  Determine if a drive is a local or network drive
n_file_get_ext_attr      Get a files extended attributes
n_file_set_ext_attr      Set a files extended attributes
n_int                    Reverse bytes in a 2 byte value
n_internet_address       Get the network node\number of a user
n_IPX                    Determine if IPX is loaded (and hence Netware)
n_local_connection_num   Get the connection number of the current work station
n_long                   Reverse bytes in a 4 byte value
n_NETBIOS                Determine if NETBIOS is installed
n_server_attach          Attach to a File Server
n_server_detach          Detach from a File Server
n_server_login           Login to the default File Server
n_server_logout          Logout from all File Servers
n_SHARE                  Determine if SHARE is installed
n_SPX                    Determine if SPX is installed
n_TTS                    Determine if TTS is installed
n_user_name              Get a user's name from a connection number
n_version                Get the Netware version


                                                     15 - Network



Function....: n_bindery_default_server.
Purpose.....: Get the File Server number.  Since there can be  up to 8 File
              Servers on a single network, this function returns the number
              for the current default File Server.  This function is needed
              internally by a few of the other network functions.
Syntax......: int n_bindery_default_server(void);
Example call: handle=n_bindery_default_server();
Returns.....: A number between 1 and 8,representing the default File Server's
              number is returned.
Common Use..: Used internally by some other network functions.
See Also....: None.
Example.....: Get the number for your currently attached default File Server.


              #include "user_int.h"
              void main(void)
              {
              int server_num;

              w_init();
              server_num=n_bindery_default_server();
              v_prtf("Default File Server Number: %d",server_num);
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_bindery_object_id.
Purpose.....: Get an  objects unique id number.  You need to  have the objects
              name and type in order to call  this function.  A list  of valid
              object types can be found in w_netwrk.h.
Syntax......: unsigned long int n_bindery_object_id(char *object_name,
                                unsigned object_type);
              char    *object_name;    Desired object's name
              unsigned object_type;    Desired object's type
Example call: id=n_bindery_object_id("NORD",N_USER);
Returns.....: If the call is  successful, then the object's  unique id is re-
              turned.  Otherwise, if the call was unsuccessful or if the app-
              lication is not on a Novell network, FALSE is returned.
Common Use..: Get a user's unique id in order to perform pc - pc communication.
See Also....: n_bindery_object_list,
              n_bindery_object_name,
              n_bindery_object_scan.
Example.....: Suppose  you  have a Print Queue  defined  on  your  network  as
              "LASER_QUEUE".  Get the object id for this Print Queue.


              #include "user_int.h"
              void main(void)
              {
              unsigned long int print_queue_id;

              w_init();
              print_queue_id=n_bindery_object_id("LASER_QUEUE",N_PRINT_QUEUE);
              if (print_queue_id)             /* If non-zero, successful*/
                  v_prtf("LASER_QUEUE object id: %ld\n",print_queue_id);
              else
                  v_prtf("Unable to get Print Queue object id\n");
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_bindery_object_list.
Purpose.....: List all objects of a given type in a menu and let the user pick
              one.  A list of object types can be found in w_netwrk.h.  Infor-
              mation about the selected object is returned in a structure type
              called N_BINDERY_OBJECT, which is also defined in w_netwrk.h and
              listed below.  Netware has an object type for N_USERs.  However,
              this returns a list of all users defined on the network.Mathware
              has therefore defined the object type  N_LOGGED_IN_USER in order
              to return a list of the users  currently logged in.  This is the
              only function for which the N_LOGGED_IN_USER  object type is de-
              fined.  Do  not use this type  with any other network  function.
              Although object names may be up to 47  characters long, the menu
              list uses 30.
Syntax......: int n_bindery_object_list(int row,int col,int num_rows,
                  int num_cols,ATTRIBUTE color,WIN_PTR *window,
                  N_BINDERY_OBJECT *object,unsigned object_type,int shdw,
                  char *title,char *help_word)
              int row;                  Screen row to display menu
              int col;                  Screen col to display menu
              int num_rows;             Number of rows   in menu
              int num_cols;             Number of columns in menu
              ATTRIBUTE color;          Menu color
              WIN_PTR *window;          Pointer to a scrolling menu window
              N_BINDERY_OBJECT *object; Holds returned object information
              unsigned object_type;     Object type
              int shdw;                 TRUE\FALSE flag indicating whether
                                        shadows should be drawn
              char *title;              Menu title
              char *help_word;          Used to retrieve context sensitive help
                                        whenever the help key (F1) is pressed.
Example call: ret_code=n_bindery_object_list(6,2,10,1,w_color_menu,&window,
                       &object,N_PRINT_QUEUE,w_shadows,"Print Queues","queues");
Returns.....: 0 : Index of object selected. The selected objects information
                   is returned in the "N_BINDERY_OBJECT *object".
              -1 : User pressed ESC
              -2 : Not on a Novell network
              -3 : Insufficient memory
              -4 : Number of objects found excedes 256 maximum
              -5 : No matching objects found
              -6 : Bindery error  (Server out of memory, Invalid name,
                                   No such object,Server Bindery locked,
                                   Bindery failure).
              Also, the window structure is set to the scrolling menu.  If  the
              return code is -1,then the menu was displayed and you must close
              it yourself. Information about the selected object is returned in
              the  object variable.  The object variable is of  type N_BINDERY_
              OBJECT which is defined in w_netwrk.h and reprinted below.

                                                     15 - Network



              typedef struct                 /* Bindery Object               */
              {                              /*                              */
                  unsigned long id;          /*                              */
                  unsigned int  type;        /*                              */
                           char name[48];    /*                              */
                  unsigned char flag;        /*                              */
                  unsigned char security;    /*                              */
                  unsigned char property;    /* TRUE if object has properties*/
              }   N_BINDERY_OBJECT;          /*                              */
Common Use..: Display a list of all users, Print Queues, File Servers, etc.
See Also....: n_bindery_object_id,
              n_bindery_object_name,
              n_bindery_object_scan.
Example.....: Display a list of all Print Queues on the Network.


              #include "user_int.h"
              void main(void)
              {
              int ret_code;                   /* Return code             */
              WIN_PTR window;                 /* Scrolling menu window   */
              N_BINDERY_OBJECT object;        /* Return info in this var */

              w_init();
              ret_code=n_bindery_object_list(6,2,10,1,w_color_menu,&window,
                       &object,N_PRINT_QUEUE,w_shadows,"Print Queues",
                       ".queues");
              if (w_isopen(window)) w_close(window);
              }

                                                     15 - Network



Function....: n_bindery_object_name.
Purpose.....: Given an objects unique object id, get the objects name. Bindery
              objects are uniquely determined by their 4 byte id.  You may get
              the object's corresponding name by calling this function.
Syntax......: int n_bindery_object_name(unsigned long int object_id,
                  char *object_name);
              unsigned long object_id;     Objects unique id
              char         *object_name;   Holds object's name on return
Example call: ret_code=n_bindery_object_name(user_id,user_name);
Returns.....: If the call is successful,then TRUE is returned and the object's
              name is returned in the "object_name" variable.  Otherwise, FALSE
              is  returned.  FALSE is also returned if you are not  on a Novell
              network.
Common Use..: Get an objects name.
See Also....: n_bindery_object_id,
              n_bindery_object_list,
              n_bindery_object_scan.
Example.....: Suppose your File Server has an object id of 0xAF363421. Get the
              name of the File Server.


              #include "user_int.h"
              void main(void)
              {
              char server_name[48];           /* Object name can be 47 bytes */
              unsigned long server_id=0xAF363421;/* Objects unique id        */

              w_init();
              if (n_bindery_object_name(server_id,server_name))
              {                               /* Display name if successful  */
                  v_prtf("File Server: %s\n",server_name);
                  k_wait(0);
              }
              else                            /* Otherwise display error msg */
                 w_errbox(0,"Unable to get File Server name.");
              w_exit(0);                      /* Exit program normally       */
              }

                                                     15 - Network



Function....: n_bindery_object_scan.
Purpose.....: Scan the Bindery for an object and optionally for all subsequent
              matching objects as  well.  The  object is  searched  for in the
              Bindery by name and type. Wild cards are allowed for both.If you
              are looking for a specific object, then copy the object type and
              name into  the corresponding  fields of the N_BINDERY_OBJECT ob-
              ject, whose structure is defined in w_netwrk.h and reprinted be-
              low. If you wish to search for multiple objects of a given type,
              or for multiple  objects of a given  name, you should  specify a
              wild card as the object  name or type.  For example, if you  are
              trying to find all  objects of type  N_USER, set  the name to N_
              WILD_CARD_NAME, which is  defined in w_netwrk.h  as "*", and the
              type field to N_USER.If you are trying to find all objects named
              "LIEF", set the type to N_WILD_CARD_TYPE, defined in  w_netwrk.h
              as 0xFFFF, and the  name field  to "LIEF".  Also, the  object_id
              field should be set  to N_WILD_CARD_ID, defined as 0xFFFFFFFF in
              w_netwrk.h, for the first call to n_bindery_object_scan.  Subse-
              quent calls will return an object_id in this field. You may copy
              this field  to another  variable if you  need it.  However,  you
              should not alter this field.  n_bindery_scan_object() uses  this
              field to mark  where it  left off in  the search.  When the last
              object is read, 0xFC is returned.  The example should  clear all
              this up for you.

              typedef struct
              {
                  unsigned long id;
                  unsigned int  type;
                           char name[48];
                  unsigned char flag;
                  unsigned char security;
                  unsigned char property;
              }  N_BINDERY_OBJECT;
Syntax......: int n_bindery_object_scan(N_BINDERY_OBJECT *object);
              N_BINDERY_OBJECT *object;    Used to pass information to the
                                           function and also holds return
                                           information.
Example call: ret_code=n_bindery_object_scan(&object);
Returns.....: 0x00 - Successful
              0x96 - Server out of memory
              0xEF - Invalid name
              0xFC - No such object or not on a network
              0xFE - Server Bindery locked
              0xFF - Bindery failure
Common Use..: Get all  information available  about an object, and  to get  all
              objects of the same type.

                                                     15 - Network



See Also....: n_bindery_object_id,
              n_bindery_object_list,
              n_bindery_object_name.
Example.....: Get Bindery  information about  user "JON".  Then get a  list of
              all users.

              #include "user_int.h"
              void main(void)
              {
              N_BINDERY_OBJECT object;

              w_init();
              object.type=n_int(N_USER);      /* Object type is USER     */
              object.name="JON";              /* Specifically, user JON  */
              object.id=N_WILD_CARD_ID;       /* First call to scan()    */
              n_bindery_object_scan(&object); /* Get info from Bindery   */
              /* On return, object has all info on user JON              */
              v_prtf("User: %s    object id: %ld\n",object.name,object.id);
              /* Now, lets get info on every user on the network         */
              object.type=n_int(N_USER);      /* We want info on users   */
              strcpy(object.name,N_WILD_CARD_NAME);/* All users          */
              object.id=N_WILD_CARD_ID;       /* Only on 1st call        */
              v_prtf("User                               Object id\n");
              while (0x00==n_bindery_object_scan(&object))
              {
                     v_prtf("%s  %ld",object.name,object_id);
                     strcpy(object.name,N_WILD_CARD_NAME);
              };
              k_wait():                       /* Pause to view users     */
              w_exit(0);                      /* exit program            */
              }

                                                     15 - Network



Function....: n_bindery_property_list.
Purpose.....: List all properties of a given object in a menu and let the user
              pick one.  Objects  have  properties, which  are  simply  asciiz
              strings with a maximum length of 15 characters.  A list  of pre-
              defined Netware  properties is contained in w_netwrk.h, although
              the network supervisor may define his own.
Syntax......: int n_bindery_object_list(int row,int col,int num_rows,
                  int num_cols,ATTRIBUTE color,WIN_PTR *window,
                  N_BINDERY_PROPERTY *prop,char *object_name,
                  unsigned int object_type,int shdw,char *title,
                  char *help_word);
              int row;                  Screen row to display menu
              int col;                  Screen col to display menu
              int num_rows;             Number of rows   in menu
              int num_cols;             Number of columns in menu
              ATTRIBUTE color;          Menu color
              WIN_PTR *window;          Pointer to a  scrolling menu  window
              N_BINDERY_PROPERTY *prop; Holds returned property  information
              char *object_name;        Name of object to get properties for
              unsigned int object_type; Object type
              int shdw;                 TRUE\FALSE flag indicating whether
                                        shadows should be drawn
              char *title;              Menu title
              char *help_word;          Used to retrieve context sensitive help
                                        whenever the help key (F1)  is pressed.
Example call: ret_code=prop_sel=n_bindery_property_list(6,25,10,1,w_color_menu,
                       &window,&property,"ERIKA",N_USER,w_shadows,
                       "Erika's Properties",0);
Returns.....: 0 : Index of property selected. The selected property's infor-
                   mation is returned in the "property" parameter.
              -1 : User pressed ESC
              -2 : Not on a Novell network
              -3 : Insufficient memory
              -4 : Number of properties found excedes 256 maximum
              -5 : No matching properties found
              -6 : Bindery error  (Server out of memory, Invalid name,
                                   No such object,Server Bindery locked,
                                   Bindery failure).
              Also, the window structure is set to the scrolling menu.  If  the
              return code is -1,then the menu was displayed and you must close
              it yourself. Information  about the selected property is returned
              in the  property  variable.  The property variable is of type  N_
              BINDERY_PROPERTY which  is defined  in w_netwrk.h  and  reprinted
              on the following page.

                                                     15 - Network



              typedef struct
              {
                  char          name[16];
                  unsigned char flag;
                  unsigned char security;
                  unsigned long sequence_num;
                  unsigned char value;
              }   N_BINDERY_PROPERTY;
Common Use..: Display a list of all groups belonged to, full name, security
              rights, etc.
See Also....: n_bindery_property_scan,
              n_bindery_value_list,
              n_bindery_value_name,
              n_bindery_value_scan.
Example.....: Display a list of the properties of the user "SUPERVISOR".


              #include "user_int.h"
              void main(void)
              {
              int ret_code;                   /* Return code             */
              WIN_PTR window;                 /* Scrolling menu window   */
              N_BINDERY_PROPERTY property;    /* Return info in this var */

              w_init();
              ret_code=n_bindery_property_list(6,25,10,1,w_color_menu,
                       &window,&property,"SUPERVISOR",N_USER,w_shadows,
                       "Supervisor Properties",0);
              if (w_isopen(window)) w_close(window);
              w_exit(1);
              }

                                                     15 - Network



Function....: n_bindery_property_scan.
Purpose.....: Scan the Bindery for a property of a specific object and option-
              ally for all subsequent  matching properties.  Information about
              a property is returned in a structure of type N_BINDERY_PROPERTY
              which is defined in w_netwrk.h and shown below.  w_netwrk.h also
              contains a  list of Netware  predefined properties  although the
              network supervisor may additionally define his own. The property
              is searched  for by the object's name and type, and by the prop-
              erty's  name and  sequence  number.  As an  example, one  of the
              predefined  Netware  properties is "GROUPS_I'M_IN".  Suppose you
              want to see if user "Anders" is a member of any groups. Then you
              could call n_bindery_property_scan() to find out.If he does, you
              could subsequently call n_bindery_value_scan to find out exactly
              which groups he belongs to. Alternatively, you may also find all
              properties of user "Anders" by repeatedly calling n_bindery_prop
              erty_scan().  This would enable you to find out if he belongs to
              any groups, if a full name is defined for him, etc.  However, an
              object may have  many properties, but which ones  are accessible
              to you depends on the property's security,as discussed previous-
              ly in the concepts section.  Each property is  a NULL terminated
              ascii string, at most 16 characters long. Wild cards are allowed
              in the sequence number and property name. This is used in making
              repeated  calls to  obtain a  complete list  of properties for a
              given object.  The sequence number is a four byte number used by
              Netware  to keep track  of where it  currently is in  the search
              list of properties.If you are searching for a specific property,
              copy the property name into the name field of the N_BINDERY_PROP
              ERTY structure, and  set the sequence  number to N_WILD_CARD_ID.
              If you want to search for multiple properties, as before,set the
              sequence number to N_WILD_CARD_ID,but this time set the property
              name to N_WILD_CARD_NAME. In making multiple calls, the sequence
              number is  set to N_WILD_CARD_ID only  for the first call.  Each
              call will return a new sequence number.This sequence number must
              not be changed, as Netware  uses it to keep track of where it is
              in the search list for properties. See the examples below for an
              illustration of each type of call.  When the last property of an
              object has been read, 0xFB is returned.

             typedef struct
             {
                 char          name[16];
                 unsigned char flag;
                 unsigned char security;
                 unsigned long sequence_num;
                 unsigned char value;
             }   N_BINDERY_PROPERTY;

Syntax......: int n_bindery_property_scan(N_BINDERY_PROPERTY *property,
                  char *object_name,unsigned int object_type);
              N_BINDERY_PROPERTY *property;    /* Holds property return info */
              char *object_name;               /* Object to get property for */
              unsigned int object_type;        /* Object's type              */

                                                     15 - Network



Example call: ret_code=n_bindery_property_scan(&property,"SUPERVISOR",N_USER);
Returns.....: 0x00 - Successful
              0x96 - Server out of memory
              0xEF - Invalid name
              0xFB - No such property or not on a network
              0xFE - Server Bindery locked
              0xFF - Bindery failure
Common Use..: Get all properties of an object.
See Also....: n_bindery_property_list.
Example.....: In the first  example, see if  the SUPERVISOR belongs  to any
              groups.  The second example gets a list of all properties for
              the SUPERVISOR.

              /* Example 1 - Make a single call */
              #include <string.h>
              #include "user_int.h"
              void main(void)
              {
              int ret_code;
              N_BINDERY_PROPERTY property;

              w_init();
              property.sequence_num=N_WILD_CARD_ID;
              strcpy(property.name,N_GROUPS_IM_IN);
              ret_code=n_bindery_property_scan(&property,"SUPERVISOR",N_USER);
              switch (ret_code)
              {
                 case 0xFB:
                      v_prtf("Supervisor doesn't belong to any groups.\n");
                 break;
                 case 0x00:
                      v_prtf("Supervisor belongs to groups.\n");
                      v_prtf("Call n_bindery_value_scan()\\list()\n");
                      v_prtf("to find out the group names.\n");
                 break;
                 default:
                      v_prtf("Network error.\n");
                 break;
              }
              k_wait():                       /* Pause to view message   */
              w_exit(0);                      /* exit program            */
              }

                                                     15 - Network



              /* Example 2 - Make repeated calls.  Get a list of all */
              /*             properties.                             */
              #include <string.h>
              #include "user_int.h"
              void main(void)
              {
              N_BINDERY_PROPERTY property;

              w_init();
              property.sequence_num=N_WILD_CARD_ID;
              strcpy(property.name,N_WILD_CARD_NAME);
              v_prtf("Property Names\n\n");
              while (n_bindery_property_scan(&property,"SUPERVISOR",N_USER)==0)
              {
                     v_prtf("%s\n",property.name);
                     if (property.flag & N_DYNAMIC) v_prtf("Dynamic\n");
                     else                           v_prtf("Static\n");
                     if (property.flag & N_SET)     v_prtf("Set\n");
                     else                           v_prtf("Item\n");
                     switch (property.security & 0x0F)
                     {     /* Examine low nibble for read security */
                        case N_READ_SEC_ANYONE:
                             v_prtf("Anyone Read");
                        break;
                        case N_READ_SEC_LOGGED_IN:
                             v_prtf("Logged in Read");
                        break;
                        case N_READ_SEC_OBJECT:
                             v_prtf("Object Read");
                        break;
                        case N_READ_SEC_SUPERVISOR:
                             v_prtf("Supervisor Read");
                        break;
                        case N_READ_SEC_NETWARE:
                             v_prtf("Netware Read");
                        break;
                     }    /* Examine high nibble for write security */
                     switch (property.security & 0xF0)
                     {
                        case N_WRITE_SEC_ANYONE:
                             v_prtf("Anyone Write");
                        break;
                        case N_WRITE_SEC_LOGGED_IN:
                             v_prtf("Logged in Write");
                        break;
                        case N_WRITE_SEC_OBJECT:
                             v_prtf("Object Write");
                        break;
                        case N_WRITE_SEC_SUPERVISOR:
                             v_prtf("Supervisor Write");
                        break;
                        case N_WRITE_SEC_NETWARE:
                             v_prtf("Netware Write");
                        break;
                     }
                     strcpy(property.name,N_WILD_CARD_NAME);

                                                     15 - Network



              }
              k_wait():                       /* Pause to view properties*/
              w_exit(0);                      /* exit program            */
              }

                                                     15 - Network



Function....: n_bindery_value_list.
Purpose.....: List all values of a given property in a menu and let the user
              pick one.  Given a property of an object, this  function lists
              all the values of the property. A value, stored in the struct-
              ure N_BINDERY_VALUE, is  contained in a 128 byte (N_VALUE_LEN)
              buffer.  A value  may be one of two types: Set or Item.  A set
              is a list of 4 byte ids. Thus,since a value is 128 bytes long,
              a single value may contain up to 32 4 byte ids.  These  4 byte
              ids correspond to objects,whose names may be gotten by calling
              n_bindery_object_name().  However,  a  function  is  provided,
              n_bindery_value_name(), which does this. Just as with strings,
              ie, ending with a terminating NULL  character, set values have
              their id list terminated with a NULL id,ie, 0x00000000. There-
              fore, in order to  get all the names associated with a list of
              ids in a value, you would simply  call n_bindery_object_name()
              successively, moving over 4  bytes in the value each time.  An
              example  is shown below, to clear up  any questions.  Next, if
              the value is  an item, then the  structure of the value is not
              known.  You're just out of luck.  The one exception to this is
              if the property is "IDENTIFICATION",in which case the value is
              simply an  asciiz string.  Calls to get value information from
              the bindery use the structure shown below.

              typedef struct
              {
                  unsigned char value[N_VALUE_LEN];
                  unsigned char more_segments;
                  unsigned char property_flag;
              }   N_BINDERY_VALUE;

              n_bindery_value_list()  displays  a menu of  all values  for a
              given property of an object.  Although a value set  contains a
              list of 4 byte ids, when you select a value from the menu, the
              unselected ids are removed from the list, and only the one you
              selected will be found in the value field.
Syntax......: int n_bindery_value_list(int row,int col,int num_rows,
                  int num_cols,ATTRIBUTE color,WIN_PTR *window,
                  N_BINDERY_VALUE *value,char *object_name,
                  unsigned int object_type,char *property_name,int shdw,
                  char *title,char *help_word);
              int row;                  Screen row to display menu
              int col;                  Screen col to display menu
              int num_rows;             Number of rows in menu
              int num_cols;             Number of columns in menu
              ATTRIBUTE color;          Menu color
              WIN_PTR *window;          Pointer to a scrolling menu window
              N_BINDERY_VALUE *value;   Holds returned value information
              char *object_name;        Name of object whose value is desired
              unsigned int object_type; Type of object whose value is desired
              char *property_name;      Name of property whose value is desired
              int shdw;                 TRUE\FALSE flag indicating whether
                                        shadows should be drawn

                                                     15 - Network



              char *title;              Menu title
              char *help_word;          Used to retrieve context sensitive help
                                        whenever the help key (F1) is pressed.
Example call: n_bindery_value_list(6,38,10,1,w_color_menu,window,&value,
              "JONERIC",N_USER,"GROUPS_I'M_IN",w_shadows,"Groups",0);
Returns.....: 0 : Index of value selected. The selected objects information
                   is returned in the "BINDERY_OBJECT *object".
              -1 : User pressed ESC
              -2 : Not on a Novell network
              -3 : Insufficient memory
              -4 : Number of values found excedes 256 maximum
              -5 : No matching values found
              -6 : Bindery error  (Server out of memory, Invalid name,
                                   No such object,Server Bindery locked,
                                   Bindery failure).
              Also, the window structure is set to the scrolling menu.  If  the
              return code is -1,then the menu was displayed and you must close
              it yourself.  Information about the selected value is returned in
              the value variable. The value variable is of type N_BINDERY_VALUE
              which is defined in w_netwrk.h.
Common Use..: Get a list of all values of a given property of an object.
See Also....: n_bindery_object_list,
              n_bindery_object_name,
              n_bindery_object_scan,
              n_bindery_property_list,
              n_bindery_property_scan,
              n_bindery_value_name,
              n_bindery_value_scan.
Example.....: Display a list of all groups belonged to by the supervisor.

              #include <string.h>
              #include "user_int.h"
              void main(void)
              {
              long id;                        /* id of selected set value*/
              char name[48];                  /* Selected value's name   */
              N_BINDERY_VALUE value;          /* Holds value info        */
              int ret_code;                   /* Return code             */
              WIN_PTR window;                 /* Scrolling menu window   */


                                                     15 - Network



              w_init();
              ret_code=n_bindery_value_list(5,5,10,1,w_color_menu,&window,
                       &value,"SUPERVISOR",N_USER,N_GROUPS_IM_IN,TRUE,
                       "Group Names",0);
              if (w_isopen(window)) w_close(window);
              if (ret_code>=0)
              {
                 if (value.flag & N_DYNAMIC) v_prtf("Dynamic\n");
                 else                        v_prtf("Static\n");
                 if (value.flag & N_SET)     v_prtf("Set\n");
                 else                        v_prtf("Item\n");
                 if (value.flag & N_SET)     /* Value is a set */
                 {
                    id=(long)value.value;
                    n_bindery_object_name(id,name);
                    v_prtf("%s\n",name);
                 }
                 else                        /* Value is an item */
                    v_prtf("Unknown value structure\n");
              }
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_bindery_value_name.
Purpose.....: After  retrieving a property's value, you  may extract the names
              from the value. As was  discussed in n_bindery_value_list(), the
              structure of a value depends on whether the property is a set or
              an item. If the property is a set,then the value contains a list
              of object ids.  This  list is terminated with an object id of 0.
              If the  property is an item, then  the structure of the value is
              not  known, with the exception of the "IDENTIFICATION" property,
              in which case the value is simply an asciiz string. So,as in the
              instance of a set property,it is possible for a value to contain
              multiple names. In order to get all the names from the value, it
              is  necessary to make  repeated calls to this function.  This is
              done by incrementing the index parameter on each subsequent call,
              until FALSE is returned.
Syntax......: int n_bindery_value_name(char *property_name,
                  N_BINDERY_VALUE value,int index,char *value_name);
              char *property_name;     Property name
              N_BINDERY_VALUE value;   Value to get name from
              int index;               Name to retrieve
              char *value_name;        String to store name in
Example call: more_names=n_bindery_value_name("GROUPS_I'M_IN",value,0,name);
Returns.....: TRUE\FALSE flag indicating whether there are more names to be
              extracted from the value.
Common Use..: Get all the names of the values stored in a value.
See Also....: n_bindery_property_list,
              n_bindery_property_scan,
              n_bindery_value_list,
              n_bindery_value_scan.
Example.....: Get the list of groups that the user "DONNA" belongs to.

              #include <string.h>
              #include "user_int.h"
              void main(void)
              {
              N_BINDERY_VALUE value;          /* Value to extract names from*/
              int  i,                         /* ith name gotten            */
                   segment,                   /* Value segment              */
                   more_names;                /* more names left in value   */
              char name[48];                  /* Holds group object name    */

                                                     15 - Network



              w_init();
              segment=1;
              while (n_bindery_value_scan("DONNA",N_USER,N_GROUPS_IM_IN,
                     segment,&value)==0)
              {
                    i=0;
                    do
                    {
                        more_names=n_bindery_value_name(N_GROUPS_IM_IN,
                                   value,i,name);
                        v_prtf("%s\n",name);
                        ++i;
                     }  while (more_names);
                     ++segment;
              }
              k_wait(0):                      /* Pause to view groups      */
              w_exit(0);                      /* exit program              */
              }

                                                     15 - Network



Function....: n_bindery_value_scan.
Purpose.....: To scan the Bindery for a value of a property and optionally for
              all matching values.  Information about a value is returned in a
              structure of type N_BINDERY_VALUE which is defined in w_netwrk.h
              and shown below.  The value is searched for by the object's name
              and type,property name,and by the value's segment. As an example
              one of  the predefined  Netware  properties is  "GROUPS_I'M_IN".
              Suppose you want  to see what groups the  Supervisor belongs to.
              Then you could call n_bindery_value_scan() to find out.Note that
              values do not have a security flag,as do objects and properties.
              As was discussed in n_bindery_value_scan()\name(), the structure
              of a value depends on the property.  A value may be either a set
              or an item.  This is indicated in the property's flag field, and
              likewise is also stored in  the value's  flag field.  Predefined
              bit  masks that can  be used to test the flag, N_ITEM and N_SET.
              are defined  in w_netwrk.h.  If the value is  an item, then  the
              structure of the 128  byte value field is not known.  The single
              exception to this is when the  property whose values we  want is
              "IDENTIFICATION".  In  this case, the  value field is  simply an
              asciiz  string.  On the other hand, if the value  is a set, then
              the value  field is a list of 4  byte object ids.  The list ends
              with an object id of 0x00000000.   See n_bindery_value_name() on
              how to get the names represented by the object ids. If the prop-
              erty has more values than can be held in a single 128 byte value
              called a segment, then the more_segments filed will be non-zero.
              When the last 128 byte value, segment, is read,0xEC is returned.

              typedef struct
              {
                  unsigned char value[N_VALUE_LEN];
                  unsigned char more_segments;
                  unsigned char flag;
              }   N_BINDERY_VALUE;

Syntax......: int n_bindery_value_scan(char *object_name,unsigned int
                  object_type,char *property_name,unsigned char segment,
                  N_BINDERY_VALUE *value);
                  char *object_name;          Name of object
                  unsigned int object_type;   Type of object
                  char *property_name;        Name of property
                  unsigned char segment;      Segment to search
                  N_BINDERY_VALUE *value;     Hold return value info
Example call: n_bindery_value_scan("GUEST",N_USER,N_IDENTIFICATION,1,&value);
Returns.....: 0x00 - Successful
              0x96 - Server out of memory
              0xEC - No such value or not on a network
              0xEF - Invalid name
              0xFE - Server Bindery locked
              0xFF - Bindery failure

                                                     15 - Network



Common Use..: To search  the Bindery for a  single value  to a property or to
              get a complete list of all values for the property.
See Also....: n_bindery_object_list,
              n_bindery_object_name,
              n_bindery_object_scan,
              n_bindery_property_list,
              n_bindery_property_scan,
              n_bindery_value_list,
              n_bindery_value_name.
Example.....: See example for n_bindery_value_name().

                                                     15 - Network



Function....: n_capture_active.
Purpose.....: Determine if the default port has been captured.
Syntax......: int n_capture_active(void);
Example call: if (!n_capture_active()) break;
Returns.....: TRUE\FALSE flag indicating whether the default port is currently
              captured.  FALSE is  also returned if you  are not on a network.
Common Use..: Determine if the port to which printing is done is captured.
See Also....: n_capture_get,
              n_capture_port,
              n_capture_set.
Example.....: All printing  is done through the  port specified by  the global
              variable w_printer.cur_port. Check to see if it is captured, and
              if not, capture it.  Use parallel port 2 as the default  printer
              port.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              p_set_port(LPT2);           /* Set parallel port 2 as default */
              if (!n_capture_active())    /* Check if port 2 is captured    */
                  n_capture(w_printer.cur_port);
              }                           /* If not, capture it             */

                                                     15 - Network



Function....: n_capture_banner_get.
Purpose.....: Get the banner name used in  network printing.  The banner  name,
              if set, causes a  page to be printed before  each print job, with
              the specified name printed on the top half of the page.The banner
              name applies to all Network printers. That is, you can't have one
              banner name for LPT1 and a different one for LPT2.The same banner
              name is used by all ports. The banner name is 12 characters, with
              the 12th byte used as a NULL terminating byte.
Syntax......: n_capture_banner_get(char *banner_name);
              char *banner_name;    Name to be printed on banner page
Example call: n_capture_banner_get(banner);
Returns.....: TRUE\FALSE flag indicating  whether the banner name was obtained.
              FALSE is returned if it is unable  to get the banner name. FALSE
              is also returned if you are not on a network.
Common Use..: Use a banner name to identify which printer output is yours.
See Also....: n_capture_banner_set,
              n_capture_get,
              n_capture_set.
Example.....: Get the current banner name.


              #include "user_int.h"
              void main(void)
              {
              char banner[12];
              w_init();
              if (n_capture_banner_get(banner))
                  v_prtf("Banner: %s\n",banner);
              else
                 v_prtf("Unable to get banner name.\n");
              k_wait(0);
              w_end();
              }

                                                     15 - Network



Function....: n_capture_banner_set.
Purpose.....: Set the banner name used in  network printing.  The banner  name,
              if set, causes a  page to be printed before  each print job, with
              the specified name printed on the top half of the page.The banner
              name applies to all Network printers. That is, you can't have one
              banner name for LPT1 and a different one for LPT2.The same banner
              name is used by all ports. The banner name is 12 characters, with
              the 12th byte used as a NULL terminating byte.
Syntax......: n_capture_banner_set(char *banner_name);
              char *banner_name;    Name to be printed on banner page
Example call: n_capture_banner_set("ROLF");
Returns.....: TRUE\FALSE flag indicating whether the banner name was set. FALSE
              is returned if it is unable to set the banner name. FALSE is also
              returned if you are not on a network.
Common Use..: Use a banner name to identify which printer output is yours.
See Also....: n_capture_banner_get,
              n_capture_get,
              n_capture_set.
Example.....: Set the current banner name to your own.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              if (!n_capture_banner_set("DONNA"))
                  v_prtf("Unable to set banner name.\n");
              else
              {
                 window=p_start();
                 if (!window) break;
                 p_prtf("This is some text.  A banner page should precede\n");
                 p_prtf("this text.\n");
                 p_end();
              }
              w_end();
              }

                                                     15 - Network



Function....: n_capture_cancel.
Purpose.....: Cancel  capturing for a  specified parallel port.  This ends the
              capturing on  the specified  parallel port  just like ending the
              capture does,but Print Queue job is deleted from the Print Queue
              and no data is sent to the printer.If a local printer is attach-
              ed to the canceled port, then  the local printer regains control
              of the port, otherwise,the port simply becomes unavailable.  The
              parallel ports are defined in w_printr.h.
Syntax......: n_capture_cancel(int LPT);
              int LPT;       parallel port to end capturing
Example call: n_capture_cancel(LPT3);
Returns.....: TRUE\FALSE flag indicating whether the capturing on the specified
              port  was canceled.  FALSE is  also returned  if you are not on a
              network.
Common Use..: Delete a print job.
See Also....: n_capture_end,
              n_capture_flush,
              n_capture_port.
Example.....: Suppose you accidentally send a huge print job to be printed.You
              can delete the print job by cancelling the capture.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              p_set_port(LPT1);            /* Set parallel port 1 as default */
              for(i=0;i<10000;++i)         /* Make a stupid print job        */
                  p_prtf("Hello World.\n");
              if ('Y'==w_ynbox("Delete Print Job",0))
                   n_capture_cancel(LPT1)) /* Cancel print job               */
              else
                   n_capture_end(LPT1))    /* Send print job to be printed   */
              w_end();
              }
                                                     15 - Network



Function....: n_capture_end.
Purpose.....: Releases a print job  from the  Print Queue, sending  it  to  the
              printer,  and ends the  capturing of  the parallel port.  This is
              the standard way of  submitting a print job to the printer.  If a
              local printer is attached to the port, then the local printer re-
              gains control of the port. Otherwise,the port becomes unavailable
              able. Thus, this is an alternative method for alerting Netware to
              the end of  a Print Job when  the timeout for the  port has  been
              disabled.  If you want to explicitly end a Print Job and you want
              the job printed, use this function. You will however be  required
              to recapture the parallel  port since  this function will end the
              capturing.
Syntax......: n_capture_end(int LPT);
              int LPT;     parallel port to end capturing
Example call: n_capture_end(LPT2);
Returns.....: TRUE\FALSE flag  indicating whether  capturing was ended  on the
              parallel port.FALSE is also returned if you are not on a network
Common Use..: End capturing of a  parallel port and send print job to printer.
See Also....: n_capture_cancel,
              n_capture_flush,
              n_capture_port.
Example.....: Send some lines of text to a network printer on parallel port 3.
              Then, end the capturing on the port. Then,make sure that captur-
              ing on parallel port 3 has indeed been  canceled, and if a local
              printer  is available, send  some lines  of  text to  the  local
              printer.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;             /* Print message window           */

              w_init();
              p_set_port(LPT3);           /* Set parallel port 3 as default */
              if (!n_capture_active())    /* Make sure port 3 is captured   */
                  n_capture(LPT3);        /*                                */
              window=p_start();           /* Always bracket your printing   */
              if (!window) w_exit(1);     /* Abort if printer not ready     */

              p_prtf("This text should appear on a network printer.\n");
              p_prtf("Now end the capturing.\n");
              n_capture_end(w_printer.cur_port);
              p_end(window);              /* Close print message window     */

                                                     15 - Network



              window=p_start();           /* Now see if local printer ready */
              if (!window) w_exit1);      /* If not, exit                   */
              p_prtf("This should be printed on the local printer.\n");
              p_prtf("End of test.\n");   /* Always bracket p_start() with  */
              p_end(window);              /* a p_end()                      */
              w_exit(0);
              }

                                                     15 - Network



Function....: n_capture_file.
Purpose.....: Capture a  parallel port's print  data to a disk file instead of
              to a network printer. The previous contents of the file are lost
              if the  file already exists.  No warning is given.  In order for
              this function  to succeed, the user  must have  read, write, and
              create rights for the directory in which the file will be stored
              p_start() and p_end() should  also be called just as in printing
              to a printer. If  you wish to close the file, use  n_capture_end
              to close the file.
Syntax......: n_capture_file(char *file_path);
              char *file_path;     Name of disk file to redirect printing to
Example call: n_capture_file("N:\\HOME\\ROLF\\PRINT.FIL");
Returns.....: TRUE\FALSE flag indicating  whether the file  was created. FALSE
              is  also returned if you  are not on a network.
Common Use..: Redirect printing from a network printer to a disk file.
See Also....: n_capture_flush.
Example.....: Instead of using a network printer, print some text and have it
              stored in a disk file.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (!n_capture_file("N:\\HOME\\SANDRA\\PRINT.FIL"))
              {                           /* If unable to create disk file  */
                  w_errbox(0,"Unable to redirect printer to file.");
                  w_exit(1);
              }                           /* Else, print some text to file  */
              p_prtf("This text will be sent to a file instead\N");
              p_prtf("to a network printer.\n");
              n_capture_flush(w_printer.cur_port);
              w_exit(0);                  /* Flush print stream to end job  */
              }

                                                     15 - Network



Function....: n_capture_flush.
Purpose.....: Closes the capture file and sends it the printer for printing
              A new capture file is reopened and capturing continues.
Syntax......: n_capture_flush(int LPT);
              int LPT;        parallel port to flush
Example call: n_capture_flush(LPT1);
Returns.....: TRUE\FALSE flag indicating whether the specified port was flushed
              FALSE is  also returned if you  are not on a network.
Common Use..: End a print job which has been redirected to a disk file.
See Also....: n_capture_cancel,
              n_capture_end.
Example.....: Suppose parallel port LPT1 has been redirected to a file.  Print
              some text on LPT1(ie, to the file), and then flush the port, ef-
              fectively ending the Print Job and sending the print data to the
              Print Queue to be stored in the file.


              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;

              w_init();
              if (!n_capture_active())    /*Check default port capture      */
                  n_capture(w_printer.cur_port);
              p_redirect("Text.fil");     /* Redirect capture to a text file*/
              window=p_start();           /* Display print message          */
              if (!window) w_exit(1);     /* If not ready, abort            */
              p_prtf("This is some text to be printed out.\n");
              p_prtf("Another line of text.\n");
              p_prtf("Now flush the print stream and end Print Job.\n");
              p_prtf("All this should be in the file on disk.\n");
              n_capture_flush(w_printer.cur_port);
              p_end(window);              /* Clear print message            */
              w_exit(0);                  /* Were done                      */
              }

                                                     15 - Network



Function....: n_capture_get.
Purpose.....: Associated with each captured port are a myriad of settings. You
              don't have to know about these settings in order to do printing.
              The network  supervisor should have  set these  options  to some
              convenient default values. n_capture_get() allows you to get the
              status  of these options, about  20 altogether. The settings and
              structure used  to return  these settings, N_PRINT_CONTROL,  are
              shown below.

              N_PRINT_CONTROL field  Description
                
              status                 Printer status
              print_flag             Various capture settings
              tab_size               Number of spaces to expand tabs
              server_printer         Print Server id (1-8)
              num_copies             Number of copies of each page
              form_type              Form type
              reserved_1             Reserved
              banner_text[13]        Name that appears on lower half of title pg
              reserved_2             Reserved
              local_lpt              Printer Port number (0-4)
              timeout_cntr           Time in system  ticks before  captured port
                                     is flushed
              autoendcap             TRUE\FALSE flag indicating if stream should
                                     be flushed at end of job
              lines_per_page         Maximum number of lines per page
              chars_per_line         Maximum number of characters per line
              form_name[13]          Name for type of paper being used
              lpt_flag               TRUE\FALSE flag indicating whether printing
                                     is sent to a printer
              file_flag              TRUE\FALSE flag indicating whether printing
                                     is redirected to a disk file
              timeout_flag           Set when the Flush Timeout counter is
                                     decrementing, and 0 when no timeout count
                                     is under way.
              setup_string_ptr       Printer initialize string
              reset_string_ptr       Printer reset string
              cnct_id_q_print_job    Print Server connection id (1-8)
              in_progress            TRUE\FALSE flag indicating whether a print
                                     job is currently in progress
              print_queue_flag       Set when a print job is placed in the Queue
              print_job_valid        Set while  the capture  is open to  receive
                                     data.  When the process is ended, cancelled,
                                     or flushed, the flag is cleared.
              print_queue_id         Print Queue bindery object id
              print_job_number       Print job id number (1-999)

                                                     15 - Network



              Network printers use their own function to get the printer status
              code, which is  a bit different  from the BIOS  function used for
              local printers.  A network printer may  be active,  stopped, off-
              line, or online.  Active simply means that the network printer is
              turned on and connected to a Print  Server.  The Halted condition
              is specific  to network  printers and  signifies that the printer
              has been halted by a network manager at the File Server.  The on-
              line  and offline codes  are the  same for  local  printers.  The
              p_code() function gets the printer status code,and if the printer
              is a  network printer, converts the code to a corresponding local
              printer  code.  See the p_code()  function in chapter 13 for more
              information.

              The print_flag is a bit mapped byte which holds information about
              various capture settings.  Its format is shown below.

              7 6 5 4 3 2 1 0
              x . . . . . . .  Print banner page
              . x . . . . . .  Tabs converted
              . . . . . . . .  Reserved
              . . . x . . . .  Notify user when Print jobs finish
              . . . . x . . .  Suppress Form Feeds
              . . . . . x . .  Set if Print job is interrupted during capture
              . . . . . . . .  Reserved

              If  the banner  bit, bit 7, is  not set, then no banner  will be
              printed out, regardless of whether a banner name has  been spec-
              ified or not.
              Similarly, tabs will not be converted,regardless of the tab size
              setting, unless this bit, bit 6, is set.
              If bit 4 is set, then Netware will display a message to the user
              at the end of  each print  job indicating that the print job has
              been completed.
              Clearing bit 3, ie, setting it to 0,will cause a form feed to be
              issued at the end of each print  job. Setting this bit will sup-
              press this form feed.
              Bit 2 is set by Netware and  indicates whether an error occurred
              while trying to capture a port.

              The tab_zize field is the number of spaces tabs are to be expand-
              ed to. Netware only recognizes this field when the tab bit,bit 6,
              in the print_flag field is set.

              The server_printer is a  number between 1  and 8 which indicates
              which Print Server is controlling the parallel port.

              num_copies indicates how  many copies will be made  when data is
              sent to the printer.

                                                     15 - Network



              The form type and form name are defined by your  network manager.
              This is just a way of identifying what type of paper your printer
              uses.  For example, your network manager might define form type 0
              to be "STANDARD" 8" x 11" and form type 2 to be "LONG" 8" x 14"
              It's completely up to the network manager to decide the names and
              numbers used for the forms.

              The next field is a 1 byte field reserved by Netware.

              All print jobs sent to the printer are preceded by a title page.
              This page contains some information about  the user and the doc-
              ument being printed.  Banner_text is the banner name which will
              be printed on the lower half of the title page,in large letters.
              The user's name  is printed in the top half.  Note that Netware
              will ignore this banner  name unless the banner  bit, bit 7, is
              set in  the print_flag field.  If you have ever worked on main-
              frames, you will  notice the resemblance of  the banner page to
              the title page on your mainframe printout.

              The next byte is reserved by Netware.

              The local lpt  field is just the  printer's port number.  Since
              Netware supports up to 3 parallel ports  and 2 serial ports for
              printing (The C User Interface  Library only supports the three
              parallel ports), the local lpt field is defined as:

              0 - Parallel port 1 (LPT1)
              1 - Parallel port 2 (LPT2)
              2 - Parallel port 3 (LPT3)
              3 - Serial   port 1 (COM1)
              4 - Serial   port 2 (COM2)

              The timeout  counter is  used to  specify  the amount of  time in
              system timer ticks before a print job is flushed to a Print Queue
              for printing.  Thus, after the start of a Print Job, if  any time
              gap greater than  or equal, ,  the specified  timeout occurs  in
              which  the printer does  not receive data, then the  print stream
              data is flushed to a Print Queue and sent to a printer for print-
              ing.  Since the timer tick occurs  every 55 ms, approximately  18
              times  per second, to set the timeout for x number of seconds,set
              the timeout  field to 18 * x.  For  example, to set  the  timeout
              count for 5 seconds, use 18 * 5 = 90.

              Autoendcap is  used to "send data to a  network  printer or  to a
              network file when you  exit or enter  an application.  Autoendcap
              doesn't automatically end  the capture of an LPT port as its name
              implies. "Autoendcap merely flushes the Print Queue automatically
              each time you enter or end an application.

                                                     15 - Network



              Lines_per_page and chars_per_line are ignored by Netware.By this
              it is  meant that setting  these fields has no effect on printed
              output.  If you set chars_per_line to 10 and print 80 characters
              to the printer, all 80  characters will still  be printed on the
              same line  even though you have set this  field to 10.  In order
              to alter the lines per page and characters per line settings for
              a printer,you must send the appropriate Escape sequences to your
              printer.  For example, to set the lines per page to 20 on an IBM
              Proprinter X24, you would send an "ESC C {0} 20" to the printer.
              The only purpose of these two fields is that  you could then re-
              cord your  settings here after having  sent the appropriate com-
              mands to your printer.

              Form_name is the name of the form associated with the form_type.
              See the form_type field description for more information.

              Lpt flag and File flag indicate if a printers output has been re
              directed to a disk file instead of to a printer.  If printing is
              being sent to a parallel port, then lpt_flag will be 0xFF. Like-
              wise, if printing  has been redirected to a disk file, file_flag
              will be 0xFF.

              When the timeout is disabled, the timeout flag is 0.  Otherwise,
              after every character received, the Print Queue  starts a decre-
              ment.  If it reaches 0, the Print job is flushed and sent to the
              printer for  printing.  The timeout_flag is  set while the Print
              Queue is decrementing and clear otherwise.

              The setup  and reset  strings do exactly what their names imply.
              They  are strings that you  can send  to initialize your printer
              before printing and to reset it after each Print Job.

              The Connection  id is the Print  Server id (1-8), which services
              the Print Queue.

              In progress tells  you whether the  specified port currently has
              any Print Jobs in progress.

              The Print Queue flag is set whenever the Queue has any print jobs

              Print  Job valid is set while the captured port is open and able
              to receive  data.  When  the capturing is flushed, cancelled, or
              ended, this flag is reset.

             Print Queue id is the 4 byte bindery object id of the Print Queue

             Print Job number  is the number  assigned to the print job by the
             Print  Queue.  Since each Print Queue is  capable of servicing up
             to 1000 print jobs, numbers between 1 and 999 are valid.

                                                     15 - Network




Syntax......: n_capture_get(int LPT,N_PRINT_CONTROL *settings);
              int LPT;                   parallel port to get captured status
              N_PRINT_CONTROL *settings  Returned settings information
Example call: n_capture_get(LPT1,&settings);
Returns.....: TRUE\FALSE flag indicating whether the status information for the
              specified port was obtained.  The port settings are returned in a
              N_PRINT_CONTROL structure,defined in w_netwrk.h. If unsuccessful,
              or if you are not on a network, FALSE is returned.
Common Use..: Save the port settings before modifying them, so the  port can be
              restored at a later time.
See Also....: n_capture_set.
Example.....: Save the current port settings for parallel port 1.Then, set the
              banner text to "Squid". Then, print some text so we can see what
              the banner page looks like.

              #include <string.h>
              #include "user_int.h"
              void main(void)
              {
              WIN_PTR window;
              N_PRINT_CONTROL settings;

              w_init();
              p_set_port(LPT1);           /* Set parallel port 1 as default */
              if (!n_capture_active())    /* Check if port 1 is captured    */
                  n_capture_port(w_printer.cur_port);
              n_capture_get(LPT1,&settings);
              settings.print_flag|=0x07;  /* Set banner bit in print_flag   */
                                          /* Leave other bits alone         */
              strcpy(settings.banner_text,"Squid");
              n_capture_set(settings);    /* Set new banner text            */
              window=p_start();           /* See if printer is ready        */
              if (!window) w_exit(1);     /* If not quit                    */
              p_prtf("This is some text with the banner set to Squid.\n");
              p_prtf("That's all folks.\n");
              p_end(window);              /* End bracket for printing       */
              w_exit(0);                  /* Restore original settings      */
              }

                                                     15 - Network



Function....: n_capture_queue.
Purpose.....: Select a Print queue for a captured port.  The Print  Queue must
              be on the default File Server.
Syntax......: int n_capture_queue(int LPT,unsigned long int Queue_id);
              int LPT;       parallel port to capture
              unsigned long  Print Queue's bindery object id
Example call: n_capture_queue(LPT3,0x0C000015);
Returns.....: TRUE\FALSE flag indicating whether the queue was selected. FALSE
              is  also returned if you  are not on a network.
Common Use..: Select a Print Queue for a captured port.
See Also....: n_capture_get,
              n_capture_port.
              n_capture_set.
Example.....: Capture parallel port 2.  Select a Print Queue from among those
              on the default File Server.  Then print some text using the net-
              work printer.

              #include "user_int.h"
              void main(void)
              {
              N_BINDERY_OBJECT queue;
              WIN_PTR          window;

              w_init();
              p_set_port(LPT2);           /* Set parallel port 2 as default */
              n_bindery_object_list(6,2,10,1,w_color_menu,
              &window,&queue,N_PRINT_QUEUE,w_shadows,"Print Queues",
              ".n_print_queue_list");
              w_close(window);
              if (w_lastkey==ESC) w_end();
                                          /* Capture port                   */
              if (n_capture_port(w_printer.cur_port))
                  printf("LPT2 captured.\n");
              else
                 printf("Unable to capture LPT2.\n"");
                                          /* Select a Print Queue           */
              if (n_capture_queue(LPT2,n_long(queue.id)))
                 v_prtf("LPT2 Print Queue set.\n");
              else
                 v_prtf("Unable to set Queue for LPT2.\n");


                                                     15 - Network



              window=p_start();           /* Display init message           */
              if (!window) w_end(1);      /* If printer not ready, abort    */
              p_prtf("This text should go to the network printer\n");
              p_prtf("Controlled by Print Queue %8.8lX\n",queue_id);
              p_prtf("That is capturing the print stream on\n");
              p_prtf("parallel port 2.\n");
              p_end(window);              /* End print job, clear message   */
              }

                                                     15 - Network



Function....: n_capture_set.
Purpose.....: As was discussed in  the concepts section, each  network printer
              has a host of  associated options.  These options are set by the
              network supervisor to some default  values, and are rarely  ever
              changed. However,for those users wishing to do so, this function
              provides  access to these options.  The new settings  are placed
              in an  N_PRINT_CONTROL  structure  variable.  The format  of the
              structure is discussed in  n_capture_get().  You may  set any of
              the  fields starting from and including the print_flags field up
              to and including  the form_name.  The rest of the fields may not
              be modified.
Syntax......: n_capture_set(int LPT,N_PRINT_CONTROL settings);
Example call: n_capture_set(LPT1,settings);
Returns.....: TRUE\FALSE flag indicating whether the printer  accepted the new
              settings.  FALSE is  also  returned if you  are not on a network.
Common Use..: This function is not commonly used,but you may use it to set the
              printer options to something other than the default.
See Also....: n_capture_get.
Example.....: Set the number of copies to 2, expand tabs to 4 spaces, and dis-
              able the timeout feature.

              #include "user_int.h"
              void main(void)
              {
              N_PRINT_CONTROL settings;   /* Structure to set new settings  */
              WIN_PTR window;             /* Print init message window      */
              int     i;                  /* Loop variable                  */

              w_init();
              /* 1st get the default settings for the current port          */
              n_capture_get(w_printer.cur_port,&settings);
              /* we only want to modify these 3 fields                      */
              settings.num_copies=2;      /* Put the new settings into the  */
              settings.flush_timeout_cntr=0;
              settings.print_flag|=0x06;  /* Set tab convert bit in         */
                                          /* print_flag field. Leave other  */
                                          /* bits unchanged.                */
              n_capture_set(settings);    /* Implement our new settings     */
              window=p_start();           /* Get printer ready              */
              if (!window) w_exit(1);     /* Abort if not ready             */
                  p_prtf("Hello \tworld\t.\n");
              p_end(window);              /* Should be a total of 4 pages.  */
              w_exit(0);                  /*                                */
              }

                                                     15 - Network



Function....: n_capture_start.
Purpose.....: Capture the  print data for a  port and redirect it to a network
              printer.
Syntax......: int n_capture_start(int LPT);
              int LPT;      parallel port to capture
Example call: n_capture_start(LPT3);
Returns.....: TRUE\FALSE flag indicating whether the port was captured.  FALSE
              is  also returned if you  are not on a network.
Common Use..: Redirect a parallel port from a local or unused port to a network
              printer.
See Also....: n_capture_active,
              n_capture_get,
              n_capture_set.
Example.....: Capture parallel port 1.  Then print some text using the network
              printer.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              p_set_port(LPT2);           /* Set parallel port 2 as default */
              if (!n_capture_active())    /* Check if port 2 is captured    */
                  n_capture_start(w_printer.cur_port);
              window=p_start();           /* Display init message           */
              if (!window) w_exit(1);     /* If printer not ready, abort    */
              p_prtf("This text should go to the network printer\n");
              p_prtf("That is capturing the print stream on\n");
              p_prtf("parallel port 1.\n");
              p_end(window);              /* End print job, clear message   */
              }

                                                     15 - Network



Function....: n_connection_number.
Purpose.....: Get a user's connection number.  A connection number is a number
              between 1 and 100, that is assigned to  each user who logs in to
              the network.  The connection number is used mainly for internet-
              work communication between users.  Once  you have a user's name,
              you may  use  this function  to  get  their  connection  number.
              Although a user may be logged in at more than 1 workstation,only
              the connection number for the work station where they 1st logged
              on is returned.
Syntax......: unsigned char n_connection_number(char *user_name);
              char *user_name;
Example call: con_num=n_connection_number("NORD");
Returns.....: If successful,a connection number between 1 and 100 is returned.
              Otherwise, FALSE is returned.  FALSE is also returned if you are
              not on a network.
Common Use..: Get a user's connection  number in order to send electronic mail
              to them.
See Also....: n_local_connection_number.
Example.....: Although internetwork  mail is not supported  in this version of
              The C User Interface Library, use n_connection_number to get the
              connection number for user's SONJA and INGRID.


              #include "user_int.h"
              void main(void)
              {
              unsigned char con_num[2];   /* 2 connection numbers           */

              w_init();
              if (!(con_num[0]=n_connection_number("SONJA")) ||
                  !(con_num[1]=n_connection_number("INGRID")))
                  v_prtf("Unable to get connection numbers.\n");
              else
              {
                  v_prtf("Sonja.: %d\n",con_num[0]);
                  v_prtf("Ingrid: %d\n",con_num[1]);
              }
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_dir_get_effective_rights.
Purpose.....: Get the effective rights for a directory.  A user's  rights to a
              given  directory, called the effective rights, are determined by
              "anding" the  directory's  maximum rights  mask with  the user's
              trustee rights for the directory. The directory's maximum rights
              mask is assigned by the network supervisor.  This mask specifies
              the maximum number of rights any user of the directory can have.
              No user  can have more  rights than is specified  in the maximum
              rights mask. He can only have the same or fewer rights,but never
              more.  A list of  directory rights is defined in w_netwrk.h, and
              is shown below.

              Directory Right     Description
                   
              Read                may read files
              Write               may write to files
              Open                may open files
              Create              may create files
              Delete              may delete files
              Parental            may create\delete subdirectories and
                                  may grant\revoke trustee rights
              Search              may list files in the directory
              Modify              may change file's attributes

              Next, each user is assigned individual rights to  the directory.
              If a user has at least 1 individual rights,then these rights are
              called the user's trustee rights.  Trustee rights are granted to
              a user by  either the  supervisor or  by someone  with  parental
              rights to the directory.  Your effective rights are given by the
              "anding" of your trustee rights for a directory with the direct-
              ory's own maximum rights mask.  For example, suppose the maximum
              rights mask for a directory is Read, Write, and Open.  Your  own
              trustee rights  for this  directory are  Read, Open, and Search.
              Then, your actual (effective) rights for this directory would be
              Read and Open.
Syntax......: int n_dir_get_effective_rights(char *dir,unsigned char *rights);
              char *dir;               Directory to get rights for
              unsigned char *rights;   Holds effective rights
Example call: n_dir_get_effective_rights("M",&rights);
Returns.....: TRUE\FALSE indicating whether the rights were obtained.
Common Use..: Get the effective rights to a given directory.
See Also....: n_dir_get_maximum_rights.
              n_dir_get_trustee_rights.
              n_dir_set_trustee_rights.

                                                     15 - Network



Example.....: Assuming your home directory is mapped to drive H, get a list of
              your  effective rights.  You should  have all, or  close to all,
              rights for your home directory.


              #include "user_int.h"
              void main(void)
              {
              unsigned char eff_rights;
              w_init();
              if (n_dir_get_effective_rights("H",&eff_rights))
              {
                  v_prtf("Effective Rights for drive H are:\n");
                  if (eff_rights & N_DIR_READ  ) v_prtf("READ, ");
                  if (eff_rights & N_DIR_WRITE ) v_prtf("WRITE, ");
                  if (eff_rights & N_DIR_OPEN  ) v_prtf("OPEN, ");
                  if (eff_rights & N_DIR_CREATE) v_prtf("CREATE, ");
                  if (eff_rights & N_DIR_DELETE) v_prtf("DELETE, ");
                  if (eff_rights & N_DIR_PARENT) v_prtf("PARENTAL, ");
                  if (eff_rights & N_DIR_SEARCH) v_prtf("SEARCH, ");
                  if (eff_rights & N_DIR_MODIFY) v_prtf("MODIFY, ");
                  v_prtf("\n");
              }
              else
                 v_prtf("Unable to get effective rights for directory H.\n");
              w_end();
              }

                                                     15 - Network



Function....: n_dir_get_maximum_rights.
Purpose.....: Get the maximum rights mask for a directory.  See the  discussion
              on the preceding page for details on directory and maximum rights.
Syntax......: int n_dir_get_maximum_rights(char *dir,unsigned char *mask);
              char *dir;              Directory to get rights for
              unsigned char *mask;    Holds maximum rights mask
Example call: n_dir_get_maximum_rights("M",&mask);
Returns.....: TRUE\FALSE indicating whether the rights were obtained.
Common Use..: Get the maximum rights mask to a given directory.
See Also....: n_dir_get_effective_rights.
              n_dir_get_trustee_rights.
              n_dir_set_trustee_rights.
Example.....: Get the maximum rights mask to the directory mapped to drive M.

              #include "user_int.h"
              void main(void)
              {
              unsigned char max_rights_mask;
              w_init();
              if (n_dir_get_maximum_rights("M",&max_rights_mask))
              {
                  v_prtf("Maximum Rights Mask for drive M are:\n");
                  if (max_rights_mask & N_DIR_READ  ) v_prtf("READ, ");
                  if (max_rights_mask & N_DIR_WRITE ) v_prtf("WRITE, ");
                  if (max_rights_mask & N_DIR_OPEN  ) v_prtf("OPEN, ");
                  if (max_rights_mask & N_DIR_CREATE) v_prtf("CREATE, ");
                  if (max_rights_mask & N_DIR_DELETE) v_prtf("DELETE, ");
                  if (max_rights_mask & N_DIR_PARENT) v_prtf("PARENTAL, ");
                  if (max_rights_mask & N_DIR_SEARCH) v_prtf("SEARCH, ");
                  if (max_rights_mask & N_DIR_MODIFY) v_prtf("MODIFY, ");
                  v_prtf("\n");
              }
              else
              v_prtf("Unable to get Maximum rights mask for directory M.\n");
              w_end();
              }

                                                     15 - Network



Function....: n_dir_get_volume.
Purpose.....: Get the volume name of an associated directory. Volumes on a net-
              work are similar to drives on a DOS machine.  Drives on a network
              are dynamic and are simply directory mappings.  Each directory is
              under a Volume.  The 1st volume on Novell networks is called SYS.
              After that, any others  are defined by  the system  administrator
              when the network is set up. Each directory mapping, ie, drive, is
              under a Volume. Directories are mapped to drives by using the map
              command.  For example, suppose there are two volumes on your net-
              work, SYS and APPS.  Shown below is a  made up example of how the
              drives might be mapped.

              SYS:  BIN
                      ETC
                      HOME  ERIK
                                DONNA
                                LANCE

              APPS:  LOTUS
                      PC_TOOLS
                      NORTON

              A:=SYS:HOME\ERIK
              B:=SYS:HOME\DONNA
              C:=APPS:LOTUS

              Then, the volume for drive A and B are SYS,whereas the volume for
              drive C is APPS.  Only  network drives are assigned to  a volume.
              Local  drives  do not.  You  may use the  constant CURRENT_DRIVE,
              defined in  w_netwrk.h, to get  the volume for the current drive.
              The volume name is at most 15 characters long.
Syntax......: int n_dir_get_volume(char *volume,char drive);
              char *volume;    Array to hold volume name
              char drive;      Directory to get volume for
Example call: n_dir_get_volume(volume,'A');
Returns.....: TRUE\FALSE indicating whether the  volume name was  obtained.  If
              successful, volume will contain the name of the volume.  FALSE is
              returned if the specified drive does not exist, is not  a network
              drive, or if the drive is not mapped.
Common Use..: Get the volume name for given directory.
See Also....: None.
Example.....: Get the volume name for the current directory.

                                                     15 - Network



              #include "user_int.h"
              void main(void)
              {
              char volume[16];
              w_init();
              if (n_dir_get_volume(volume,N_CURRENT_DRIVE))
                 v_prtf("Volume: %s\n",volume);
              else
                 v_prtf("Unable to get volume.\n");
              k_wait(0);
              w_end();

                                                     15 - Network



Function....: n_dir_handle.
Purpose.....: Get  the handle of a network  directory.  Netware maintains many
              internal tables, two of which are a Volume table and a Directory
              table.  The Volume table contains the  names of up to 32 volumes
              found on the File Server,amoung other information. The Directory
              handle table contains up to 255 pointers to  the Directory table
              which holds various  bits of information, including names, about
              the directories.  This function returns the directory handle for
              a directory mapped drive.  If the drive is a local  drive, or if
              the drive is  not mapped, 0x00 will be returned.  This  function
              only returns handles for mapped drives.
Syntax......: unsigned char n_dir_handle(char drive);
              char drive;      network directory mapped to a drive
Example call: handle=n_dir_handle('L');
Returns.....: 0x00 if unsuccessful, and the Directory handle otherwise.
Common Use..: Get a directory's handle for use in other Netware functions.
See Also....: none.
Example.....: Get the directory handle for drive 'L'.

              #include "user_int.h"
              void main(void)
              {
              unsigned char handle;         /* Directory handle           */

              w_init();
              handle=n_dir_handle('L');
              if (handle)
                  v_prtf("The directory handle for drive L is %d.\n",handle);
              else
                  v_prtf("Unable to get the directory handle for drive.\n");
              w_end();
              }

                                                     15 - Network



Function....: n_drive.
Purpose.....: Determine if a specified drive is a  local drive, floppy or hard
              drive on a user's work station,or a network drive located on the
              File Server. There are 2 constants defined in w_netwrk.h, called
              N_LOCAL_DRIVE and N_NETWORK_DRIVE, which are defined as 0  and 1
              respectively.
Syntax......: int n_network_drive(char drive);
              char drive;            Drive to test
Example call: if (n_drive('F')) break;
Returns.....: TRUE if the given  drive is a network drive and FALSE otherwise.
Common Use..: Can be used for security purposes,to check whether data is being
              sent to a user or simply across the network.
See Also....: None.
Example.....: Copy files to another drive if the drive is a network drive.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_drive('E')==N_NETWORK_DRIVE)
                 fcopy("Myfile", "HisFile", 't');
              else
                  w_errbox(0,"Drive E is not a network drive.");
              w_exit(0);
              }

                                                     15 - Network



Function....: n_file_get_ext_attr.
Purpose.....: Get the extended attributes of a file. Netware adds four extended
              rights to the normal DOS file rights.They are defined in w_netwrk
              .h, and are also listed below.

              FA_TRANSACTION
              FA_INDEX
              FA_R_AUDIT
              FA_W_AUDIT

              The Transaction Tracking System (TTS) attribute
Syntax......: int n_file_get_ext_attr(char *file, unsigned char *ext_attr);
              char *file;                file to get attributes of
              unsigned char *ext_attr;   return extended attributes
Example call: n_file_get_ext_attr("C:\\temp.mak",&ext_rights);
Returns.....: TRUE\FALSE indicating whether the file's extended attributes were
              obtained.
Common Use..: Get the extended attributes of a given file.
See Also....: n_file_set_ext_attr.
Example.....: Get the extended rights of a file on your hard drive.


              #include "user_int.h"
              void main(void)
              {
              unsigned char ext_rights;

              w_init();
              n_file_get_ext_attr("C:\\temp.mak",&ext_rights);
              if (ext_rights & FA_TRANSACTION)
                 v_prtf("Transaction");
              if (ext_rights & FA_INDEX)
                 v_prtf("Index");
              k_wait(0);
              w_end();
              }

                                                     15 - Network



Function....: n_file_set_ext_attr.
Purpose.....: Set the extended attributes of a file.Netware adds four extended
              rights to the normal DOS file rights. They are defined in w_net-
              wrk.h, and are also listed below.

              FA_TRANSACTION
              FA_INDEX
              FA_R_AUDIT
              FA_W_AUDIT

              The Transaction Tracking System (TTS) attribute
Syntax......: int n_file_set_ext_attr(char *file,unsigned char ext_attr);
              char *file;               file to set attributes of
              unsigned char ext_attr;   extended attributes
Example call: n_file_set_ext_attr("C:\\temp.mak",ext_rights);
Returns.....: TRUE\FALSE indicating whether the file's extended attributes were
              set.
Common Use..: Set the extended attributes of a given file.
See Also....: n_file_get_ext_attr.
Example.....: Set the extended file attributes for a file on your hard drive to
              enable Transaction tracking and for Read Auditing.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              n_file_set_ext_attr("C:\\temp.c",FA_TRANSACTION | FA_R_AUDIT);
              w_end();
              }

                                                     15 - Network



Function....: n_int.
Purpose.....: This function is actually defined as a macro. Netware uses some
              reverse byte ordered numbers in some of its function calls.This
              is in direct contrast to the byte ordering that Intel microproc-
              essors use.  So, n_int() reverses the 2 bytes in  an "int" type
              variable from the Intel style to the Netware style.
Syntax......: int n_int(int variable);
              int variable;    variable to be byte order reversed
Example call: request.type=n_int(N_USER);
Returns.....: Byte reversed integer.
Common Use..: Some of Netware's functions require fields to be filled in with a
              reverse order integer.  This macro does that for you.
See Also....: n_long.
Example.....: Reverse an integer.


              #include "user_int.h"
              void main(void)
              {
              int var=0xFC2B;               /* Integer to reverse         */

              w_init();
              v_prtf("Intel   Style: %4.4X\n",var);
              v_prtf("Netware Style: %4.4X\n",n_int(var));
              k_wait(0);
              w_end();

                                                     15 - Network



Function....: n_internet_address.
Purpose.....: Get a user's network  number and node.  The network  number is a
              4 byte  number which identifies which server you  are using on a
              multiserver  platform, and  the network  node is a 6 byte number
              representing the  workstation  id.  These are useful in  sending
              internetwork  mail.  You  must first have  the user's connection
              number in order to obtain their network number and node.
Syntax......: int n_internet_address(unsigned char connection_number,
                  unsigned char *network_number,unsigned char *network_node);
              unsigned char  connection_number; user's connection number
              unsigned char *network_number;    4 byte buffer to hold net num
              unsigned char *network_node;      6 byte buffer to hold net node
Example call: n_internet_address(con_num,net_num,net_node);
Returns.....: TRUE\FALSE flag indicating whether the network was able to return
              the  user's network  number and node.  FALSE is also  returned if
              you are not on a network.
Common Use..: Get a user's network  number and node in order  to send them some
              electronic mail.
See Also....: n_connection_number,
              n_local_connection_number.
Example.....: Get user ERIK's network node and number.


              #include "user_int.h"
              void main(void)
              {
              unsigned char con_num,      /* User's connection number       */
                            net_num[4],   /* Network number                 */
                            net_node[6];  /* Network node                   */
              w_init();
              con_num=n_connection_number("ERIK");
              if (!con_num)
              {
                  v_prtf("Unable to get connection number.");
                  w_exit(1);
              }
              if (!n_internet_address(con_num,net_num,net_node))
                  v_prtf("Unable to get network number and node\n");
              else
                                                     15 - Network



              {
                  v_prtf("Connection number: %2.2X\n",con_num);
                  v_prtf("Network number...: %2.2X %2.2X %2.2X %2.2X\n",
                          net_num[0],net_num[1],net_num[2], net_num[3]);
                  v_prtf("Network node.....: %2.2X %2.2X %2.2X %2.2X %2.2X
                                             %2.2X\n",net_node[0],net_node[1],
                          net_node[2],net_node[3],net_node[4],net_node[5]);
              }
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_IPX.
Purpose.....: Determine if IPX is installed. If IPX is installed, then you are
              on a  Novell network.  This  is the test used  to set w_network.
              installed.
Syntax......: int n_IPX(void);
Example call: if (!n_IPX()) break;
Returns.....: TRUE\FALSE flag indicating whether IPX Is installed.
Common Use..: Determine if IPX is installed.
See Also....: n_NETBIOS,
              n_SHARE,
              n_SPX,
              n_TTS.
Example.....: Determine if IPX is installed.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_IPX())                /* Check if IPX is installed      */
                  v_prtf("IPX is installed.\n");
              else
                  v_prtf(IPX is not installed.\n");
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_local_connection_number.
Purpose.....: Get a your own connection number.A connection number is a number
              between 1 and 100, that is assigned to  each user who logs in to
              the network.  The connection number is used mainly for internet-
              work communication between users.  Although you may be logged in
              at more than one workstation, only the connection number for the
              work where you 1st logged on is returned.
Syntax......: unsigned char n_local_connection_number(void);
Example call: con_num=n_connection_number();
Returns.....: If successful,a connection number between 1 and 100 is returned.
              Otherwise, FALSE is returned.  FALSE is also returned if you are
              not on a network.
Common Use..: Get a your own connection number in order that you may send  and
              receive electronic mail.
See Also....: n_connection_number.
Example.....: Although internetwork  mail is not supported  in this version of
              The C User Interface Library,use n_connection_number to get your
              connection number.


              #include "user_int.h"
              void main(void)
              {
              unsigned char con_num;      /* connection numbers             */

              w_init();
              if (!(con_num=n_local_connection_number()))
                  v_prtf("Unable to get connection number.\n");
              else
                  v_prtf("Con Number: %d\n",con_num);
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_long.
Purpose.....: This function is actually defined as a macro. Netware uses some
              reverse byte ordered numbers in some of its function calls.This
              is in direct contrast to the byte ordering that Intel microproc-
              essors use.  So, n_long() reverses the 4 bytes in a "long" type
              variable from the Intel style to the Netware style.
Syntax......: long n_int(long variable);
              long variable;  variable to be byte order reversed
Example call: request.id=n_long(id);
Returns.....: Byte reversed long integer.
Common Use..: Some of Netware's functions require fields to be filled in with a
              reverse order long integer.  This macro does that for you.
See Also....: n_int.
Example.....: Reverse a long integer.


              #include "user_int.h"
              void main(void)
              {
              int var=0xFC2BEC01;           /* Long Integer to reverse    */

              w_init();
              v_prtf("Intel   Style: %8.8X\n",var);
              v_prtf("Netware Style: %8.8X\n",n_long(var));
              k_wait(0);
              w_end();

                                                     15 - Network



Function....: n_NETBIOS.
Purpose.....: Determine if NETBIOS is installed.
Syntax......: int n_NETBIOS(void);
Example call: if (!n_NETBIOS()) break;
Returns.....: TRUE\FALSE flag indicating whether NETBIOS Is installed.
Common Use..: Determine if NETBIOS is installed.
See Also....: n_IPX,
              n_SHARE,
              n_SPX,
              n_TTS.
Example.....: Determine if NETBIOS is installed.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_NETBIOS())            /* Check if NETBIOS is installed  */
                  v_prtf("NETBIOS is installed.\n");
              else
                  v_prtf(NETBIOS is not installed.\n");
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_server_attach.
Purpose.....: Attach to a network File Server.Netware allows a network to have
              up to 8 File Servers.  They are numbered 1-8. This is the server
              id number. Attaching to a File Server does not log you in to the
              File Server.  Attaching merely establishes a  connection between
              your workstation and the File Server.
Syntax......: int n_server_attach(unsigned char server_id);
              unsigned char server_id;   Network File Server number
Example call: if (n_server_attach(1)) continue;
Returns.....: TRUE\FALSE flag  indicating whether you were attached to the re-
              quested File Server.  FALSE is also returned if you are not on a
              network.
Common Use..: Each File Server maintains it's own Bindery.You have access only
              to the  Bindery of the File  Servers  to which you are attached.
              This allows you to get  information from  the Bindery's of other
              File Servers.
See Also....: n_server_detach,
              n_server_login,
              n_server_logout.
Example.....: Suppose you have a system with two File Servers.  One may be for
              your database programmers, and the other could be for your tech-
              nical support staff.  Assume you are a programmer, and  you want
              to attach to the Tecnical Support File Server.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_server_attach(2))     /* Try to attach to Tech Server   */
                  v_prtf("You are attached to the Tech Support File Server.");
              else
                  v_prtf("Unable to attach to the Tech Support File Server.\n");
              k_wait(0);
              w_exit(0);

                                                     15 - Network



Function....: n_server_detach.
Purpose.....: Detach from a  network File Server. Netware  allows a network to
              have up  to 8 File  Servers.  They are numbered 1-8. This is the
              server id number.  Detaching from a File Server does not log you
              out  from the  File Server.  It  merely  removes the  connection
              between you and the File Server.
Syntax......: int n_server_detach(unsigned char server_id);
              unsigned char server_id;   Network File Server number
Example call: if (n_server_detach(1)) continue;
Returns.....: TRUE\FALSE flag indicating  whether the  user was detached  from
              the File  Server.  FALSE is also  returned if you are  not on  a
              network.
Common Use..: Detach from  a File Server  on which  you are  attached  but not
              logged in.
See Also....: n_server_attach,
              n_server_login,
              n_server_logout.
Example.....: Suppose  you are connected to 2  File Servers.  Detach  yourself
              from the 2nd File Server.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_server_detach(2))     /* Try to detach from 2nd Server  */
                  v_prtf("You are detached from the 2nd File Server.");
              else
                  v_prtf("Unable to detach from the 2nd File Server.\n");
              k_wait(0);
              w_exit(0);

                                                     15 - Network



Function....: n_server_login.
Purpose.....: Login to the default network File Server.  The user's name must
              be  47 characters, and  the password must be  127 characters.
              This will attach you and log you in to the default File Server.
Syntax......: int n_server_login(char *user,char *password);
              char *user;     User's name
              char *password  User's password
Example call: n_server_login("JONERIC","HOBBES");
Returns.....: TRUE\FALSE flag indicating whether the user was logged in to the
              File Server. FALSE is also returned if you are not on a network.
Common Use..: Login in to a File Server from inside a program. This allows you
              automate a program without  having to go  to the DOS  prompt and
              logging in.
See Also....: n_server_attach,
              n_server_detach,
              n_server_logout.
Example.....: Login to the default File Server from inside a program.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_server_login("JONERIC","HOBBES"))
                  v_prtf("You are logged in to the default File Server.");
              else
                  v_prtf("Unable to login to the default File Server.");
              k_wait(0);
              w_exit(0);

                                                     15 - Network



Function....: n_server_logout.
Purpose.....: Logout from all network File Servers.  This function may be used
              to log only  yourself out from all File Servers(Think what might
              happen if you were allowed to log anyone off the network instead
              of it being restricting to just you).
Syntax......: void n_server_logout(void);
Example call: n_server_logout();
Returns.....: None.
Common Use..: Logout from all File  Servers from inside a program. This allows
              you automate a program without having to go to the DOS prompt to
              logout.
See Also....: n_server_attach,
              n_server_detach,
              n_server_login.
Example.....: Logout from all File Servers from inside a program.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              n_server_logout();
              v_prtf("You are logged out from all File Servers.");
              k_wait(0);
              w_exit(0);

                                                     15 - Network



Function....: n_SHARE.
Purpose.....: Determine if SHARE is installed.  SHARE.EXE is an external DOS
              command, included with  DOS 3.0 and later.  Share permits file
              sharing on networks. Starting with DOS 4.0, SHARE.EXE is auto-
              matically loaded for you by DOS.
Syntax......: int n_SHARE(void);
Example call: if (!n_SHARE()) break;
Returns.....: TRUE\FALSE flag indicating whether SHARE Is installed.
Common Use..: Determine if SHARE is installed.
See Also....: n_IPX,
              n_NETBIOS,
              n_SPX,
              n_TTS.
Example.....: Determine if SHARE is installed.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_SHARE())              /* Check if SHARE is installed    */
                  v_prtf("SHARE is installed.\n");
              else
                  v_prtf(SHARE is not installed.\n");
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_SPX.
Purpose.....: Determine if SPX is installed. SPX is an optional part of Netware
              which is used for  communications.
Syntax......: int n_SPX(void);
Example call: if (!n_SPX()) break;
Returns.....: TRUE\FALSE flag indicating whether SPX Is installed.
Common Use..: Determine if SPX is installed.
See Also....: n_IPX,
              n_NETBIOS,
              n_SHARE,
              n_TTS.
Example.....: Determine if SPX is installed.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_SPX())                /* Check if SPX is installed      */
                  v_prtf("SPX is installed.\n");
              else
                  v_prtf(SPX is not installed.\n");
              k_wait(0);
              w_exit(0);
              }



                                                     15 - Network



Function....: n_TTS.
Purpose.....: Determine if TTS  is  installed.  TTS is an optional addition to
              Netware.  TTS (Transaction Tracking  System) permits Netware  to
              reverse file writes  and other actions.  However, this imposes a
              tremendous  drain  on system  resources, and  almost  brings the
              system  to a halt.  However, in an  emergency, it can be a life-
              saver.
Syntax......: int n_TTS(void);
Example call: if (!n_TTS()) break;
Returns.....: TRUE\FALSE flag indicating whether TTS Is installed.
Common Use..: Determine if TTS is installed.
See Also....: n_IPX,
              n_NETBIOS,
              n_SHARE,
              n_SPX.
Example.....: Determine if TTS is installed.


              #include "user_int.h"
              void main(void)
              {
              w_init();
              if (n_TTS())                /* Check if TTS is installed      */
                  v_prtf("TTS is installed.\n");
              else
                  v_prtf(TTS is not installed.\n");
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_user_name.
Purpose.....: Given a connection number, get a user's name.  The name can be
              up to  47 characters  long, plus a  terminating NULL character.
Syntax......: int n_user_id(unsigned char connection_number,char *user_name);
              unsigned char connection_number;    Connection number (1-100)
              char         *user_name;            User's name
Example call: n_user_name(connect_num, name);
Returns.....: TRUE\FALSE flag indicating whether connection number is valid
              and if the function was able to obtain the user's name.
Common Use..: Since connection numbers are assigned in login  order, ie, who
              logged in  first, who logged in  second, etc, you can use this
              function to see who is logged in and in what order they logged
              in.
See Also....: n_bindery_object_name,
              n_bindery_object_scan.
Example.....: Get your own name from your connection number.


              #include "user_int.h"
              void main(void)
              {
              unsigned int con_num;
              char name[48];
              w_init();
                                          /* Get your connection number     */
              con_num=n_local_connection_number();
              n_user_name(con_num,name);  /* Get your name from connection #*/
              k_wait(0);
              w_exit(0);
              }

                                                     15 - Network



Function....: n_version.
Purpose.....: Get the Novell netware version you are using.
Syntax......: int n_version(void);
Example call: if (n_version()<0x300) break;
Returns.....: If you are on a network, the Novell netware version is returned
              in BCD format.  Otherwise, 0 is returned.
Common Use..: Get the Novell netware version you are running under.
See Also....: None.
Example.....: Get the Novell netware version.


              #include "user_int.h"
              void main(void)
              {
              int version=0;

              w_init();
              if (w_network.installed)       /* Check if were on a network   */
                  version=n_version;         /* If yes, get Netware version  */
              if (version)
                  v_prtf("Netware version: %2X.%2.2X\n",
                         version & 0xFF00>8, /* Major version                */
                         version & 0x00FF);  /* Minor version                */
              else
                 v_prtf("Netware not installed.\n");
              k_wait(0);
              w_exit(0);
              }

                                                     16 - Globals



                                  Chapter 16

                                   Globals


                                                     16 - Globals


    Concepts

    The C User  Interface maintains a  large number of globals. Most of these
globals contain information  about the computers hardware.  A list of all the
global variables used by the C User Interface Library is shown on the follow-
ing pages.  All globals are prefixed  with "w_".  Some of  the globals may be
read only, some may be modified, and some are for internal use only. The read
and write descriptions will contain one of three following words:

            Directly
            None
            function name

    If the word "Directly" appears, it means that you can directly access the
variable. For example,the read field for w_cursor states that you may direct-
ly access this variable  for reading.  This means, that  statements  such as:
"if (w_cursor)" are permissible.  If the word "Directly" appears in the write
field, this  means you  may modify  the variable  directly.  For example, the
w_ERROR write field states that you may modify it directly.  Thus, statements
such as: "w_ERROR=FALSE" are permissible. However, if the read or write field
contains the word "None", then the global  is reserved for internal use only,
and you may not reference the variable in any way. Finally,if a function name
appears in the read or write fields, this indicates that  the variable may be
referenced, but only through function calls to the routines listed.  They may
not be referenced directly.

                                                     16 - Globals

                         Global List


       Variable               Description
          
       w_aut_return           Flag indicating if user must press Enter to end
                              data input.
       w_border               Current border style.
       w_box                  Box drawing characters.
       w_color                Current color.
       w_color_data           Data input window color.
       w_color_editor_block   Editor color for block commands.
       w_color_editor_text    Editor text and window color.
       w_color_error          Error message window color.
       w_color_help           Context Sensitive Help window color.
       w_color_menu           Menu color.
       w_color_overall        Screen color.
       w_cur_col              Physical cursor column coordinate.
       w_cur_row              Physical cursor row    coordinate.
       w_cursor               Flag indicating whether cursor is on.
       w_def_INT_09           Replacement keyboard ISR.
       w_DOS                  DOS memory and version.
       w_DPMI                 DOS Protected Mode Interface memory and version.
       w_EMS                  EMS memory and version.
       w_ERROR                Flag indicating a floating pt./Critical error.
       w_ext_vga_modes        Non-standard VGA modes.
       w_floppy               Types of floppy drives.
       w_funkeys              Function key Routine pointers.
       w_get                  Get.
       w_get.cur_get          Currently active get.
       w_get.num_gets         Total number of gets currently set.
       w_get.get[]->edit_var  Edit copy of get variable.
       w_hard_drive           Hard drive capacity.
       w_help_dat_path        Path to Help.dat file.
       w_help_ntx_path        Path to Help.ntx file.
       w_last_drive           Letter of last logical drive.
       w_lastkey              Character code of last key pressed.
       w_max_cols             Number of columns on screen.
       w_max_rows             Number of rows on screen.
       w_monitor              Monitor type and resolution.
       w_mouse                Mouse type and position.
       w_network              Network programs and version.
       w_num_floppies         Number of floppy drives present.
       w_num_serial_ports     Number of serial ports present.
       w_num_parallel_ports   Number of parallel ports present.
       w_parallelport         Parallel port addresses.
       w_pc                   Computer type and processors.
       w_printer              Printer port and type.
       w_printer_dat_path     Path to printer.dat.
       w_printer_ntx_path     Path to printer.ntx.
       w_screen_style         Background screen style.
       w_serialport           Serial port addresses.
       w_setup_path           Path to setup.dat.

                                                     16 - Globals

                         Global List


       Variable               Description
          
       w_shadows              Flag indicating if shadows are on.
       w_shd_attr             Attribute used to draw shadows.
       w_sound                Flag indicating if sound should be on or off.
       w_start_c_col          Cursor column at start up.
       w_start_c_row          Cursor row at start up.
       w_start_mode           Video mode at start up.
       w_start_screen         Initial screen at start up.
       w_substring            Static buffer used to return substrings.
       w_user                 Network user information.
       w_VCPI                 Virtual Control Program Interface memory and ver.
       w_video_mem            Base address of video text memory.
       w_XMS                  XMS memory and version.

                                                     16 - Globals



Variable....: w_aut_return.
Type........: int.
Read........: None.
Write.......: w_setup().
Description.: This flag indicates whether Enter must be  pressed to end a read
              of a get.  If w_aut_ret is  FALSE, then if  the user reaches the
              end of the get specified by the max_char parameter, the get will
              automatically end.  If w_aut_return is TRUE, then  the user must
              press Enter to end the read.

                                                     16 - Globals



Variable....: w_border.
Type........: int.
Read........: w_getborder().
Write.......: w_setborder().
Description.: This variable  holds  the border style  which specifies the line
              drawing characters held by w_box.  The border styles  are listed
              in  w_window.h.  This  variable  may  be  accessed  through  the
              w_setborder and w_getborder functions.  Once set, all subsequent
              windows  will  be  drawn  using  the  border  style specified by
              w_border.

                                                     16 - Globals



Variable....: w_box
Type........: char [6];
Read........: w_getborder().
Write.......: w_setborder().
Description.: This array holds the box drawing characters used by w_setborder.
              The array is arranged as follows:

              byte      character
                    
               0        Upper left hand corner.
               1        Top.
               2        Upper right hand corner.
               3        Side.
               4        Lower right hand corner.
               5        Lower left hand corner.

                                                     16 - Globals



Variable....: w_color.
Type........: int.
Read........: v_getcolor().
Write.......: v_setcolor().
Description.: Holds the color attribute with which all subsequent screen print-
              ing will  be done.  The variable  is accessed  through v_setcolor
              and v_getcolor.  w_color is composed of a foreground and a  back-
              ground color.  Predefined  constants can be found  in w_window.h,
              with 8 Background  colors, prefixed with "B_", and 16  foreground
              colors, prefixed with "F_".  For example, B_BLUE | F_PURPLE is  a
              purple foreground on a blue background.


                                                     16 - Globals



Variable....: w_color_data.
Type........: ATTRIBUTE.
Read........: None.
Write.......: w_setup().
Description.: This  variable  holds the  screen attributes  for the data input
              color.  The  ATTRIBUTE  structure  shown  below  is  defined  in
              windows.h.  The  variable  can  only  be  set  through a call to
              w_setup, and is stored in the users setup.dat file.

              typedef struct
              {
                  unsigned standard,
                           enhanced;
              } ATTRIBUTE;

                                                     16 - Globals



Variable....: w_color_editor_block.
Type........: ATTRIBUTE.
Read........: None.
Write.......: w_setup().
Description.: This variable holds  the attributes  for the file  editor  block
              colors(Blocked text and EOF line). The ATTRIBUTE structure shown
              below is  defined in  windows.h.  The variable  can only  be set
              through a call to w_setup, and is stored in the users  setup.dat
              file.

              typedef struct
              {
                  unsigned standard,
                           enhanced;
              } ATTRIBUTE;

                                                     16 - Globals



Variable....: w_color_editor_text.
Type........: ATTRIBUTE.
Read........: None.
Write.......: w_setup().
Description.: This variable  holds the  attributes  for the file  editor  text
              colors(Window and text).  The ATTRIBUTE structure shown below is
              defined in windows.h.The variable can only be set through a call
              to w_setup,and is stored in the users setup.dat file.

              typedef struct
              {
                  unsigned standard,
                           enhanced;
              } ATTRIBUTE;

                                                     16 - Globals



Variable....: w_color_error.
Type........: ATTRIBUTE.
Read........: None.
Write.......: w_setup().
Description.: This  variable holds  the screen attributes for the error color.
              The ATTRIBUTE structure shown below is defined in windows.h. The
              variable can only be set through a call to w_setup,and is stored
              in the users setup.dat file.

              typedef struct
              {
                  unsigned standard,
                           enhanced;
              } ATTRIBUTE;

                                                     16 - Globals



Variable....: w_color_help.
Type........: ATTRIBUTE.
Read........: None.
Write.......: w_setup().
Description.: This  variable holds  the screen attributes  for the help color.
              The ATTRIBUTE structure shown below is defined in windows.h. The
              variable can only be set through a call to w_setup,and is stored
              in the users setup.dat file.

              typedef struct
              {
                  unsigned standard,
                           enhanced;
              } ATTRIBUTE;

                                                     16 - Globals



Variable....: w_color_menu.
Type........: ATTRIBUTE.
Read........: None.
Write.......: w_setup().
Description.: This  variable holds  the screen attributes  for the menu color.
              The ATTRIBUTE structure shown below is defined in windows.h. The
              variable can only be set through a call to w_setup,and is stored
              in the users setup.dat file.

              typedef struct
              {
                  unsigned standard,
                           enhanced;
              } ATTRIBUTE;

                                                     16 - Globals



Variable....: w_color_overall.
Type........: ATTRIBUTE.
Read........: None.
Write.......: w_setup().
Description.: This variable holds  the screen attributes for the screen color.
              The ATTRIBUTE structure shown below is define in windows.h.  The
              variable can only be set through a call to w_setup,and is stored
              in the users setup.dat file.

              typedef struct
              {
                  unsigned standard,
                           enhanced;
              } ATTRIBUTE;

                                                     16 - Globals



Variable....: w_cur_col.
Type........: int.
Read........: v_getcur().
Write.......: v_setcur().
Description.: This global contains the current video cursor column coordinate.
              It may be  read by  calling v_getcur and  can  be set by calling
              v_setcur.

                                                     16 - Globals



Variable....: w_cur_row.
Type........: int.
Read........: v_getcur().
Write.......: v_setcur().
Description.: This global contains the current video cursor row coordinate. It
              may be  read by  calling v_getcur  and  can  be  set by  calling
              v_setcur.

                                                     16 - Globals



Variable....: w_cursor.
Type........: int.
Read........: Directly.
Write.......: v_curon(), v_curoff().
Description.: This global is a flag indicating whether the video cursor is
              currently on or off.  It may be read Directly, and is set by
              calling either v_curon or v_curoff to turn the cursor on and
              off respectively.

                                                     16 - Globals



Variable....: w_def_INT_09.
Type........: void interrupt (*)(void);
Read........: Directly.
Write.......: None.
Description.: In order to  disable Ctrl-C\Break without  corrupting the screen,
              the keyboard ISR for interrupt 09h had to be chained on to. Also,
              w_exit has to be able to restore the default ISR before terminat-
              ing any  application.  Thus, this global holds the  original 0x09
              ISR @.

                                                     16 - Globals



Variable....: w_DOS.
Type........: MEMORY.
Read........: Directly.
Write.......: w_DOS_total(), w_DOS_avail().
Description.: w_DOS contains information about conventional memory. The memory
              structure  shown  below  and  defined  in  windows.h   shows  the
              information contained in the w_DOS global.  This variable is also
              displayed by w_display_config().  This variable may  be read dir-
              ectly, but may  not be written to.  It is set  by w_init() at the
              start of the program, and  therefore does not reflect the current
              status of available DOS memory.  You may  determine the amount of
              DOS(conventional)  memory, both total and  available, at any time
              by calling  w_DOS_total() and w_DOS_avail().  See w_window.h  for
              the function prototypes.

              typedef struct
              {
                unsigned int version;
                unsigned long int total;
                unsigned long int available;
              } MEMORY;

                                                     16 - Globals



Variable....: w_DPMI.
Type........: MEMORY.
Read........: Directly.
Write.......: w_DPMI_memory().
Description.: w_DPMI contains information about the DOS  Protected mode inter-
              face.  The memory structure shown  below and defined in windows.h
              shows the information  contained in the w_DPMI global.  This var-
              iable is also displayed by w_display_config().  This variable may
              be read directly,but may not be written to. It is set by w_init()
              at the start  of the program, and  therefore does not reflect the
              current status of available DPMI memory.  DPMI memory may only be
              detected when running  in protected mode.  You may  determine the
              amount of DPMI memory, both total and  available, at any  time by
              calling w_DPMI_memory().  See w_window.h  for the function proto-
              types.

              typedef struct
              {
                unsigned int version;
                unsigned long int total;
                unsigned long int available;
              } MEMORY;

                                                     16 - Globals



Variable....: w_EMS.
Type........: MEMORY.
Read........: Directly.
Write.......: w_EMS_total(), w_EMS_avail().
Description.: w_EMS  contains  information about  Expanded memory.  The memory
              structure  shown  below  and  defined  in  windows.h  shows  the
              information contained in the w_EMS global. This variable is also
              displayed by w_display_config().  This variable may be read dir-
              ectly, but may not be written to.  It is set  by w_init() at the
              start of the program, and therefore does not reflect the current
              status of available or total EMS memory.  You may  determine the
              amount of DPMI memory, both total and available, at any  time by
              calling w_DPMI_total() and w_DPMI_avail().See w_window.h for the
              function prototypes.


              typedef struct
              {
                unsigned int version;
                unsigned long int total;
                unsigned long int available;
              } MEMORY;

                                                     16 - Globals



Variable....: w_ERROR.
Type........: int.
Read........: Directly.
Write.......: Directly.
Description.: This global is set to TRUE whenever a floating point exception or
              Critical  Error occurs.  You may read the variable directly,  and
              may reset the  variable to FALSE  when it is detected to be TRUE.
              You should never set the variable to TRUE.

                                                     16 - Globals



Variable....: w_ext_vga_modes.
Type........: char [3].
Read........: None.
Write.......: None.
Description.: Holds the non-standard VGA modes for 25 x 132, 28 x 132, and  44
              x 132 columns.  This information is  placed into  the  setup.dat
              file by the user with a standard text editor.  See w_setup() for
              more information.

                                                     16 - Globals



Variable....: w_floppy.
Type........: char [4].
Read........: Directly.
Write.......: None.
Description.: Set by w_init(), w_floppy[i] holds the drive type  of up to four
              floppy drives, drive A  in floppy[0], drive B in floppy[1], etc.
              The drive types are listed below.

              Drive Type         w_floppy[]
                      
              Not present            0
              5" 360K               1
              5" 1.2M               2
              3" 720K               3
              3" 1.44M              4
              3" 2.88M              5
              Unknown                6

              The  value may be read directly or viewed by w_display_config().
              w_floppy  refers  to floppy  drives  only.  See the  w_hard_disk
              global to see  whether a  hard  drive is present, and if so it's
              capacity.

                                                     16 - Globals



Variable....: w_funkeys.
Type........: void (* [12])(int type,void *ptr,int indx,char *help_word);
Read........: Directly.
Write.......: k_set().
Description.: Array of pointers to function key routines. Each of the function
              keys may be  set to execute  a function  whenever it is pressed.
              This sets  up the function  key as  a "hot" key.  Initially,  at
              program startup, the F1  key is set to the help routine, and the
              rest of the  keys are set to a default, called k_FX_def(), which
              does nothing but sound an error beep.  You may set  any function
              key to your own function using k_set().  See k_set() in the Key-
              board chapter for more information.

                                                     16 - Globals



Variable....: w_get.
Type........: GET
Read........: Directly.
Write.......: None.
Description.: Holds information about the currently pending gets.  The GET
              structure is shown below.

              typedef struct GET_ITEM
              {
              WIN_PTR window;         /* Window in which get will be done    */
              int     row,            /* Window row where prompt will start  */
                      col;            /* Window col where prompt will start  */
              char   *prompt;         /* Prompt text                         */
              int     get_type;       /* Type of variable to edit            */
              void   *get_var;        /* Address of variable being edited    */
              void   *edit_var;       /* Edit copy of variable               */
              int     edit_col;       /* Column after prompt where edit begin*/
              char   *mask;           /* Edit mask                           */
              char   *buffer;         /* Screen buffer used to edit variable */
              int     max_char,       /* Length of screen edit buffer        */
                      disp_flag;      /* Display initial value or not        */
              char   *help_word;      /* Help key word                       */
              int    (*valid)(void);  /* Valid function                      */
              } GET_ITEM;

              typedef struct GET_DATA
              {
              int       num_gets;            /* Number of pending gets       */
              int       cur_get;             /* Index of currently active get*/
              GET_ITEM *get[MAX_NUM_GETS];   /* Pointer to an array of gets  */
              } GET;

                                                     16 - Globals



Variable....: w_get.cur_get.
Type........: int.
Read........: Directly.
Write.......: Directly.
Description.: Holds the index of the currently active get.  The gets are num-
              bered starting from 0.

                                                     16 - Globals



Variable....: w_get.num_gets.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: Holds the total number of gets currently active.

                                                     16 - Globals



Variable....: w_get.get[w_get.cur_get]->edit_var.
Type........: void *.
Read........: Directly.
Write.......: Directly.
Description.: Pointer to the currently active get edit variable.  When you set
              up a get for a variable, the C User Interface Library automatic-
              ally creates a duplicate of the  variable.  It is this duplicate
              that you edit when a g_read() is performed.  If the user presses
              ESC to end the read,then the duplicate variable is discarded and
              the changes are lost.  The original variable is left  unchanged.
              Otherwise, when the user ends the read  by pressing ENTER on the
              last get, or presses PAGE DOWN, the original variable is updated
              with the changes  made to  this duplicate  variable.  After  the
              original variable is updated, the duplicate is discarded.

                                                     16 - Globals



Variable....: w_hard_drive.
Type........: HARD_DRIVE [2].
Read........: Directly.
Write.......: None.
Description.: Contains the capacities in megs and the drive letters of the hard
              drives found.  Although most hard drives start at letter C and go
              up from their, the actual  drive letter depends on the  number of
              floppy drives present.  If 1  or 2 floppies are present, then the
              hard drive letters  will start at C.  If 3 or 4 are present, then
              the  hard drive  letters will start at D and E respectively.  For
              this reason, the drive  letter as  well as  the size of the drive
              are stored  together.  Since most controllers support at most two
              drives, the C  User Interface Library only checks for at most two
              hard drives.  If  a hard drive is  not found, then  the size  and
              letter  are set  to 0.  The w_hard_drive  variable may  be viewed
              directly or viewed by w_display_config().

                                                     16 - Globals



Variable....: w_help_dat_path.
Type........: char [80].
Read........: None.
Write.......: None.
Description.: This is the full path to the applications  help.dat file.  It is
              set by w_init. If w_init can not find the help.dat file, it will
              exit the program.

                                                     16 - Globals



Variable....: w_help_ntx_path.
Type........: char [80].
Read........: None.
Write.......: None.
Description.: This is the full path to the applications  help.ntx file.  It is
              set by w_init. If w_init can not find the help.ntx file, it will
              exit the program.

                                                     16 - Globals



Variable....: w_last_drive.
Type........: char.
Read........: Directly.
Write.......: None.
Description.: This global holds the letter of the last logical drive available
              in the system.  This is set by w_init() and may not  reflect the
              current status of system drives.

                                                     16 - Globals



Variable....: w_lastkey.
Type........: unsigned int.
Read........: Directly.
Write.......: None.
Description.: Contains the last key pressed by the user.

                                                     16 - Globals



Variable....: w_max_cols.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: Holds the last column number available on the screen.

                                                     16 - Globals



Variable....: w_max_rows.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: Holds the last row number available on the screen.

                                                     16 - Globals



Variable....: w_monitor.
Type........: SCREEN.
Read........: Directly.
Write.......: None.
Description.: This variable holds information about the video card and monitor.
              The screen structure shown below, is  defined  in windows.h.  The
              variable may be read directly or viewed by w_display_config(). It
              is set by w_init().

              typedef struct
              {
                  char adapter[20];
                  int  color;
                  int  ver_res;
                  int  hor_res;
                  int  max_colors;
              } SCREEN;

              The possible adapter types are:

              1.  None
              2.  MDA
              3.  Hercules
              4.  MCGA
              5.  CGA
              6.  EGA
              7.  PGA
              8.  VGA
              9.  SVGA
              10. IBM 8514/A
                                                     16 - Globals



Variable....: w_mouse.
Type........: W_MOUSE.
Read........: Directly.
Write.......: All mouse functions.
Description.: This  variable  contains information about the mouse.  All mouse
              functions return  their information  by  updating various fields
              of the w_mouse variable.  The W_MOUSE  structure is shown below.

              typedef struct MOUSE_DATA
              {
                 int       installed,     /* Flag if mouse is installed      */
                           version,       /* Driver version in BCD           */
                           type,          /* Mouse type                      */
                           irq,           /* Interrupt line used             */
                           num_buttons,   /* Number of buttons on mouse      */
                           cursor,        /* Cursor On/Off flag              */
                           pix_row,       /* Pixel  row                      */
                           pix_col,       /* Pixel  column                   */
                           txt_row,       /* Text   row                      */
                           txt_col,       /* Text   column                   */
                           rht_but,       /* Right  button pressed flag      */
                           lft_but,       /* Left   button pressed flag      */
                           cnt_but;       /* Center button pressed flag      */
                 char far *copyright;     /* Copyright notice in mouse driver*/
              } MOUSE;

              The mouse type and irq are defined as:

        w_mouse.type   Type               w_mouse.irq   IRQ line
                          
            0          Unknown                 0        PS/2
            1          Bus                     1        Unknown
            2          Serial                  2        IRQ2
            3          Port                    3        IRQ3
            4          PS/2                    4        IRQ4
            5          HP                      5        IRQ5
                                               6        IRQ6
                                               7        IRQ7

                                                     16 - Globals



Variable....: w_network.
Type........: N_NETWORK.
Read........: Directly.
Write.......: None.
Description.: This variable contains information about various network modules
              and version information. This is Novell network specific and can
              not be used for other types of LANS. w_network.installed is TRUE
              if IPX is installed.  SPX, SHARE, and NETBIOS are  TRUE if these
              programs are  installed.  TTS  is TRUE if  the network  supports
              Transaction tracking.  If  w_network.installed is  TRUE, then we
              are on a Novell network,and the version is stored in the version
              field.  The structure is shown below.

              typedef struct
              {
                  int      installed;
                  int      SPX;
                  int      TTS;
                  int      SHARE;
                  int      NETBIOS;
                  unsigned int version;
              }   N_NETWORK;

                                                     16 - Globals



Variable....: w_num_floppies.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: This variable contains the number of  floppy drive in the system.
              It is set by w_init. It can be viewed by calling w_display_config
              and read directly.

                                                     16 - Globals



Variable....: w_num_parallel_ports.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: This  variable contains the number of parallel ports present in
              the system. Is set by w_init,and may be read directly or viewed
              by calling w_display_config().

                                                     16 - Globals



Variable....: w_num_serial_ports.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: This variable contains the number of serial ports present in the
              system. Is set by w_init(),and may be read directly or viewed by
              calling w_display_config().

                                                     16 - Globals



Variable....: w_parallelport.
Type........: unsigned int [4].
Read........: Directly.
Write.......: None.
Description.: This variable  holds the  addresses of the  parallel ports.  The
              number  of parallel  ports present  is  in w_num_parallel_ports.
              The port addresses are 2 bytes each, and can be read directly or
              viewed by w_display_config().  It is set by w_init().

                                                     16 - Globals



Variable....: w_pc.
Type........: MACHINE.
Read........: Directly.
Write.......: None.
Description.: The w_pc  variable holds  information about the type of computer
              an  application  is being run  on.  The machine structure, shown
              below holds the names of the computers model, cpu, and  math co-
              processor, as well as its operating speed in Mhz.  This variable
              is set by w_init. You may read the variable directly, or view it
              by calling w_display_config().

              typedef struct
              {
                  char  brand[15];
                  char  cpu[8];
                  float speed;
                  char  math_coprocessor[8];
              } MACHINE;

                                                     16 - Globals



Variable....: w_printer.
Type........: PRINTER.
Read........: Directly.
Write.......: w_setup().
Description.: Variable identifying the printer type and the port it is connected
              to.  Also holds  the printer's status codes and  command language.
              The PRINTER structure  is shown  below.  The  valid ports are LPT1
              LPT2,and LPT3. The user may select a printer for each of the three
              parallel ports.  These printers are stored in the user's setup.dat
              file, as is the currently selected port.

              typedef struct
              {
                  char flag;
                  char path[128];
                  FILE *handle;
              }   REDIRECT;

              typedef struct
              {
                  char            model[3][P_MODEL_LENGTH+1];
                  char            emulation[3][P_MODEL_LENGTH+1];
                  PRINT_CONTROL   old_capture;
                  unsigned char   cur_port;
                  REDIRECT        redirected;
                  unsigned char **commands;
                  int             num_printers;
                  int             num_ports;
              } PRINTER;

                                                     16 - Globals



Variable....: w_printer_dat_path.
Type........: char [].
Read........: None.
Write.......: None.
Description.: Holds path to printer.dat file.  This file is a database of sup-
              ported printers and their corresponding command languages.

                                                     16 - Globals



Variable....: w_printer_ntx_path.
Type........: char [].
Read........: None.
Write.......: None.
Description.: Holds path to printer.ntx file.

                                                     16 - Globals



Variable....: w_screen_style.
Type........: int.
Read........: None.
Write.......: w_setup().
Description.: This is a flag  indicating the screen style.  There are  3 valid
              screen style whose values  are listed in w_windows.h.  They are:
              1. Clear.
              2. Tiled.
              3. Checkered.

              This variable may only be modified by calling w_setup. Its value
              is stored in the users setup.dat file.

                                                     16 - Globals



Variable....: w_serialport.
Type........: unsigned int [4].
Read........: Directly.
Write.......: None.
Description.: This variable contains the addresses  of the serial ports.  Each
              port address is 2 bytes long. The number of serial ports is held
              in the variable w_num_serial_ports.  Both of these variables are
              set by w_init.  These  variables may be read directly, or viewed
              by calling w_display_config().

                                                     16 - Globals



Variable....: w_setup_path.
Type........: char [80].
Read........: None.
Write.......: None.
Description.: This  is the full  path to the  users setup.dat file.  This file
              contains the settings for the users color and screen preferences.
              The variable if set  by w_init.  If the users setup.dat file can
              not be found, w_init aborts the program.

                                                     16 - Globals



Variable....: w_shadows.
Type........: int.
Read........: None.
Write.......: w_setup().
Description.: This is a flag indicating whether windows should have shadows or
              not.  It can only  be changed  by calling w_setup.  The value of
              w_shadows is stored in the users setup.dat file.

                                                     16 - Globals



Variable....: w_shd_attr.
Type........: int.
Read........: None.
Write.......: None.
Description.: This is the attribute used to draw shadows on windows.  Its value
              depends on the screen color w_color_overall and the screen style.
              When  the window color is 8,24,40,56,74,90, or 106 and the screen
              style is clear, the  normal shadow  attribute of 8 is the same as
              the foreground color and  the shadows  become "invisible".  Thus,
              the shadow  attribute is set to  112 whenever the screen color is
              one of the above attributes.

                                                     16 - Globals



Variable....: w_sound.
Type........: int.
Read........: Directly.
Write.......: w_setup().
Description.: This flag is  used  internally  by  several  functions,  notably
              w_ynbox and w_errbox.  If w_sound is TRUE, then  these functions
              will sound a beep  before displaying their  messages. Otherwise,
              no beep will sound.

                                                     16 - Globals



Variable....: w_start_c_col.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: This is the initial cursor column at start up.  It is saved by
              w_init and restored by w_exit.

                                                     16 - Globals



Variable....: w_start_c_row.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: This is the cursor row location at start up.  It is saved by
              w_init and restored by w_exit.

                                                     16 - Globals



Variable....: w_start_mode.
Type........: int.
Read........: Directly.
Write.......: None.
Description.: This is the initial video mode at start up. It is saved by w_init
              and restored by w_exit.

                                                     16 - Globals



Variable....: w_start_screen.
Type........: char [].
Read........: None.
Write.......: None.
Description.: This is a buffer used to  save and restore the initial screen.
              The start up screen is saved by w_init and restored by w_exit.

                                                     16 - Globals



Variable....: w_substring.
Type........: char [257];
Read........: w_substring().
Write.......: None.
Description.: This global holds the return string from the w_substring function.
              Since C does not  allocate memory  to return strings, this  saves
              the user  from having  to allocate memory and from having to pass
              the  address of a  substring buffer, and makes  the function call
              much easier to use.

                                                     16 - Globals



Variable....: w_user.
Type........: N_USER_ID.
Read........: Directly.
Write.......: None.
Description.: If you are on a  Novell network, then this global will be filled
              in with information about you, otherwise, it has no meaning. The
              structure is shown below. The object_id is a 4 byte number which
              uniquely identifies you.  The name is a Null  terminated  string
              which holds your user name.  The network node is a 6 byte number
              identifying your work station. The connection_number is a number
              between 1 and  100, and  represents the  order in which you were
              logged in. Finally, the network_number is a 4 byte number ident-
              ifying the segments of a multiserver network.

              typedef struct
              {
                  unsigned char connection_number;
                  unsigned char network_number[4];
                  unsigned char network_node[6];
                  unsigned long object_id;
                  unsigned char name[48];
              }   N_USER_ID;

                                                     16 - Globals



Variable....: w_VCPI.
Type........: MEMORY.
Read........: Directly.
Write.......: w_VCPI_total(), w_VCPI_avail().
Description.: w_VCPI contains  information  about  the Virtual Control Program
              interface.  The memory  structure shown  below  and  defined  in
              windows.h shows  the information contained in the w_VCPI global.
              This variable is also displayed by w_display_config(). This var-
              iable may be read directly, but may not be written to. It is set
              by w_init() at the start of the  program, and therefore does not
              reflect the current status of available VCPI memory. You may de-
              termine the amount of VCPI memory, both total and available,  at
              any  time  by  calling w_VCPI_total()  and  w_VCPI_avail().  See
              w_window.h for the function prototypes.

              typedef struct
              {
                unsigned int version;
                unsigned long int total;
                unsigned long int available;
              } MEMORY;

                                                     16 - Globals



Variable....: w_video_mem.
Type........: unsigned char far *.
Read........: Directly.
Write.......: None.
Description.: This variable  holds the base  address of video text memory.  It
              is set  by an internal  function, w_config,  which  is called by
              w_init.  w_video_mem is set to B800:0000h for color monitors and
              to B000:0000h for monochrome monitors.

                                                     16 - Globals



Variable....: w_XMS.
Type........: MEMORY.
Read........: Directly.
Write.......: w_XMS_total(), w_XMS_avail().
Description.: w_XMS  contains information about  Extended memory.  The memory
              structure  shown  below  and  defined  in  windows.h  shows  the
              information contained in the w_XMS global. This variable is also
              displayed by w_display_config().  This variable may be read dir-
              ectly, but may not  be written to.  It is set by w_init() at the
              start of the program, and therefore does not reflect the current
              status of available or total XMS memory.  You may  determine the
              amount of XMS memory, both total and available,  at any time  by
              calling w_XMS_total() and w_XMS_avail().  See w_window.h for the
              function prototypes.

              typedef struct
              {
                unsigned      int version;
                unsigned long int total;
                unsigned long int available;
              } MEMORY;

                                                     Appendix A



                                Bibliography


      1.  Nabajyoti Barkati, The Wait Group's Microsoft C Bible, Howard W. Sams
          & Company, 1988.

      2.  Nabajyoti Barkati, The Wait Group's Turbo C Bible, Howard W. Sams &
          Company, 1989.

      3.  Citizen GSX-140 Plus User's Manual, Citizen America Corporation,
          1991.

      4.  Ray Duncan, Programmers Quick Reference Series, MS-DOS Functions,
          Microsoft Press, 1988.

      5.  Ray Duncan, Programmers Quick Reference Series, IBM ROM BIOS
          Functions, Microsoft Press, 1988.

      6.  Ray Duncan, General Editor, The MS-DOS Encyclopedia,Microsoft Press,
          1988.

      7.  Peter Norton, Richard Wilton,Programmers Guide to the IBM PC & PS/2,
          Microsoft Press, 1988.

      8.  Al Stevens, Extending Turbo C Professional, MIS Press, 1989.

      9.  Phoenix Technologies Ltd., System BIOS for IBM PC/XT/AT Computers
          and Compatibles, Addison-Wesley Publishing Company, Inc., 1989.

      10. Steven Holzner, C With Assembly Language, Brady, 1989.

      11. Borland International, Inc., Turbo C Reference Guide Version 2.0,
          Borland International, 1988.

      12. Borland International, Inc., Turbo C User's Guide Version 2.0,
          Borland International, 1988.

      13. Thom Hogan, The C Programmers Handbook, Brady Communications Company,
          Inc., 1984.

      14. The Cobb Group, Inc., Inside Turbo C, The Cobb Group, Inc., 1989 -
          1991.

      15. Lotus/Intel/Microsoft Expanded Memory Specification Version 4.0,
          Lotus Development Corporation, Intel Corporation, Microsoft
          Corporation, 1987.

      16. George Sutty and Steve Blair, Advanced Programmer's Guide to
          SuperVGAs, Brady, 1990

      17. Charles G. Rose, Programmer's Guide to Netware,
          SuperVGAs, McGraw-Hill, 1990

                                                     Appendix A



                                Bibliography


      18. Hewlett Packard, PCL5 Printer  Language Technical  Reference  Manual,
          Hewlett Packard

                                                     Appendix B












                           Default Valid Functions



                               def_val_char
                               def_val_chkbox
                               def_val_date
                               def_val_double
                               def_val_ext_date
                               def_val_ext_time
                               def_val_ext_zip
                               def_val_file_name
                               def_val_float
                               def_val_int
                               def_val_long
                               def_val_password
                               def_val_phone
                               def_val_soc_sec
                               def_val_string
                               def_val_tf
                               def_val_time
                               def_val_unchar
                               def_val_unint
                               def_val_unlong
                               def_val_yn
                               def_val_zip

                                                     Appendix B



                           Default Valid Functions


       This section describes the action taken by the default valid functions.
    Whenever you don't specify an explicit  valid function for a "get", The  C
    User Interface Library uses  a default function.  These default  functions
    are described below.

    1.  def_val_char       - Returns TRUE always.

    2.  def_val_chkbox     - Converts all  characters to lower  case x and re-
                             turns TRUE.

    3.  def_val_date       - If the last key pressed was an up arrow, TRUE  is
    4.  def_val_ext_date     returned.  Otherwise, the  following  checks  are
                             performed:

                             a. 1  month  12
                             b. 1  day    days in month

                             The  default  valid will return  FALSE if any  of
                             these conditions are not met, and TRUE otherwise.

    5.  def_val_double     - If the last key  pressed was an up arrow, TRUE is
                             returned.  Otherwise, TRUE is returned.

    6.  def_val_filename   - If the last key pressed was  an up arrow, TRUE is
                             returned.  Otherwise,  the full path name is con-
                             structed.  This full path name is then checked to
                             see  that it  conforms to DOS' directory\filename
                             naming scheme. If the path name is an invalid DOS
                             name,FALSE is returned.Otherwise TRUE is returned
                             The  filename default valid does not check if the
                             filename\directory exists, only whether or not it
                             is a valid name.

    7.  def_val_float      - Returns TRUE always.

    8.  def_val_int        - Returns TRUE always.

    9.  def_val_long       - Returns TRUE always.

                                                     Appendix B



                           Default Valid Functions


    10. def_val_password   - Returns  TRUE always. It also displays  a warning
                             message which says that  you should be using your
                             own password valid function.  Your valid function
                             should be a  database lookup routine to check the
                             name  and password of your users.

    11. def_val_phone      - If the last key pressed was an up arrow, TRUE  is
                             returned. Otherwise, the default valid will leave
                             the area code as optional, but force the standard
                             seven digits to be entered.

    12. def_val_socsec     - If the last key  pressed was an up arrow, TRUE is
                             returned. Otherwise,the default valid will ensure
                             that all 11 digits of the social security  number
                             have been filled in.

    13. def_val_string     - Returns TRUE always.


    14. def_val_time       - If the last key pressed was an up arrow, TRUE  is
    15. def_val_ext_time     returned.  Otherwise, the  following  checks  are
                             performed:

                             a. 1  hour    12
                             b. 1  minute  59
                             c. 1  second  59
                             d. meridian == 'a' or 'p'

    16. def_val_tf         - If the last key pressed was an up arrow, TRUE  is
                             returned.Otherwise, the character entered is con-
                             verted to upper case.  Then, if the character  is
                             'T' or 'F', TRUE is returned. Otherwise, FALSE is
                             returned.

    17. def_val_unchar     - Returns TRUE always.

    18. def_val_unint      - Returns TRUE always.

    19. def_val_unlong     - Returns TRUE always.

    20. def_val_yn         - If the last key pressed was an up arrow, TRUE  is
                             returned.Otherwise, the character entered is con-
                             verted to upper case.  Then, if  the character is
                             'Y' or 'N', TRUE is returned. Otherwise, FALSE is
                             returned.

    21. def_val_zip        - If the last key pressed was  an up arrow, TRUE is
    22. def_val_ext_zip      returned.  The default valid ensures that the 1st
                             five digits of the zip code have been  filled in.
                             The last four digits are optional.

                                                     Appendix C



                                Utilities













                                HLP_INDX

                                PRT_INDX

                                PRT_MAN

                                PRT_STAT

                                PRT_TEST

                                                     Appendix C



                                Utilities




Utility.....: index.
Purpose.....: Used to create\update index files for companion .dat files.
Description.: index is used to create .ntx files for corresponding .dat files.
              The C User Interface Library uses 3 database files:
              1. printer.dat
              2. help.dat
              3. error.dat

              All 3 of  these files are  optional and are not needed  to write
              applications using the C User Interface Library.  For a descrip-
              tion of  these  files, see  the following: Chapter  on printing,
              Chapter on  help, and the w_errbox()  function in the Chapter on
              windows.  index creates  a matching  .ntx file which  is used to
              speed lookups into the .dat databases.The syntax for using index
              is shown below.

              index [.dat path] || [all [path]]

              For example,you can create an index file to the printer.dat file
              by typing: index D:\apps\printer.dat.
              To create index files for all database files,ie, for printer.dat
              error.dat, and help.dat, type: index all.  If the databases were
              in a directory other than the current, you might type:
              index all D:\apps.

              You need to specify the path to the .dat file if it is not in
              your current directory.


                                                     Appendix C



                                Utilities




Utility.....: prt_man
Purpose.....: Used to print this manual.
Description.: Simply type  prt_man at the DOS prompt, select your  printer and
              port,and then sit back for about three and half hours and relax.
              If you have a laser printer, it will only take about 40 minutes.
              For those of us with dot  matrix printers, it will  take between
              3  and 5 hours to  print.  You can  avoid this  by ordering the
              manual, which will be  printed using a 7 color printer.  See the
              order.frm  file for details  and prices.  First the odd numbered
              pages  will be printed  out, and  then you will have to take the
              paper out  and turn it over before reinserting it back  into the
              printer so that the even  numbered pages  can be printed  on the
              back. A minor hassle, but it saves you about 160 pages of paper.
              The prt_man utility takes two optional command line  parameters,
              [path] and [side].  The path is  where the manual is located,and
              side is which side of the manual you want printed.  If you don't
              specify the path to  the manual, prt_man will  first look for it
              in the current directory, and if not found, it will then search
              the directories listed on the DOS path. If the side parameter is
              not specified, which may be either "ODD" or "EVEN", prt_man will
              print both sides, starting with the odd numbered pages, and then
              the even.You may get a listing of the "usage" of prt_man by typ-
              ing "/?" or "/h" after prt_man at the DOS prompt ("prt_man /?").

                                                     Appendix C



                                Utilities




Utility.....: prt_stat
Purpose.....: Used to determine a printers status codes.
Description.: If you find  yourself using a printer that is not currently sup-
              ported, you can add the printer yourself. In order to do so, you
              will need to know the printers return status codes.prt_stat will
              do just that.  This is a simple utility that prompts you to turn
              the  printer off and on, and  to put  the printer  into  various
              states.  prt_stat  will then tell you what  the printer's status
              code is for  each state.  You can then enter the codes  into the
              printer.dat file in the format specified by the printer.frm file
              which is sent to you when you register.

                                                     Appendix C



                                Utilities




Utility.....: prt_test
Purpose.....: Used to test the printer.dat file after a new printer is added.
Description.: After having added a new printer and run the prt_indx utility to
              update the printer.ntx file, you may use the prt_test utility to
              test your printer. To add a printer to the database, you have to
              add the status codes and commands to the printer.dat file in the
              format specified by the printer.frm file. After having done that
              and re-indexing the printer.ntx file with prt_indx, you can test
              to see if  the commands  and status codes you  have entered  are
              correct and in the proper format. prt_test will tell you whether
              the printer supports  the commands and  if so, will print  out a
              demonstration of the command.  It will also tell  you whether or
              not The C User Interface Library is able to interpret the status
              codes you entered.  The prt_test() utility is  easy to use and a
              usefull debugging tool as well.


                                                     Appendix D



                              Error Messages

Bad memory image of FAT.  Program aborted
   This is a critical error.  The custom installed critical error handler will
   abort the program.

Bindery error in n_bindery_object_list.
   This can occur for a number of reasons, which are listed below.  There is
   nothing you can do to correct this problem.
   1. File Server out of memory
   2. Invalid object name
   3. No such object
   4. File Server Bindery locked
   5. Bindery Failure

Color attributes must be  127
   When choosing a color attribute,you must specify a number between 0 and 127.
   You have inadvertently specified a number outside this range.

Data error reading file XXXXXXXXXX (file name)
   This occurs if f_edit encounters an error while reading the file into  mem-
   ory.  If this happens the  edit\browse will be aborted.  f_edit was able to
   open the file for reading, but during the reading an error occured. This is
   an extremely rare,  almost non-existent occurrence.  You  should simply try
   to re-read the file.  If you persistently get this error message, it may be
   that your disk heads are out of alignment or are not timed correctly.

Day can not be < 1
   This error is  generated by  the default  valid function, def_val_date, for
   dates.  The day must be greater than or equal to 1.

Editing is not available in the shareware version
   The File editing capability  has been removed from the shareware version of
   the library.  When  you register with Mathware, the edit capability will be
   included.  However, the  demo  program  demonstrates how the  file  editing
   feature works.

Error in CLOCK$ device.  Program aborted
   This is a critical error.  The custom installed critical error handler will
   abort the program.

Error in NUL device.  Program aborted
   This is a critical error.  The custom installed critical error handler will
   abort the program.

Error in STDIN device.  Program aborted
   This is a critical error.  The custom installed critical error handler will
   abort the program.

Error in STDOUT device.  Program aborted
   This is a critical error.  The custom installed critical error handler will
   abort the program.

                                                     Appendix D



                              Error Messages

Error in m_scrollmenu.  Menu item NN is longer than item_len
   One of the  items list is longer than the item_len parameter you specified.
   Since m_scrollmenu() arranges the items in columns, it  pads all menu items
   to the length specified by item_len.  Thus, all items must  be less than or
   equal to the item length parameter.

File can not end with a \
   The default valid function for g_filename does not permit file names to end
   with a '\'.

File XXXXXXXXXXXX not found.
   When f_fileio is asked to open a file for reading and is unable to find it,
   this error  message  will be displayed  before prompting the  user to enter
   another file name.

Floating Point Exception: NNN (fpe_code)
   A floating point error occurred. This is the result of an invalid mathemat-
   ical computation.  When this  happens, the custom installed  floating point
   error handle will clear the error, reset the floating point package(coproc-
   essor or  floating point emulation package), and  set the global w_ERROR to
   TRUE.  The possible exceptions are listed below:

   1. Floating Point divide by 0
   2. INTO executed w/ OF Flag set
   3. Integer divide by 0
   4. Invalid Operation
   5. Loss of Precision
   6. Numeric Overflow
   7. Numeric Underflow
   8. User Program executed raised

Form feed control character in print string
   The form  feed control character, 0Ch, is not  allowed when writing to  the
   screen. Thus,both w_prtf and v_prtf will display this error message if they
   encounter one in the string to be printed.p_prtf is the only print function
   in which the form feed control character is allowed and has meaning.

Hours can not be < 1
   The default valid function for g_time and g_exttime check that the hour is
   positive.  This error will occur when the hour is less than or equal to 0.

Hours can not be > 12
   The default valid function for g_time  and g_exttime check that the hour is
   less  than or equal to 12.  This  is because the time functions use 12 hour
   intervals and use the meridian field to determine am or pm.

Hours field contains characters.  Hours must be a number
   The default valid function for g_time  and g_exttime check that the hour is
   a numeric field between 1 and 12.  If any part  of the hours field is not a
   number, this error message will be generated.

                                                     Appendix D



                              Error Messages

Insufficient memory to copy block
   When moving a blocked  section of text to  another location, f_edit  creates
   new rows to hold the blocked text and  then copies the text to the new rows.
   This error occurs  when there is insufficient memory to create the new rows.
   The two possible solutions are to move to the compact or large memory models
   or to copy the text using smaller blocks.

Insufficient memory to create file XXXXXXXX (file name)
   f_edit() requires 3000 * sizeof(char *) + 3 * vir_wth bytes to create a new
   file.  If you get this error, the only solution is too move to the large or
   compact memory model.

Insufficient memory to create menu
   Since m_menu() dynamically  allocates memory from the heap, this error will
   occur when there is not enough  memory to  create the menu structure  or if
   there is not enough memory to open a window for the menu.

Insufficient memory to display file list.
   This occurs  when there is not enough memory for m_filebox() to display  the
   list of files requested.

Insufficient memory to display object list.
   This occurs  when there is not enough memory for  n_bindery_object_list() to
   display the list of objects requested.

Insufficient memory to display printers
   w_setup  gets a list of supported printers from the printer.dat database. It
   then allocates 26  bytes for each printer name that it finds and  copies the
   printer  names into the array it has  created.  This error  will occur  when
   there are  too many printers  but not  enough memory to create  the array to
   display them. Again, you're only possible solution  would be to move  to the
   compact or large memory model if you are not already doing so.

Insufficient memory to insert a new line
   When there is no more memory left, f_edit is unable to create a new line.

Insufficient memory to load file XXXXXXXX (file name)
   f_edit will display this message when one of two condition occurs.  The 1st
   happens if the  file to be  edited\browsed is  more than the  default  3000
   lines long.  This may be changed by changing the "#define MAX_LINES" state-
   ment in  w_file.h.  The 2nd  place where  this may occur is if although the
   file contains less than 3000 lines, there is  not enough memory to load the
   entire file into memory all at once.f_edit allocates vir_wth bytes for each
   line in the file along with 3000 lines * sizeof(char *) bytes  for pointers
   to the lines of text.  Although the 3000 pointers  is needed (so to speak),
   the only way for the programmer to use less memory for the file is to use a
   smaller virtual width.

Insufficient memory to load help.
   This  error will occur after the Help key (F1 by default) has been pressed,
   and the context sensitive help text is too large to fit into memory.

                                                     Appendix D



                              Error Messages

Insufficient memory to load printer commands.  Program aborted
   w_init reads in the current printer model and port from setup.dat. Then, it
   tries to read in the commands and status codes  for that printer model.  It
   first has to reserve memory, about 750 bytes, for the commands. If there is
   not enough memory to do this, you will get this error.

Insufficient memory to load program
   w_init allocates memory for various globals.  If it is unable to do so, you
   will get this message.

Insufficient memory to move block
   This error will almost never occur.f_edit requires num_lines*sizeof(char *)
   bytes to move text around.  Thus, if you are moving  20 lines in  the small
   memory model,f_edit needs 40 extra bytes of memory to do the move. However,
   if is physically possible that there isn't 40 bytes left.

Insufficient memory to open window
   When a window is opened, it  has to reserve  memory for it's  structure and
   also to save the screen underneath it,  so that it may be restored later by
   w_close().  If there is not  enough memory on the heap, then  you will  get
   error message.  The only  possible solution is to move to  the large memory
   model if you are using the small or medium models.

Insufficient memory to save screen area.
   v_savescreen reserves memory for the area to be saved.  If it is  unable to
   do  this, you  will get  this  message.  Note  that v_savescreen() requires
   2*height*length bytes in order to save the screen area.

Invalid color parameter in call to p_color().
   The C User Interface Library supports 8 printing colors which are listed in
   w_printr.h. If the printing color parameter passed to p_color is not one of
   those listed, this error will occur.

Invalid command parameter in call to p_command_exec().
   p_command_exec is an internal  function  called by other print functions to
   execute a  "fancy" print  command.  Currently, the C User Interface Library
   supports about 50 commands.  If the command passed to p_command_exec is not
   one of these 50 or so recognized commands, this error will occur.

Invalid date passed to d_julian
   If the date  passed to d_julian is not a valid date, then you will get this
   error.

Invalid date passed to d_ofweek
   If the date  passed to d_ofweek is not a valid date, then you will get this
   error.

Invalid drive specified.  Drive X is the last available drive.
   Your system has only X logical drives.  You  are trying to use a drive that
   is not present on your system.

                                                     Appendix D



                              Error Messages

Invalid file mode parameter, X, in call to f_fileio.
   f_fileio may open a file  for 'r'eading or 'w'riting.  Any  other parameter
   causes this error.

Invalid file name
   This is a  general type  of error that is generated  by the  default  valid
   function for g_filename whenever the file name entered by the user does not
   follow the DOS file naming conventions.

Invalid file translation mode, X, in call to f_fileio\f_copy.
   f_fileio\f_copy may open a file using 'b'inary (none) or 't'ranslation('\n'
   ->LF CR) translation.  Any other translation causes this error.

Invalid font parameter in call to p_font().
   Whenever p_font encounters a font not supported, this error occurs.  A list
   of valid fonts are listed in w_printr.h.

Invalid get type specified NNN.  Get not set. (gettype)
   When setting  gets, you must use  one of the currently supported get types.
   These are listed in w_get.h. If you specify an invalid GET type, this error
   will occur.

Invalid get type in g_XXXXXXXX. (function name)
   This is an  internal  error.  Call  Mathware if  you ever  see this  error.

Invalid get type in XXXXXXXXXX. (function)
   Currently, the  C User  Interface library has 21  types of gets, which  are
   listed in w_get.h.  Since  the w_get  variable is global, it is possible to
   modify the get field.  There is  no valid  or logical reason to do this but
   it is physically possible.  If the get  type is  not one of the 21 types on
   the list, you will  get  this message.  The solution is  obvious,  Don't go
   modifying this field.

Invalid height parameter in call to p_height().
   p_height supports 3 character heights which are listed in w_printer.h. When
   an invalid height is encountered, this error occurs.

Invalid key parameter in call to k_set
   Only function  keys may have a  function assigned to it.  You will get this
   error if you specify any key other than a function key.

Invalid num_char parameter in call to s_strsub
   s_strsub can only  handle sub strings with  character lengths less  than or
   equal to  255 characters.  If you  specify a sub-string length greater than
   255, this error will occur.

Invalid number of rows specified.  Rows not set
   w_setup allows the user to change the number of rows on the  screen to  one
   of four values.  If you try to set the number of rows to a value other than
   those four, this error will occur.

                                                     Appendix D



                              Error Messages

Invalid on\off parameter in call to p_style().
   The p_style commands takes two parameters. The 1st is the new style that is
   desired, and the 2nd is whether the user wants to turn the style off or on.
   These are the only 2 possibilities and are  defined in w_printer.h.  If any
   other value is specified, this error will occur.

Invalid parameter in call to d_add
   The 1st date parameter passed to d_add must be a valid date.  The 2nd  date
   parameter does  not have to  satisfy this  requirement.  Also, if  the date
   pointer passed as the 3rd parameter is 0,this error message will also occur

Invalid parameter in call to d_sub
   The 1st date parameter passed to d_sub must be a valid date.  The 2nd  date
   parameter does  not have to  satisfy this  requirement.  Also, if  the date
   pointer passed as the 3rd parameter is 0,this error message will also occur

Invalid quality parameter in call to p_quality().
   The only two valid print qualities  are draft and letter.  Any other values
   will cause p_quality to generate this message.

Invalid set parameter in p_char_set().
   The C User Interface  Library supports 8 character sets which are listed in
   w_printr.h.  If the character set parameter passed to p_char_set is not one
   of those listed, this error will occur.

Invalid style parameter in call to p_style().
   The valid styles currently supported are listed in w_printer.h.  If  an in-
   valid print style is  specified, p_style will cause this message to be dis-
   played.

Invalid width parameter in call to p_height().
   Although p_height is used to set the height of the characters, it also sets
   the characters width at the same time.  There are only two valid widths and
   are listed  in w_printer.h.  If the  width is invalid, this message will be
   displayed.

I\O error: XX.  (status code)
   The printer I\O error message is a catch all when the C User Interface does
   not recognize the return code from the printer.  Since each printer returns
   different codes for the same condition,these codes are stored in the print-
   er.dat database. However, if the printer returns a status code which is dif
   ferent from those stored in the database, the C User Interface Library does
   not know how to process this code  and therefore issues  this general error
   message.

M_close trying to close an unopened menu
   This error happens when you try to close a menu that is already closed or a
   menu that has not yet been opened.  This often occurs when you try to close
   a menu that you set to close upon the user's selection.

                                                     Appendix D



                              Error Messages

M_scrlbox called with invalid number of columns\items parameter
   If the number of rows, number of columns, item length,or number of items is
   less than zero,m_scrollbx, the internal function used by all scrolling menu
   functions, generates this error.

M_scrlbox is unable to fit the menu on the screen
  This happens when you specify a number of columns and item width that causes
  the menu to become to wide or the menu has too many rows and the menu is too
  big to fit onto the screen.

Max_char parameter must be  1.  Get not added
   All gets must have a length of at least 1 character.

Meridian must be am or pm
   The default valid function for g_time and g_exttime check that the meridian
   field is either am or pm,since it uses two twelve hour intervals to repres-
   ent a period of 1 day.

Minutes can not be > 59
   The default valid  function for g_time and g_exttime check that the minutes
   field is less than or equal to 59.  If not, this error will occur.

Minutes field contains characters.  Minutes must be a number
   The default valid  function for g_time and g_exttime check that the minutes
   field is contains only numeric characters.  If not, this  error will occur.

Month can not be < 1
   This  error is  generated by the default  valid function, def_val_date, for
   dates.  The month must be greater than or equal to 1.

Month can not be > 12
   This  error is  generated by the default  valid function, def_val_date, for
   dates.  The month must be less than or equal to 12.

Negative year passed to d_leapyear
   The d_leapyear function can only handle non-negative years, ie (AD).  Thus,
   all B.C. years are invalid.

Nested reads are not currently supported
   Currently, the C  User Interface  library does not  support  the setting of
   nested reads. This occurs when while  executing a call to g_read, the prog-
   rammer sets other gets, and then executes  another g_read. You may set more
   gets during a g_read, but  you may not  make another call to g_read.  As an
   example, if while  you are in a  valid function (and hence inside a call to
   g_read) you  set a get.  This is valid. The get will simply be added to the
   end of the list of  currently active gets.  What  is not allowed is to then
   call g_read to read the new gets you have just set.  This  may be corrected
   in a future version.

                                                     Appendix D



                              Error Messages

No matching files were found
   If m_filebox is unable to locate any matching files of the  type  specified
   in the specified directory, you will get this message.

No parallel ports have been detected.  Printer options are not available
   The C User  Interface Library only supports parallel printers.  Thus, if no
   parallel ports  are detected  and the user is  trying to  select a  printer
   option, this error message will be displayed.

Number of allowable rows exceeded
   f_edit is compiled to handle  a maximum number of lines per file.  Whenever
   a file has  more than this number, 3000,  this error message will occur and
   the file will not be loaded.

Object list excedes 256 object maximum.
   n_bindery_object_list() reserves  memory for a maximum of  256 objects, re-
   gardless of the object type  being requested.  There is nothing  you can do
   about this error.  Call Mathware if you receive this error.

Power to printer LPTX is off. Press ESC to quit, any other key to retry.
   This message can be generated by  any print function that sends data to the
   printer.  Each print function tests the printer status prior to sending any
   data. If the printer is not turned on, you turn the printer on and bring it
   on line to clear error, or press ESC to stop retrying.

Printer error in p_prtf()
   p_prtf has to send a character string 1 character at a time to the printer.
   If the printer is unable to accept any one of the characters,this will come
   up.This means that the printer has lost one of the characters in the string
   Then, p_prtf() will continue on with the rest of the string.

Printer paused.  Press any key to continue.
   This is the message generated by p_pause(), which is used to allow the user
   to pause and abort a  Print Job.  FALSE is returned if the user pressed ESC
   and wants to abort the Print job.  It is up to  your program to fulfill the
   user's request.

Printer LPTX is off line. Press ESC to quit, any other key to retry.
   This message can be generated by  any print function that sends data to the
   printer.  Each print function tests the printer status prior to sending any
   data.  If the printer is  off line, you must add paper bring the printer on
   line to clear the error, or press ESC to stop retrying.

Printer LPTX is out of paper. Press ESC to quit, any other key to retry.
   This message can be generated by  any print function that sends data to the
   printer.  Each print function tests the printer status prior to sending any
   data.  If  the printer is  out of paper, you  must add paper and  clear the
   error, or press ESC to stop retrying.

                                                     Appendix D



                              Error Messages

Printer XXXXXXXXXX on port LPTN unable to except XXXXXXX command.
   This error occurs when the printer fails to accept a  command.  The command
   itself is a valid printer command, but for some  reason the printer was un-
   able to process it.

Printer XXXXXXXXXX not found in printer.dat database.
   The most common cause of this error is  a user adding a new printer to  the
   database and forgetting to run the prt_indx utility to update  the printer.
   ntx file.  Thus, when the user chooses the newly added printer, w_setup can
   not locate the printer because of the outdated index file.

Seconds can not be > 59
   The default  valid for  g_time and g_exttime  checks to make sure  that the
   seconds field is less than  or equal to 59 and generates this error when it
   is not.

Seconds field contains characters.  Seconds must be a number
   The seconds field is checked by the default time valid function to make sure
   that the seconds field is composed entirely of numerics.  If it is not, this
   error will occur.

Setup not saved. Unable to open XXXXXXXXX (path to setup.dat)
   After the user has made a change using w_setup, the changes are immediately
   saved in the file setup.dat.  w_init finds the full path  to this file, but
   when w_setup is unable to open the file for writing, this error occurs. The
   cause is usually insufficient access rights.

The Phone number must  be completely  filled in.  The  area code  is  optional
   Although  the default valid for the phone get allows  the area code to  be
   left blank, the exchange(1st 3 digits) and last 4 digits must be completely
   filled in.  Otherwise you will receive this error  message.
The Social Security number must be completely filled in
   The default valid for the social security get checks that all eleven digits
   have been entered and generates this error message if any are missing.

The Zip Code must have 5 numbers
   When using the 5 digit old zip code style get, the entire zip  code must be
   filled in.  This error is generated by  the default  valid for the standard
   zip code get.

The Zip Code must have the 1st  5 numbers filled in.  The 2nd part is optional
   This error message is  generated by the default valid function used for the
   g_extzip gets.  The default  valid requires  that a user completely fill in
   the standard portion (the 1st 5 digits) of the  zip code, but the 2nd half,
   (the 4 digits after the hyphen "-") remains optional.

                                                     Appendix D



                              Error Messages

There are only NN days in XXXXXXXX,XXXX
   This  error is  generated by the default  valid function, def_val_date, for
   dates. The day must  be less than or equal to the total number of days in a
   given month.  For  example, April has  only 30 days.  If you try to use the
   date April 31st, you will get  this error message.  If  the error occurs in
   the month of  February, the year  will also  be  displayed since the  total
   number of days in February is sensitive to the year.

Unable to allocate memory for GET in g_get.  Get not set
   When  setting a get, an internal function, g_set, is called to allocate the
   necessary  memory  and perform  initialization  for the get.  If  there  is
   insufficient memory to set the get, g_set will generate this error message.

Unable to create XXXXXXXX (file_name)
   This error occurs when f_edit can not create a new file to be edited.  This
   can occur if  the user does not have  sufficient rights to create the file,
   such as write or create rights.

Unable to display printer list.
   When choosing  a printer using  w_setup(), if w_setup() is  unable to  open
   printer.ntx to get a listing of supported printers, this error occurs.

Unable to install Floating Point Exception Handler
   w_init installs a custom floating point exception. If for some reason it is
   unable to do this, you will get this error.

Unable to load printer commands from printer.dat.
   This error will  occur when the user  uses w_setup to choose a new  printer
   model.  After  choosing  the model, w_setup  tries to read  in the commands
   specific to the selected printer from the printer.dat file. If it is unable
   to open the file, this error message is generated.

Unable to locate XXXXXXXXXXX   (file_name)
   This error  is generated by  f_edit  whenever a  file is to  be browsed but
   f_edit can not find it.  This happens only in browse mode. In edit mode, if
   f_edit  can not find the file, a new one is created. In browse mode, f_edit
   searches for the file in the current directory if no path is specified, and
   then continues the search along the DOS path until it is found. If it can't
   find the file, f_edit quits and displays this error message.

Unable to locate XXXXXXXXXXXX. Please check DOS path. Program aborted.
   w_init tries to find files that the Library needs.  If it is unable to find
   any of these files, you will get this message with the name of the particu-
   lar file that it was unable to find.  The necessary files are listed below:

   1. help.dat
   2. help.ntx
   3. printer.dat
   4. printer.ntx
   5. setup.dat

                                                     Appendix D



                              Error Messages

Unable to open XXXXXXXXXXXX (file_name)
   This error is caused by f_edit not being able to open a file for editing or
   browsing after having found it.  This is due to insufficient access rights,
   or someone else having a lock on the file.

Unable to open XXXXXXXXXXXX for writing.
   When f_fileio() is asked to open a file for writing and it can not open the
   file, this message will be displayed.

Unable to open XXXXXXXXXXXX.  Please check DOS Path.
   This is generated by w_init() if it is unable to open one of the five files
   that the library  needs.  w_init  was able to find  the file, but  the user
   does not have sufficient access rights to open the file.

Unable to open Help.dat file.  Help unavailable.
   This occurs after the  Help key(F1 by default) is pressed. w_help must open
   help.dat to retrieve the context sensitive help text that is being request-
   ed.  If it is unable to do  so, you will get this error message. Again, the
   causes for this are mostly Network related. Possible  causes are that some-
   one has deleted the file, has a file  lock on it, or you no longer have the
   necessary rights to open the file.

Unable to open source\destination file XXXXXXXXXXXX
   If f_copy is unable to open the source file for reading or the  destination
   file for writing, this error occurs.

Unable to save changes to XXXXXXXXXX (file_name).  File not updated.
   This error will occur  whenever f_edit() is not able to reopen the file for
   writing.  f_edit first open the file for reading in the  translated mode in
   order to read the file into memory. The file is then closed and all editing
   is done on the copy in memory.  If the user wishes to save the changes, the
   file is reopened for writing in translated mode.  It is at this  point that
   this error will occur. This occurs if the user has read rights for the file
   but not write or update rights.

W_close trying to close an unopened window
   This message can occur for two reasons.  Either you have not yet opened the
   window  you are trying to close or  you have already  closed the window and
   are trying to close it again.

W_prtf trying to write to an unopened window
   You may not write to a window  that has not been opened or to a window that
   has already been closed.

Window Error: Title without border
   w_open will  display this message when a window is being opened  that has a
   title but does not have a border.  Titles may be  displayed only on windows
   that have borders.

                                                     Appendix D



                              Error Messages

You did not enter a file name
   When reading  a filename set by g_filename, the default valid doe  not allow
   the user to enter a blank file name.  This error message occurs whenever the
   user does not enter anything.

You may not set colors on a monochrome monitor
   If you have a monochrome monitor, then w_setup does not allow you to change
   the colors.

You may not use drive B on single floppy drive systems
   For user's of  single drive systems, DOS  controls which  logical drive the
   floppy  is currently set to.  When you use the  other logical floppy drive,
   DOS corrupts the screen by displaying a "place diskette in drive X" message
   For this reason,the C User Interface Library does not let you specify drive
   B on single drive systems.

You must enter 'T'rue or 'F'alse
   The default valid for a True\False get takes the entered character,converts
   it to upper case, and then checks if it is a 'T' or 'F'.  If it is not, you
   will receive this message.

You must enter 'Y'es or 'N'o
   The default valid for a Yes\No get takes the entered character, converts it
   to upper case, and then checks if it is a 'Y' or 'N'. If it is not,you will
   receive this message.

You should be using your own password valid function instead of the default.
   When getting a password,you should be using your own valid function to look
   up the user on a database to see if access is permitted. The default simply
   returns TRUE and displays this warning message.

                                                     Appendix E


















                              ERROR HANDLERS






                              k_INT_09

                              w_fpe_handler

                              matherr

                              w_crit_err_handler

                                                     Appendix E



                              Error Handlers

Function....: k_INT_09.
Purpose.....: Ignore Ctrl-C\Break.
Description.: Control C\Break use Interrupt 23h. The default ISR for interrupt
              23h simply aborts the current process. It is very easy indeed to
              replace the default Int 23h ISR with a routine that does nothing
              and simply returns.  Although this would keep your programs from
              being aborted, DOS prints a "C" on  your screen to let  you know
              that a Control-C\Break has been pressed. This "C" is printed and
              the screen is down scrolled one line,before the Int 23h ISR gets
              executed. Thus, no matter how great you ISR 23h is,you still get
              that annoying "C".In order to prevent the screen from being cor-
              rupted, it is necessary to replace the ISR for Int 09h, the key-
              board hardware ISR.This prevents the screen from being corrupted
              but it introduces another problem.  The default ISR  for Int 23h
              is  automatically restored  when your program ends.  This is not
              the case with Int 09h. If your program terminates normally, with
              a  call to w_exit(), then the default ISR  09h is  restored  and
              everything is OK. No problem. But what happens when your program
              terminates abnormally? Then,w_exit does not restore the ISR 09h,
              and  since your  program is no  longer in memory, the  Interrupt
              vector  table still  has the ISR 09h address  as pointing to our
              custom ISR 09h which is no longer  there. So what happens?  Your
              system hangs and you have to reboot.  Sorry!

                                                     Appendix E



                              Error Handlers

Function....: w_fpe_handler.
Purpose.....: Process floating point exceptions.
Description.: Floating Point Exceptions (FPE's) are general arithmetic errors,
              which include the following:

              1. Integer division by 0
              2. 80x87 invalid operation (invalid 80x87 op code)
              3. Floating point division by 0
              4. Underflow (number is too small to be represented)
              5. Overflow  (number is too large to be represented)
              6. Loss of precision
              7. 80x87 Stack overflow

              The default FPE handler prints out a message about the error and
              then aborts your program.  The C User Interface Library provides
              a much better handler. The error is displayed in a window at the
              bottom of the screen, and the error is cleared. Also, the global
              variable w_ERROR  is set to TRUE.  Your  program  needs to reset
              this variable  to FALSE.

              Note: Only the Borland compilers link this handler correctly. It
                    is therefore unavailable for all other compilers.

                                                     Appendix E



                              Error Handlers

Function....: matherr
Purpose.....: Process Math exceptions.
Description.: Math  exceptions are a bit different from FPE's.  The standard C
              library contains a collection  of mathematical functions.  A few
              examples are sin(), exp(), sqrt(), etc.  Each of these functions
              has  a specific  domain (range  of valid values) for  which  the
              function is defined.  For  example, the sqrt() function can only
              handle values  0.  If  you try  to take  the square  root of  a
              negative number, you will get a math exception.  Another example
              would be trying to find the  natural log (ln) of 0.  So, as  you
              see, math exceptions occur when a number outside of a function's
              domain is attempted.  These math exceptions differ from FPE's in
              that an FPE is a general exception, such as dividing by 0, while
              a math exception is the direct result of calling one of the math
              functions from the standard C library with  an invalid argument.
              In either case, the global w_ERROR  is set to TRUE.  The default
              math  handler, like the FPE handler, prints a message and aborts
              your program.  The C User Interface Library math  handler simply
              displays a message in a window  at the bottom of the screen  and
              clears the error.
                                                     Appendix E



                              Error Handlers

Function....: w_crit_err_handler.
Purpose.....: Process all DOS critical errors.
Description.: Who amoung has not  seen the now  infamous  "Abort, Fail, Retry"
              message.  This is the  default critical error handler in action.
              The  critical  error  handler, ISR 24h, handles all  serious DOS
              errors, which, to name a  few, include open  drive  doors, write
              protected disks, Sector not found, Device errors, etc.The C User
              Interface Library ISR  24h was  mainly  designed to  handle  the
              floppy  drive related errors, since  these  are by far  the most
              common. The action taken by the default ISR 24h varies depending
              on which  error occurred.  We'll  only discuss the  floppy drive
              errors in detail. All other types of critical errors will simply
              cause  the program to be  aborted, as would the default critical
              error handler.  When a floppy  drive error  occurs, a message is
              displayed in a window at the bottom of the screen describing the
              error and how to  fix it.  For  example, "Disk  in drive "X"  is
              write protected. Check  disk and  press Enter to retry"  will be
              displayed  when a  write-disk error  occurs.  Then, the  C  User
              Interface Library ISR 24h waits for you to take corrective action
              at  which time  it will try  again.  It will keep repeating this
              process of asking you to fix the problem and retrying  until one
              of  two things happen.  Either  you fix the problem or you press
              ESC.  If  you press ESC, the  global variable  w_ERROR is set to
              TRUE. It is up to you to reset this variable. All other critical
              errors abort the program with an exit code of 1.
