D:\Atwin32.dev\Samples\UIEX\UIEX4
D:\Atwin32.dev\Samples\UIEX\UIEX5
  1|*
  2|**************************************************************************
  3|* Copyright (c) 2004 Schellenbach & Associates, Inc. dba AccuSoft        *
  4|* Enterprises as an unpublished work. Permission is hereby granted, free *
  5|* of charge, to any person obtaining a copy of this software, to use the *
  6|* software without restriction, including without limitation the rights  *
  7|* to use, copy, modify, merge, publish or distribute the software, and   *
  8|* to permit persons to whom the software is furnished to do so, subject  *
  9|* to the following conditions: This copyright notice and permission      *
 10|* notice shall be included in all copies or substantial portions of the  *
 11|* software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY    *
 12|* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES  *
 13|* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND               *
 14|* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR *
 15|* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF         *
 16|* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION     *
 17|* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *
 18|**************************************************************************
 19|**************************************************************************
 20|*
 21|* USER INTERFACE EXAMPLE PROGRAM 4
 22|*
 23|**************************************************************************
 24|**************************************************************************
 25|*
 26|* This example illustrates a character-based interface using the AccuSoft
 27|* Smart User Interface library for data entryMost display and input
 28|* processing is handled by the SUI subroutines, rather than using PRINT
 29|* and INPUT statements. By using the SUI library, input fields accept
 30|* cursor keys, editing keys, function keys and mouse clicks. The SUI
 31|* subroutines also utilize AccuTerm Visual Styles to display screen
 32|* elements using a Windows-like look (if avaliable).
 33|*
 34|**************************************************************************
 35|*
 36|* To use the SUI library, you must include SUI.TERMDEF. This INCLUDE item
 37|* contains EQUates for various terminal functions like visual attributes
 38|* and line graphics, as well as constants for the keyboard commands like
 39|* TERM.ENTER$ or TERM.PGUP$.
 40|*
 41|$INCLUDE SUIBP SUI.TERMDEF
 42|*
 43|**************************************************************************
 44|*
 45|* The CUST.REC INCLUDE item declares the CUST.REC array, which is used to
 46|* store a working copy of the current data record. It also defines the
 47|* record layout by equating field names to array positions in the CUST.REC
 48|* array.
 49|*
 50|$INCLUDE UIEX.CUST.REC
 51|*
 52|**************************************************************************
 53|*
 54|* EQUates for control characters and delimiters and other constants
 55|*
 56|EQU VM TO CHAR(253)
 57|EQU BEL TO CHAR(7)
 58|EQU ESC TO CHAR(27)
 59|EQU STX TO CHAR(2)
 60|EQU CR TO CHAR(13)
 61|EQU FALSE TO 0
 62|EQU TRUE TO 1
 63|*
 64|**************************************************************************
 65|*
 66|* Any routine that uses the SUI library must call SUI.GET.TERM to
 67|* initialize the TermDef array. The TermDef array is a required argument
 68|* for all of the SUI subroutines. It is much better to call this routine
 69|* one time and pass the TermDef array between various routines instead of
 70|* calling it in each application subroutine that uses SUI.
 71|*
 72|CALL SUI.GET.TERM(MAT TermDef)
 73|*
 74|**************************************************************************
 75|*
 76|* Once the TermDef array is initialized by SUI.GET.TERM, the TERM.RESET
 77|* string is sent to the terminal to initialize the terminal state. The
 78|* reset string programs necessary function keys and initalizes any other
 79|* terminal state as required for each particular terminal type.
 80|*
 81|PRINT TERM.RESET:
 82|*
 83|**************************************************************************
 84|*
 85|* This program uses AccuTerm Imaging to display pictures associated with
 86|* records in the customer file. This EQUate defines the path where the
 87|* image files are located.
 88|*
 89|EQU PIX.PATH TO 'http://www.asent.com/demo/PIX/'
 90|*
 91|* Check for image support (no images if dumb terminal or AccuTerm Lite)
 92|*
 93|IF INDEX(TERM.SPECIAL,'I',1) THEN IMGFLG = TRUE ELSE IMGFLG = FALSE
 94|*
 95|**************************************************************************
 96|*
 97|* Open our files...
 98|*
 99|OPEN 'CUST.SAMPLE' TO FN.CUST ELSE PRINT 'NO CUST.SAMPLE FILE'; STOP
