7524 CFR Sample Library of Useful Functions
-------------------------------------------


Table of Contents
-----------------
  Introduction
  Function Reference
  Binary Validation
  format_date
  format_time
  get_seconds
  GetRecord
  GetValRecord
  GetValRecordFast
  pop_up_wnd
  read_auto
  sprintf_752x / sprintf_752xf


Introduction
------------
This library of sample Custom Function Routine functions provides various
useful, pre-written routines which help to speed development of CFRs for the
7524 Data Collection Terminal.  This same code can be used to build CFRs
that will run on any terminal that is supported by the DCConnect Client
(formerly 752x Emulator for DOS).

Four versions of the utility library are provided:
- A DOS version for use with the IBM C/2 1.10 compiler in order to build CFRs
  to be used on 7524 terminals with 7524 ETS flash or to be used on terminals
  running one of the DOS versions of the DCConnect Client.
- A DOS version for use with the Borland Turbo C++ 3.0 for DOS compiler in
  order to build CFRs to be used on 7524 terminals with 7524 ETS flash or to be
  used on terminals running one of the DOS versions of the DCConnect Client.
- A 32-bit Windows version for use with the Microsoft Visual C++ compiler in
  order to build CFRs for devices that are running the 32-bit Windows version
  of the DCConnect Client.
- A Windows CE version for use with the Microsoft Visual C++ compiler in
  order to build CFRs for Intermec 5020 terminals that are running the
  Windows CE version of the DCConnect Client.

For actual 7524 terminals, the 7524 must be running the "7524 Extended Terminal
Services" flash in order for the CFR to be used.  Other terminals must be
running the DCConnect Client.

The program product Data Collection Control/2 or "Data Collection Connection"
used in conjuncton with "7524 Interface Support" are offered to facilitate
configuring and loading of the 7524 with the CFR, and then to control the data
collection terminals.  (7524 Interface Support is only needed if you are
actually using 7524 terminals on an RF network that is attached to the
data collection server via the serial port).

For simplicity, the remainder of this document will use 7524 to refer to the
terminal.



Utility functions included are:

o Routines to extract data from validation files by finding a specific record
  offset or a numbered record

o A binary validation file search routine which greatly speeds the checking of
  a record in a validation file of fixed length, sorted records.

o A version of sprintf which is written specifically for use on the data
  collection terminal

o Format the time and date into strings

o Get the current time, represented as seconds since January 1, 1900 at
  mid-night.

o Control input from sensor ports and/or keypad, forcing numeric input to valid
  forms, handling scanner errors, and allowing cursor control within the input
  field.

Source code is available for educational purposes, for creation of derivative
functions, and for fixing of any defects which may exist in the code.



Binary Validation
-----------------
This function performs a validation of the presence or absence of a match
between a string and the records of a validation file, using a binary searching
method.  The binary search can yield a much faster search time when the
validation file has many records.

Records must be of fixed length, and must be sorted into ascending order.  An
example of a properly formated validation file is:

  123456789
  222222222
  987654321

If the file is not found on the terminal, the function will return
FILE_NOT_FOUND.  Otherwise, it will return VAL_PASSED or VAL_FAILED, depending
on the seach type which was requested and the results of the search.


     #include   "cfrutl24.h"    // Defined values for 7524 CFRs

     int BinaryValidation(char * ValFilename, char type, char * data)

     char * ValFilename         // The validation file name

     char type                  // The validation type desired, either
                                // INCL_SKIP_IF_FAIL or
                                // EXCL_SKIP_IF_FAIL.

     char * data                // The string to compare against.






#include "cfrutl24.h"
#include "cfrapi24.h"


