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); . . . }