100|OPEN 'DICT CUST.SAMPLE' TO FN.DICT.CUST ELSE PRINT 'NO DICT CUST.SAMPLE FILE'; STOP
101|OPEN 'CUST.SAMPLE.XREF' TO FN.CUST.XREF ELSE PRINT 'NO CUST.SAMPLE.XREF'; STOP
102|*
103|**************************************************************************
104|*
105|* Define the data field control structures. NUMFLDS is the number of
106|* fields. The CONTROL array defines the field control elements such as
107|* field label, label position, field position and size, and field prompt.
108|* The IDATA array stores the current field values, and is initialized
109|from the CUST.REC array when a data record is read from the file. When
110|the record is updated, values are copied from the IDATA array to the
111|* CUST.REC array and the CUST.REC array is passed to the CUST.UPDATE
112|* subroutine to update the data and index files (a separate subroutine is
113|* used to update the file since the update process may handle other
114|* functions like updating indexes).
115|*
116|NUMFLDS = 12
117|DIM CONTROL(12)
118|DIM IDATA(12)
119|*
120|* Define field control elements
121|*  value 1: field label text
122|*  value 2: field label column
123|*  value 3: field label row
124|*  value 4: field label width (0 for actual width, no padding)
125|*  value 5: field data column
126|*  value 6: field data row
127|*  value 7: field data width
128|*  value 8: field data height
129|*  value 9: field prompt message
130|CONTROL(1) = 'Customer IDý7ý2ý20ý28ý2ý30ý1ýEnter the ID, or name to search for, or N for next number'
131|CONTROL(2) = 'Contactý7ý4ý20ý28ý4ý30ý1ýEnter the contact name'
132|CONTROL(3) = 'Company nameý7ý5ý20ý28ý5ý30ý1ýEnter the company name'
133|CONTROL(4) = 'Address line 1ý7ý6ý20ý28ý6ý30ý1ýEnter address line 1'
134|CONTROL(5) = 'Address line 2ý7ý7ý20ý28ý7ý30ý1ýEnter address line 2'
135|CONTROL(6) = 'Cityý7ý8ý20ý28ý8ý25ý1ýEnter the city'
136|CONTROL(7) = 'State or provinceý7ý9ý20ý28ý9ý15ý1ýEnter the state or province abbreviation'
137|CONTROL(8) = 'Zip/postal codeý7ý10ý20ý28ý10ý10ý1ýEnter the zip or postal code'
138|CONTROL(9) = 'Countryý7ý11ý20ý28ý11ý18ý1ýEnter the country'
139|CONTROL(10) = 'Phoneý7ý12ý20ý28ý12ý15ý1ýEnter the phone number'
140|CONTROL(11) = 'Faxý7ý13ý20ý28ý13ý15ý1ýEnter the fax number'
141|CONTROL(12) = 'Notesý7ý14ý20ý28ý14ý30ý3ýEnter any notes about this customer'
142|*
143|**************************************************************************
144|*
145|Define some screen control strings for prompts & errors
146|*
147|PROMPT ''
148|PL = @(5,22):TERM.CEOL
149|EL = @(5,23):TERM.CEOL
   
   
   
   
   
   
150|*
151|**************************************************************************
152|*
153|* This program processes one customer record at a time, and is organized
154|* using three nested loops. The outermost loop (the RECORD loop) is
155|* executed once for each record accessed. The loop repeats until the EXIT
156|* control variable is set to TRUE.
157|*
   
   
   
   
158|EXIT = FALSE
159|LOOP UNTIL EXIT DO
160| *
161| *************************************************************************
162| *
163| * Before prompting for the customer ID, reset the internal data array
164| * (IDATA) and CUST.ID variables, then clear the screen and display the
165| * heading and field labels.
166| * 
167| GOSUB RESTART
168| GOSUB DSPSCRN
169| *
170| *************************************************************************
171| *
172| * The middle loop is the ACTION loop. It is executed for the current
173| * record until the user performs an action that terminates processing of
174| * that record, such as exiting, cancelling, saving or deleting the
175| * record. The field number to begin prompting (NXTFLD) is initialized to
176| * 1, causing the ID field to be prompted first. The loop immediately
177| * enters the PROMPT loop, followed by the field modification prompt. The
178| * loop repeats until the DONE control variable is set to TRUE.
179| *
180| NXTFLD = 1
181| DONE = FALSE
182| LOOP
183|  *
184|  ************************************************************************
185|  *
186|  * The inner loop is the PROMPT loop. It is executed for each prompt
187|  * field as specified by the NXTFLD variable. The prompt loop simply
188|  * calls the local INPUT.FIELD subroutine which performs field input,
189|  * data validation and keyboard command decoding. The FIELD loop repeats
190|  * until the field number is greater than the number of fields, or until
191|  * the DONE control variable is set to TRUE. The DONE control variable
192|  * may be set to TRUE in the INPUT.FIELD subroutine, if the user enters a
193|  * NULL to for the item-ID.
   