int far main (int funct,char far *params)
{
 USHORT xfrcnt;                   // Vio transfer count
 char filename[13];
 char badge_read[40];

   .
   .
   .
 strcpy(filename, "BADGES.VAL");

 type = INCL_SKIP_IF_FAIL;

  // get data passed from transaction program
 ReadUserVariable(0, badge_read);

   // Try to do binary validation.  If file is
   // not found, resort to trying the regular
   // Validation routine, which will try to
   // do a host-based validation.
 rc = BinaryValidation(filename, type, badge_read);

 if (rc == FILE_NOT_FOUND)
 {
    // try regular support
    // (returns E_OK or E_DATA_NOT_FOUND,
    // which in the case of inclusive validation
    // are the same as VAL_PASSED and VAL_FAILED
    // as returned by the BinaryValidation routine.
   rc = Validation(filename, badge_read);
 } /* endif */

  // handle results...
 switch(rc)
 {
   case VAL_PASSED:
   case E_OK:
     // more...
    break;
   case VAL_FAILED:
   case E_DATA_NOT_FOUND:
     // more...
    break;
   case REMOTE_VAL_FAILED:
     // more...
    break;
   case FILE_NOT_FOUND:
     // more...
    break;
 }

   .
   .
   .
}


format_date
-----------
This function reads the current date from the DCT's real-time clock and formats
the data into strings which are ready for presentation or printing.  You can
specify AMERican or EUROpean format and the character you want as the
months-days-years delimiters.

You must provide the addresses of two data areas:

 1.  A buffer of at least 9 characters in length for the time string with
     delimiters between the date elements

 2.  A buffer of at least 7 characters in length for a compact string with no
     element delimiters






     #include   "cfrutl24.h"           // Defined values for 7524 CFRs
     #include   "cfrapi24.h"

     void format_date(formatted_date, no_delim_date, form, date_delimiter)

     char * formatted_date // A pointer to a results work area which your
                           // program must provide for the formatted date with
                           // delimiters in place -- minimum size 12 bytes

     char * no_delim_date  // A pointer to a results work area which your
                           // program must provide for the formatted date with
                           // no delimiters used -- minimum size 9 bytes

     char form             // The form of the date string; defines are
                           // EURO (DD.MM.YY) or AMER (MM/DD/YY)

     char date_delimiter   // The character you want used between date elements






#include "cfrutl24.h"
#include "cfrapi24.h"


int far main (int funct,char far *params)
{

  char date_str[9], short_date[7];  // data return areas


   .
   .
   .

  // get the current date for printing
 format_date(date_str, short_date, EURO, '.');

   .
   .
   .
}


format_time
-----------
This function reads the current time from the DCT's real-time clock and formats
the data into strings which are ready for presentation or printing.  You can
specify 12 or 24-hour time and the character you want as the
hours-minutes-seconds delimiters.

You must provide the addresses of two data areas:

 1.  A buffer of at least 12 characters in length for the time string with
     delimiters between the time elements

 2.  A buffer of at least 9 characters in length for a compact string with no
     element delimiters






     #include   "cfrutl24.h"           // Defined values for 7524 CFRs
     #include   "cfrapi24.h"

     void format_time(formatted_time, no_delim_time, form, time_delimiter)

     char * formatted_time // A pointer to a results work area which your
                           // program must provide for the formatted time with
                           // delimiters in place -- minimum size 12 bytes

     char * no_delim_time  // A pointer to a results work area which your
                           // program must provide for the formatted time with
                           // no delimiters used -- minimum size 9 bytes

     int form              // The form of the time string; defines are
                           // HHMMSS_24 and HHMMSS_12

     char time_delimiter   // The character you want used between time elements






#include "cfrutl24.h"
#include "cfrapi24.h"


int far main (int funct,char far *params)
{

  char time_str[12], short_time[9];  // data return areas


   .
   .
   .

  // get the current time for printing
 format_time(time_str, short_time, HHMMSS_24, ':');

   .
   .
   .
}


get_seconds
-----------
This function reads the current time and date from the DCT's real-time clock
and converts it to an unsigned long integer representing the number of seconds
which have elapsed since Janary 1, 1900 at midnight.  This is useful for
determining a point in time at which an event started or the current point in
time for comparison to a starting time so that elapsed time can be calculated
(i.e.  for time-outs, durations, etc.).






     #include   "cfrutl24.h"           // Defined values for 7524 CFRs
     #include   "cfrapi24.h"

     unsigned long get_seconds(void)






#include "cfrutl24.h"
#include "cfrapi24.h"


int far main (int funct,char far *params)
{

  unsigned long start_time;


   .
   .
   .

  // get the starting time of the procedure
 start_time = get_seconds();

  // perform some function (e.g. watch for keypad data,
  // just sit and do nothing, show a message) for
  // 5 seconds
 do
 {
    // do something
   .
   .
   .
 }
 while( get_seconds() - start_time <= 5 );

   .
   .
   .
}