194|  *
195|  LOOP
196|   CURFLD = NXTFLD
197|  UNTIL DONE OR CURFLD > NUMFLDS DO
198|   *
199|   ***********************************************************************
200|   *
201|   * Prompt for the next field. Update the NXTFLD variable with the field
202|   * number to prompt nexttaking into account cursor keys and mouse
203|   * clicks.
   
204|   *
205|   GOSUB INPUT.FIELD
206|  REPEAT ;* end of PROMPT loop
207|  *
208|  ************************************************************************
209|  *
210|  * If the FIELD loop exited with the DONE control variable set to TRUE,
211|  * bypass the modification prompt because no action is required.
212|  * Otherwise, prompt for which field to modify, or other actions such as
213|  * save or delete.
214|  *
215|  IF NOT(DONE) THEN
216|   *
217|   NXTFLD = NUMFLDS + 1 ;* assume we need to reprompt for action
218|   *
219|   PRINT PL:'Enter field number to modify or FI to save, DE to delete, EX to exit: ':
220|   INPUT ANS:
221|   PRINT EL:
   
   
   
   
   
   
222|   *
223|   ***********************************************************************
224|   *
225|   * Decode the response
226|   *
227|   ANS = OCONV(ANS, 'MCU')
   
   
   
   
   
   
   
   
   
   
   
   
   