GetRecord
---------
This function returns a pointer to any numbered record within an on-board
terminal validation file.  The pointer is to the beginning of the record number
prefix text.

Records may be fixed or variable length.  The record number is a zero-padded,
ascending prefix at the beginning of each record.  Each record is ended by a
NULL character.  The record prefix may be from 1 to 5 characters in length.
The records must be sorted into ascending order, but need not be consequtive.
An example of a properly formated validation file is:

  00001 This is record 1
  00100 This is record 100
  11000 This is record 11000

Because the records are sorted, this function can perform a binary search for
the desired record, resulting in very fast access to any record in a large
file.

If the record cannot be found in the file, or the file cannot be found, a NULL
is returned for the pointer.






     #include   "cfrutl24.h"                // Defined values for 7524 ETS

     char * GetRecord(val_file_name, record_number, digits)

     char *        val_file_name            // Validation file name

     unsigned int  record_number            // Desired record number

     UCHAR         digits                   // Number of digits in zero-padded
                                            // prefix string.





#include "cfrutl24.h"
#include "cfrapi24.h"

#define PREFIX    5          // 5 digit prefixes used here
#define MAX_WIDTH 80

int far main (int funct,char far *params)
{
 USHORT xfrcnt;                   // Vio transfer count
 char filename[13];
 char * help_ptr;
 unsigned int help_rec;
                                  // character.
 char temp[MAX_WIDTH+1];

   .
   .
   .
 strcpy(filename, "HELP.VAL");

 help_rec = 155;  // Get record prefixed with 00155

  // get line from val file and show the part after the
  // record prefix.
 help_ptr = GetRecord(filename, help_rec, PREFIX);

 if ( help_ptr == NULL )
       {
         char temp[35];
         strcpy(temp,"Could not find record #");
         itoa((int)msg_start + ctr, &temp[24], 10);
         VioWrtCharStr(temp, strlen(temp), 0,0, &xfrcnt, 0);
       }

   // Make a null-terminated string of the record's data
   // handle 'blank lines' in HELP.VAL which have no
   // characters but the terminator after the prefix.
 if(help_ptr[PREFIX] != NULL)
  {
   strncpy(temp,&help_ptr[PREFIX+1], MAX_WIDTH );
  }
  else
  {
   strcpy(temp," ");
  }

 VioWrtCharStr(temp, strlen(temp), 0, 0,
                                  &xfrcnt, NO_CURSOR_MOVE);
   .
   .
   .
}


GetValRecord
------------
This function returns a pointer to any absolute record within an on-board
terminal validation file.  The function works by starting at the beginning of
the file and counting records until it find the one requested.  The first
record in the file is considered absolute record zero.

Records may be fixed or variable length.  Each record is ended by a NULL
character.  An example of a properly formated validation file is:

  This is record 0
  This is record 1
  This is record 2

If the record cannot be found in the file, or the file cannot be found, a NULL
is returned for the pointer.






     #include   "cfrutl24.h"                // Defined values for 7524 ETS

     char * GetValRecord(val_file_name, record_number)

     char *        val_file_name            // Validation file name

     unsigned int  record_number            // Desired record number






#include "cfrutl24.h"
#include "cfrapi24.h"

#define MAX_WIDTH 80

int far main (int funct,char far *params)
{
 USHORT xfrcnt;                   // Vio transfer count
 char filename[13];
 char * help_ptr;
 unsigned int help_rec;
                                  // character.
 char temp[MAX_WIDTH+1];

   .
   .
   .
 strcpy(filename, "HELP.VAL");

 help_rec = 155;  // Get record 155 (the 156th record
                  // from the beginning of the file

  // get line from val file and show the part after the
  // record prefix.
 help_ptr = GetValRecord(filename, help_rec);

 if ( help_ptr == NULL )
       {
         char temp[35];
         strcpy(temp,"Could not find record #");
         itoa((int)msg_start + ctr, &temp[24], 10);
         VioWrtCharStr(temp, strlen(temp), 0,0, &xfrcnt, 0);
       }


 VioWrtCharStr(help_ptr, strlen(help_ptr), 0, 0,
                                  &xfrcnt, NO_CURSOR_MOVE);
   .
   .
   .
}