228|   BEGIN CASE
229|    CASE NUM(ANS) AND ANS >= 1 AND ANS <= NUMFLDSNXTFLD = ANS
230|    CASE ANS EQ 'FI'; GOSUB SAVE.RECORD
231|    CASE ANS EQ 'DE'; GOSUB DELETE.RECORD
232|    CASE ANS EQ 'EX' OR ANS EQ ''; GOSUB CHECK.EXIT
   
   
   
   
233|   END CASE 
234|   *  
235|  END
236|  *
237| UNTIL DONE DO REPEAT ;* end of ACTION loop
238| *
239|REPEAT ;* end of RECORD loop
240|*
241|**************************************************************************
242|*
243|* All done - clear the screen, restore the cursor and exit!
244|PRINT TERM.CLEAR:TERM.CSRON:
245|STOP
246|*
247|*
248|**************************************************************************
249|**************************************************************************
250|* LOCAL SUBROUTINES
251|**************************************************************************
252|**************************************************************************
253|*
254|*
255|**************************************************************************
256|*
257|* The INPUT.FIELD subroutine is the main prompting routine. This routine
258|* displays the prompt string (from the CONTROL array), and enters a loop,
259|* prompting for a specified field (CURFLD) and setting the next field
260|* variable (NXTFLD) appropriately. The loop repeats until the NXTFLD
261|* (initially set to CURFLD) changes. This causes the field prompt to be
262|* repeated in case unrecognized keys are pressed (for example, the PGUP
263|* key), or invalid data is entered (illegal customer ID, etc.) If a NULL
264|is entered for the ID fieldand there is no current record, the ACTION
265|loop control variable, DONE, and the RECORD loop control variable, EXIT,
266|are set to TRUEand this routine exits. A mouse click is handled by
267|setting the NXTFLD variable to the field number that was clicked.
   
   
268|*
269|INPUT.FIELD: 
270|*
271|**************************************************************************
272|*
273|* Display the prompt message
274|*
275|CALL SUI.DISPLAY.LABEL(522, 74, 'L', 0, CONTROL(CURFLD)<1,9>, CMD, MAT TermDef)
276|*
277|**************************************************************************
278|*
279|* Initialize current value, next field & character positions
280|*
281|PREVAL = IDATA(CURFLD) ;* Save previous field value to detect change in value
282|NXTFLD = CURFLD ;* Assume field number not changed
283|BEGPOS = 0 ;* Set initial text display character position
284|CURPOS = 0 ;* Set initial text cursor character position
285|*
286|**************************************************************************
287|*
288|* Prompt for this field until NXTFLD variable is updated
289|*
290|LOOP
291| *
292| *************************************************************************
293| *
294| * Prompt for input with full text editing functions
295| *
296| CALL SUI.INPUT.TEXT(CONTROL(CURFLD)<1,5>, CONTROL(CURFLD)<1,6>, CONTROL(CURFLD)<1,7>, CONTROL(CURFLD)<1,8>, '', 0, IDATA(CURFLD), BEGPOS, CURPOS, CMD, MAT TermDef)
297| PRINT TERM.CSRON:EL: ;* Turn cursor back on & clear the error line
298| *
299| *************************************************************************
300| *
301| * Decode returned CMD
302| *
303| BEGIN CASE
304|  *
305|  ************************************************************************
306|  *
307|  * Check for ENTER, TAB, UP, DOWN or mouse click
308|  *
309|  CASE CMD EQ TERM.ENTER$ OR CMD EQ TERM.TAB$ OR CMD EQ TERM.DOWN$
310|   NXTFLD = CURFLD + 1; * Move to next field   
311|  CASE CMD EQ TERM.STAB$ OR CMD EQ TERM.UP$
312|   IF CURFLD > 1 THEN NXTFLD = CURFLD - 1 ;* Move to previous field
313|  CASE CMD EQ TERM.LEFTBUTTON$
314|   GOSUB CHECK.MOUSE ;* Move to clicked-on field
315|   IF CURFLD EQ 1 AND NXTFLD NE CURFLD THEN
316|    IF IDATA(1) EQ '' THEN NXTFLD = CURFLD ;Mouse click in invalid field - ignore click
317|   END
   
   
   
   
   
   
   
   
   
   
318|  *
319| END CASE
320| *
321| *************************************************************************
322| *
   
   
   
   
   
   
323| * Check for any special values (like 'END' or 'EXIT')
324| *
325| IF OCONV(IDATA(CURFLD),'MCU') EQ 'END' THEN
326|  IDATA(CURFLD) = PREVAL ;* Restore previous value
327|  GOSUB CHECK.ABANDON ;* Ensure OK to loose changes
328|  IF OK THEN
329|   *
330|   ***********************************************************************
331|   *
332|   * No changes, or user OKs abandoning them, so we are outa here!
333|   *
334|   DONE = TRUE
335|   EXIT = TRUE
336|   RETURN
337|   *
338|  END ELSE
339|   *
340|   ***********************************************************************
341|   *
342|   * User does not want to abandon changes, so refresh previous value &
343|   * reprompt
344|   *
345|   XLINE = CURFLD ;* Field number to refresh
346|   GOSUB DSPLINE ;* Redisplay the previous value
347|   NXTFLD = CURFLD ;* Reprompt
348|   *
349|  END
350| END
351| *
352| *************************************************************************
353| *
354| * Peform field data validation if next field number changed
355| *
356| IF NXTFLD NE CURFLD THEN
357|  BEGIN CASE
358|   *
359|   CASE CURFLD EQ 1
360|    *
361|    **********************************************************************
362|    *
363|    * Validate the ID field. If NULL, quit. If changed, read new record.
364|    *
365|    IF CUST.ID EQ '' AND IDATA(CURFLD) EQ '' THEN
366|     DONE = TRUE
367|     EXIT = TRUE
368|     RETURN
369|    END
370|    *
371|    IF IDATA(CURFLD) NE PREVAL THEN
372|     ID = IDATA(CURFLD)
373|     GOSUB CHECK.ID ;* Check the newly entered ID handling index lookups
374|     IF OK THEN
375|      *
376|      ********************************************************************
377|      *
378|      * New ID (or result of index lookup) is good!
379|      *
380|      IDATA(CURFLD) = ID ;* Update the current field value in case of index lookup
381|      *
382|     END ELSE
383|      *
384|      ********************************************************************
385|      *
386|      * New ID is invalid
387|      *
388|      IDATA(CURFLD) = PREVAL ;* Restore previous value
389|      XLINE = CURFLD ;* Field number to refresh
390|      GOSUB DSPLINE ;* Redisplay the previous value
391|      NXTFLD = CURFLD ;* Reprompt
392|      *
393|     END
394|    END
395|    *
   
   
   
   
   
   
   
   
396|  END CASE
397| END
398| *
399|WHILE CURFLD EQ NXTFLD DO REPEAT
400|*
401|RETURN
402|*
403|*
404|**************************************************************************
405|*
   
   
   
   
   
   
   
   
   
   
   
   
   