GetValRecordFast
----------------
This function returns a pointer to any absolute record within an on-board
terminal validation file.  The function works by starting at the beginning of
the file and counting records until it find the one requested.  The first
record in the file is considered absolute record zero.

The function learns the location of each offset of 100 records on the first
invocation of the function which searches to or past those locations.  On
subsequent invocations, it already knows a short-cut to within 100 records of
the final record.  This can save substantial time (as much as 1-2 seconds on
large files) after the function gets warmed up.  The validation file must be
limited to under 1,099 records.

The list of learned locations is only valid for the last file name used in the
call.  If the next invocation requests another file name, the search must be
done without benefit of learned locations.  Thus, if you alternate very
frequently between files searched, the Fast function may be of little value.

A side effect of the function is that the first character of the first record
is changed to a '%' character.  This serves as a flag to the function that the
validation file has not been reloaded since it learned the locations of the
100-record offsets.

Records may be fixed or variable length.  Each record is ended by a NULL
character.  An example of a properly formated validation file is:

  This is record 0
  This is record 1
  This is record 2

If the record cannot be found in the file, or the file cannot be found, a NULL
is returned for the pointer.






     #include   "cfrutl24.h"                // Defined values for 7524 ETS

     char * GetValRecordFast(val_file_name, record_number)

     char *        val_file_name            // Validation file name

     unsigned int  record_number            // Desired record number






#include "cfrutl24.h"
#include "cfrapi24.h"

#define MAX_WIDTH 80

int far main (int funct,char far *params)
{
 USHORT xfrcnt;                   // Vio transfer count
 char filename[13];
 char * help_ptr;
 unsigned int help_rec;
                                  // character.
 char temp[MAX_WIDTH+1];

   .
   .
   .
 strcpy(filename, "HELP.VAL");

 help_rec = 155;  // Get record 155 (the 156th record
                  // from the beginning of the file

  // get line from val file and show the part after the
  // record prefix.
 help_ptr = GetValRecordFast(filename, help_rec);

 if ( help_ptr == NULL )
       {
         char temp[35];
         strcpy(temp,"Could not find record #");
         itoa((int)msg_start + ctr, &temp[24], 10);
         VioWrtCharStr(temp, strlen(temp), 0,0, &xfrcnt, 0);
       }


 VioWrtCharStr(help_ptr, strlen(help_ptr), 0, 0,
                                  &xfrcnt, NO_CURSOR_MOVE);
   .
   .
   .
}


pop_up_wnd
----------
This function prepares a blank pop-up window on the display screen according to
the size and highlighting attribute you specify, or restores a previously
cleared window.  The function is useful for providing pop-up help screens,
error messages, or input panels.

The window size may be:

o 1 to 16 rows of 22 characters for 7524 operating in 20x40 screen mode If you
  request more rows than will fit, the number will be clipped at the maximum
  size.

A window frame of '*' characters will be drawn around the window, and either
REVERSE_VIDEO or NORMAL_VIDEO mode may be selected.

The beginning text position for all window sizes is at row 2, column 3.

The return code may be examined to determine the number of lines possible, the
width of those lines, and the starting position of the text.

The function stores both the characters and their display attributes when it
clears the window, and returns the screen to its original state when the window
is restored.  Any individual pixel manipulations are lost within the window
area.



     #include   "cfrutl24.h"           // Defined values

     UCHAR      pop_up_wnd(op_code, vio_mode, rows_requested,
                           rows_available, row_length,
                           start_col, start_row)


     CHAR       op_code               // CLEAR or RESTORE
     UCHAR      vio_mode              // NORMAL_VIDEO or REVERSE_VIDEO
     int        rows_requested        // Number of rows desired
                                         // (set to 0 when RESTOREing)
     int *      rows_available        // Returned rows available
     int *      row_length            // Returned row length available
     UCHAR *    start_col             // Returned row of upper left corner
                                         // of printable area
     UCHAR *    start_row             // Returned column of upper left corner
                                         // of printable area

     Note:      Values returned above are set to 0 when performing a RESTORE

     Returns:   MODEL_002_20X40          // If clearing a window area
                RESTORED                 // When restoring a window on any type






int far main (int funct,char far *params)
{
  USHORT xfrcnt;                   // Vio transfer count
  int rows_requested;              // Number of rows desired
   int rows_available, row_length;  // Returned values
   UCHAR r, c;                      // Returned row and column to place text

   rows_requested = 3;

   pop_up_wnd(CLEAR, REVERSE_VIDEO, rows_requested,
                               &rows_available, r, 00",21, r,c,&xfrcnt,0);
   VioWrtCharStr("By S. Morgenstern     ",22, r+1,c,&xfrcnt,0);
   VioWrtCharStr("(c) 1987, 1992",14, r+2,c,&xfrcnt,0);

    // delay 1 second
   do_var_delay(50);

    // restore original text/attributes
   pop_up_wnd(RESTORE, REVERSE_VIDEO, 0, &rows_available, r,
   .
   .

}



read_auto
---------
The read_auto function obtains keypad and/or sensor port input in the form
desired, and shows it in the designated position on the screen.  It will
control the method of data input, its maximum length, and numeric features such
as signed/non-signed, integer or floating point.

Data read is returned in key_in_num variable provided by the user.  This buffer
must be large enough to hold the length (plus 1) specified in the call.

When keypad input is enabled, the following keys may be used when the function
has control:

Function              Keys Used
Accept data           Left tab, Right tab, Enter, or OK keys.
Cursor Left           Shift - 1,4, or 7

                      Note:  For a single character movement, the Shift key may
                             be released prior to pressing the numeric key.
                             For multiple character movements, hold the Shift
                             key down will repeatedly pressing the numeric key.
Cursor Right          Shift - 3,6, or 9

                      Note:  See note under Cursor Left.
Backward Rub-out      back-space (rub-out)

                      Note:  This key rubs-out the data immediately to the left
                             of the cursor, and moves all text past the cursor
                             along with it to the left.
Clear                 Ends the input in a non-completed state and returns
                      CLEAR_KEY.
Cancel                Ends the input in a non-completed state and returns
                      CANCEL_KEY.


     #include   "cfrutl24.h"           // Defined values for 7524 ETS

     int read_auto(length, row, col, inputs_allowed, prefill, time_limit,
              edit, field_signed, field_precision, key_in_num)

     int length      Length of the input field; defines maximum keypad
                     input length and the length of the underscored
                     input field.  Maximum value is 39, assuming column
                     0 is used (see below).

     UCHAR row, col  Starting position of the input field.  (0,0) is the
                     upper left corner of the display.  The starting column
                     plus the length (see above) must total 39 or less
                     on a 40-character display, or 31 or less for a 7524-002
                     operating in 14x32 mode.

     char inputs_allowed   The input methods allowed in the field

            Defined input modes are:
              AI_ONLY           Only bar code and magnetic sensor
                                inputs are allowed
              AI_OR_KEYBD       Sensor or full keypad input is allowed
              KEYBD_ONLY        Only full keypad input is allowed
              NUM_KEYBD_ONLY    Only numeric keys forming a valid number
                                are allowed
              AI_OR_NUMKEYBD    Only sensor input (any data) or valid
                                numeric keys
              DATE_AMER         Date in form DD-MM-YYYY
              DATE_EURO         Date in form MM-DD-YYYY
              TIME_STD          24 hour time in form HH:SS

     char * prefill  String of characters to prefill the input field.
                     Use empty string for no prefill.  Time and date
                     format will be filled with input template as a default.

     int time_limit  Number of seconds allowed of inactivity before timeout.
                     Values are 1-65535, or 0 for no timeout enforced.

     char edit       Use defines YES and NO to allow editing of the prefilled
                     data;  NO means prefilled data is cleared as soon as a
                     data key is pressed.

     char field_signed  Use YES or NO defines to tell if the negative
                        (change sign) key should be allowed.

     int field_precision  -1 for no decimal point allowed, any other value
                          allows decimal point to be input.

     char * key_in_num    String buffer for function to place obtained from
                          sensors or keypad

Return values are:

o CANCEL_KEY if Cancel key is pressed
o CLEAR_KEY if Clear key is pressed
o LEFT_TAB, RIGHT_TAB, ENTER_KEY, or OK_KEY if one of those keys are pressed to
  accept the keyed input
o AI_READ if bar code or mag scanned
o TIME_OUT if time limit expired.





#include "cfrutl24.h"
#include "cfrapi24.h"

#define BUFFER_SIZE  40

int far main (int funct,char far *params)
{
 char buffer[BUFFER_SIZE];
 int rc;
 char prefill[10];

   .
   .
   .

 strcpy( prefill, " 1.50");

   // read an signed, real number from the numeric keypad, allowing
   // up to 30 seconds for input.  Show the 10 position input field
   // at row 1, column 20, with a prefilled value.
   // Loop while operator presses Clear key
 do
 {
   rc =  read_auto(10, 1, 20, NUM_KEYBD_ONLY, prefill, 30,  YES, YES,
                 1, buffer);
   switch(rc)
   {
     case TIME_OUT:
     case CANCEL_KEY:
        return(ABORT);
        break;
     case CLEAR_KEY:
          // re-do the read with no prefill
        strcpy(prefill, "");
        break;
   }
 }
 while( rc == CLEAR_KEY );

   // return data in UV 1
 WriteUserVariable(buffer, 1);

   .
   .
   .
}


sprintf_752x / sprintf_752xf
----------------------------
sprintf_752x performs print string formating like the regular C library sprintf
function provides, but without the PC-specific usage of std out.  All aspects
of the function work as printf/sprintf work, except the following:

o The length of the target buffer area must be provided (to prevent buffer
  overruns.

o The output may be automatically displayed at the requested row and column of
  the 752x display.  0,0 is the upper left corner of the display.  Use -1,-1
  for non-display usage (e.g.  for formating a transaction or printer string).

o The F and N addressing convention prefixes are not supported The h prefix
  (short 'size') is not supported   (USHORTS will work with the 'u' type).

o The e, E, g, and G types will be converted to f type.

o The n and p types are not supported.

o The # flag is not supported for any type.

The sprintf_752xf named version of the routine has the floating point support
included.  This adds several kilobytes of storage requirements over the basic
sprintf_752x version.  However, if you need floating point numbers formated in
an CFR, you should use the floating point version for all calls to avoid
redundant code being included in the file.






     #include   "cfrutl24.h"           // Defined values for 7524 ETS

     int sprintf_752x(buffer, buf_size, row,
                      col, format_str,...)

     char * buffer         // A pointer to a results work area which your
                           // program must provide

     int buf_size          // The size (in characters) of the buffer provided
                           // (see above)

     int row               // The row and column where you want the resulting
     int col               // string shown on the screen.  If you do not want
                           // the string shown, then specify row = -1 (the
                           // column value may be anything).

     char far * format_str // The output format string specification.  Refer
                           // to the IBM C/2 1.10 Language Reference under
                           // "printf" for details.

     ...                   // The variable number of numeric values, characters,
                           // and/or string pointers in the order referenced
                           // in the format string.



Return values are:

o OVERFLOW if the resulting string will not fit within the buffer provided
o BAD_WIDTH if a width specified is more than 2 digits long
o BAD_PREC if a precision specified is more than 2 digits long
o BAD_FORMAT_PHRASE if a "%" character is found with no valid trailing type
  specifier.
o E_OK if no error occured.

In the event of an error, the formatted string obtained up to the point of the
error is available.  Also, if optional automatic display was selected, the
following strings will be appended to the display to show the error result:

o *** shows that the formatted result exceeded the length of the supplied
      buffer

o *1* shows that a bad width was specified for a field

o *2* shows that a bad precision value was specified

o *3* shows that an unknown format identifier was used





#include "cfrutl24.h"
#include "cfrapi24.h"

#define BUFFER_SIZE  100

int far main (int funct,char far *params)
{
 char buffer[BUFFER_SIZE];
 static int number = 24;
 static char string[] = "Hello World";


   .
   .
   .

  // format a string and show at upper left corner
  // of the display
  // In this example, will show
  // "String = Hello World, Decimal = 24, Hex = 1B"
 sprintf_752x(buffer, BUFFER_SIZE, 0, 0,
              "String = %s, Decimal = %d, Hex = %X",
              string, number, number);

   .
   .
   .
}