406|* The CHECK.EXIT subroutine checks if any field data has changed, and
407|* prompts if the user wants to abandon changes. If no changes, or the
408|user decides to abandon the changes, the DONE and EXIT loop control
409|variables are set to TRUE, causing all three loops to terminate, and the
410|program itself to exit.
411|*
412|CHECK.EXIT: *
413|*
414|GOSUB CHECK.ABANDON
415|IF OK THEN
416| DONE = TRUE
417| EXIT = TRUE
418| GOSUB HIDEPIX
419|END
420|RETURN
421|*
422|*
423|**************************************************************************
424|*
425|* The CHECK.ID subroutine validates a newly entered item-ID. If the
426|* current record has unsaved changes, the user is prompted to abandon the
427|* changes. If no changes, or the user abandons the changes, and the new ID
428|* is not NULL, an attempt is made to read a record using the new ID. If
429|* the read is not successful, the ID is assumed to be a search string, and
430|* the search subroutine is called to select an ID based on the search
431|* string. If a valid ID is returned (or if one was initially entered), the
432|* new record data is displayed. If the new ID is null, or if the search
433|* routine did not return a valid ID, a warning message is displayed and
434|* the OK indicator variable is set to FALSE. Otherwise it is set to TRUE.
   
435|*
436|CHECK.ID: *
437|*
438|**************************************************************************
439|*
440|* Make sure we don't have any unsaved data before changing the ID
441|*
442|GOSUB CHECK.ABANDON
443|IF NOT(OK) THEN RETURN ;* Reprompt for the ID
444|IF ID EQ '' THEN
445| OK = FALSE ;* NULL is not a valid ID!
446|END ELSE
447| *
448| *************************************************************************
449| *
450| * Check if user wants new ID
451| *
452| IF ID EQ 'N' OR ID EQ 'n' THEN
453|  * Get next sequential ID
454|  READVU ID FROM FN.DICT.CUST,'NEXT',2 THEN
455|   WRITEV ID + 1 ON FN.DICT.CUST,'NEXT',2
456|   GOSUB RESTART
457|   IDATA(1) = ID
458|  END ELSE
459|   PRINT EL:TERM.DRV:'Next item counter record not found!':TERM.NV:BEL:
460|   INPUT ANS:
461|   PRINT EL:
462|   OK = FALSE
463|   RETURN
464|  END
465| END ELSE
466|  *
467|  *************************************************************************
468|  *
469|  * Try to read the customer record from the entered ID
470|  *
471|  GOSUB READ.RECORD
472|  IF NOT(OK) THEN
473|   *
474|   ************************************************************************
475|   *
476|   * The attempt to read a record failed - assume the ID is a search string
477|   *
478|   GOSUB HIDEPIX ;* Pictures always show on top of text, so hide before call
479|   CALL UIEX.GET.CUST.IDX(XID,ID,FN.CUST.XREF,FN.CUST)
480|   GOSUB DSPSCRN ;* Refresh the screen after index lookup
   
   
   
   
481|   *
482|   ************************************************************************
483|   *
484|   * If the user did not select an item in the search routine, reprompt
485|   *
486|   IF XID EQ '' THEN RETURN
487|   *
488|   ************************************************************************
489|   *
490|   * Try to read the customer record from the selected ID
491|   *
492|   ID = XID
493|   GOSUB READ.RECORD
494|   *
495|  END
496| END  
497|END
498|*
499|**************************************************************************
500|*
501|* If success, display the new record, otherwise show warning message
502|*
503|IF OK THEN
504| GOSUB DSPDATA ;* Display new record
   
505|END ELSE
506| PRINT EL:TERM.DRV:'Please enter a valid customer ID!':TERM.NV:BEL:
   
507|END
508|RETURN
509|*
510|*
511|**************************************************************************
512|*
513|* The READ.RECORD subroutine reads a new customer record from the file and
514|* initializes the internal field data array (IDATA) from the record array
515|* (CUST.REC). If the record does not exist, the routine returns with the
516|* OK indicator variable set to FALSE. Otherwise OK is set to TRUE, and the
517|* CUST.ID variable is set to the new ID.
518|*
519|READ.RECORD: *
520|*
521|MATREAD CUST.REC FROM FN.CUST,ID THEN
522| CUST.ID = ID
523| IDATA(1) = CUST.ID
524| IDATA(2) = CUST.CONTACT
525| IDATA(3) = CUST.NAME
526| IDATA(4) = CUST.ADDRESS1
527| IDATA(5) = CUST.ADDRESS2
528| IDATA(6) = CUST.CITY
529| IDATA(7) = CUST.ST
530| IDATA(8) = CUST.ZIP
531| IDATA(9) = CUST.COUNTRY
532| IDATA(10) = CUST.PHONE
533| IDATA(11) = CUST.FAX
534| IDATA(12) = CUST.HISTORY
535| OK = TRUE ;* Set the SUCCESS indicator
536|END ELSE
537| OK = FALSE ;* Set the FAILURE indicator
538|END
539|RETURN
540|*
541|*
542|**************************************************************************
543|*
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
544|* The DELETE.RECORD subroutine confirms that the user intends to delete
545|* the current record. If the action is confirmed, the CUST.DELETE
546|* subroutine is called to perform the deletion. A separate subroutine is
547|* used to handle updating indexes, etc.
548|*
549|DELETE.RECORD: *
550|*
551|IF CUST.ID NE '' THEN
552| PRINT EL:TERM:DRV:'Are you sure you want to delete this customer? ':TERM:NV:
553| INPUT ANS:
554| IF ANS[1,1] EQ 'Y' OR ANS[1,1] EQ 'y' THEN
   
555|  * Deletion has been confirmed - do the delete
556|  OK = TRUE ;* Set the SUCCESS indicator
557|  CALL UIEX.CUST.DELETE(CUST.ID,FN.CUST,FN.CUST.XREF)
558|  DONE = TRUE ;* proceed to next record
559|  GOSUB HIDEPIX ;* erase picture
560| END ELSE
561|  OK = FALSE ;* Set the FAILURE indicator
562| END
563|END
564|RETURN
565|*
566|*
567|**************************************************************************
568|*
569|* The SAVE.RECORD subroutine copies internal field data from the IDATA
570|* array to the customer record array (CUST.REC). The CUST.UPDATE
571|* subroutine is called to perform the update. A separate subroutine is
572|* used to handle updating indexes, etc.
573|*
574|SAVE.RECORD: *
575|*
576|IF IDATA(1) NE '' THEN
577| * Copy data from the internal field data array (IDATA) to the CUST.REC array
578| CUST.ID = IDATA(1)
579| CUST.CONTACT = IDATA(2)
580| CUST.NAME = IDATA(3)
581| CUST.ADDRESS1 = IDATA(4)
582| CUST.ADDRESS2 = IDATA(5)
583| CUST.CITY = IDATA(6)
584| CUST.ST = IDATA(7)
585| CUST.ZIP = IDATA(8)
586| CUST.COUNTRY = IDATA(9)
587| CUST.PHONE = IDATA(10)
588| CUST.FAX = IDATA(11)
589| CUST.HISTORY = IDATA(12)
590| * Update the file
591| CALL UIEX.CUST.UPDATE(CUST.ID,MAT CUST.REC,FN.CUST,FN.CUST.XREF)
592| OK = TRUE ;* Set the SUCCESS indicator
593|END ELSE
594| OK = FALSE ;* Set the FAILURE indicator
595|END
596|DONE = TRUE ;* proceed to next record
597|RETURN
598|*
599|*
600|**************************************************************************
601|*
602|* The RESTART subroutine prepares the internal field data array (IDATA),
603|* customer record array (CUST.REC) and ID for a new customer record.
604|*
605|RESTART: *
606|*
607|CUST.ID = ''
608|MAT CUST.REC = ''
609|MAT IDATA = ''
   
610|RETURN
611|*
612|*
613|**************************************************************************
614|*
615|* The CHECK.CHANGED subroutine checks if any internal field data has been
616|* changed. The OK indicator variable is set to FALSE if any data is
617|* changed, otherwise it is set to TRUE. The ID field is not checked, since
618|* it is appropriately handled by the CHECK.ID subroutine.
619|*
620|CHECK.CHANGED: *
621|*
622|OK = FALSE
623|IF CUST.CONTACT # IDATA(2) THEN RETURN
624|IF CUST.NAME # IDATA(3) THEN RETURN
625|IF CUST.ADDRESS1 # IDATA(4) THEN RETURN
626|IF CUST.ADDRESS2 # IDATA(5) THEN RETURN
627|IF CUST.CITY # IDATA(6) THEN RETURN
628|