/* COPYRIGHT (c) 1986 - 1995 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED. THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. */ /* PROGRAM NAME: FORMS$SAMPLE_PROGRAM_C.C PROGRAM DESCRIPTION: This is the Introductory Sample Application provided with the DECforms product. AUTHOR: Digital Equipment Corporation CREATION DATE: Dec-1991 MODIFIED: Mar-1998 ------ Instructions ------ If your system manager copied the Sample from the DECforms kit onto your system, you can run the DECforms Sample Checking Application by doing the following: $ RUN FORMS$EXAMPLES:FORMS$SAMPLE_PROGRAM_C The DECforms INTRODUCTORY Sample Checking Application in the C language consists of two files: FORMS$SAMPLE_PROGRAM_C.C The application itself FORMS$SAMPLE_FORM.IFDL The IFDL source form Both files are copied from the DECforms kit to the FORMS$EXAMPLES directory. Putting the files in FORMS$EXAMPLES is an installation option; talk to your system manager if they aren't there. A working version of the application can be created in your own directory from these sources by doing the following: $! Set the default to your own directory: $ SET DEFAULT yourdirectory $ $! Copy all the sources files from FORMS$EXAMPLES to your own directory: $ COPY FORMS$EXAMPLES:FORMS$SAMPLE_PROGRAM_C.C, - FORMS$SAMPLE_FORM.IFDL [] $! Compile the C source: $ CC FORMS$SAMPLE_PROGRAM_C.C $ $! Translate the IFDL source form: $ FORMS TRANSLATE FORMS$SAMPLE_FORM.IFDL $ $! Extract an object module which contains only the form's call table vectors from the binary form: $ FORMS EXTRACT OBJECT /NOFORM_LOAD FORMS$SAMPLE_FORM.FORM $ $! Link the C and the Form objects: $! With VAX C: $ LINK FORMS$SAMPLE_PROGRAM_C.OBJ, FORMS$SAMPLE_FORM.OBJ, - SYS$INPUT/OPTIONS SYS$LIBRARY:VAXCRTL.OLB/LIB $! With DEC C: $ LINK FORMS$SAMPLE_PROGRAM_C.OBJ, FORMS$SAMPLE_FORM.OBJ ! ! note that FORMS$AR_FORM_TABLE must be specified in the FORMS$ENABLE call ! due to the use of an escape routine $! Define logical for the device to be used: $ DEFINE FORMS$DEFAULT_DEVICE SYS$INPUT ! if using a char cell terminal OR $ DEFINE FORMS$DEFAULT_DEVICE DECW$DISPLAY ! if using a Motif workstation ( you may also have to $ SET DISPLAY /CREATE /NODE=nodename) You can then run the executable in your own directory by simply typing: $ RUN FORMS$SAMPLE_PROGRAM_C $! If creating DDIF output, use a command similar to the following to produce a PostScript file for high quality printed results: $ CONVERT/DOCUMENT ddif_form.doc ddif_form.ps /FORMAT=PS $ $! You can effectively test the appearance of a DDIF form by using the VIEW command. For example, $ VIEW ddif_form.doc /FORMAT=DDIF /INTERFACE=DECWINDOWS Note that the program expects the form file to be in the FORMS$EXAMPLES directory or in the current directory. By copying the files to your local directory, you can change the form if you wish and retranslate it. */ #include #include #include #include #include #include /* * A simple macro to construct a string descriptor for a structure */ #define $STRUCTURE_DESCRIPTOR(name,rec) struct dsc$descriptor_s name = {sizeof(rec), DSC$K_DTYPE_T, DSC$K_CLASS_S, (char *)&rec} /* A session desc must be used on every call to the FORMS$... subroutines. forms_status is returned from every call on the FORMS$... subroutines. */ char session_buffer[16]; struct dsc$descriptor_s session_desc = {sizeof(session_buffer), DSC$K_DTYPE_T, DSC$K_CLASS_S, session_buffer}; char ddif_session_buffer[16]; struct dsc$descriptor_s ddif_session_desc = {sizeof(ddif_session_buffer), DSC$K_DTYPE_T, DSC$K_CLASS_S, ddif_session_buffer}; int forms_status; $DESCRIPTOR(ddif_out_desc,"ddif_form.doc"); $DESCRIPTOR(term_desc,"FORMS$DEFAULT_DEVICE"); $DESCRIPTOR(form_file_desc,"FORMS$EXAMPLES:forms$sample_form.form"); /* The ACCOUNT record is sent to the form at the beginning of the program to set the form data so it can appear on the check and deposit slip. */ struct account_str { int account_number; char mail_name[39]; char street[30]; char mail_csz[30]; }; struct account_str account={1594,"Harold Q. Stevenson", "134 North Elm Street", "Elk Grove, MA 99943"}; /* The UPDATE record keeps the variable account information. It is sent to the form at the beginning of each exchange. */ struct update_str { short check_number; int balance; }; struct update_str update={15,13251}; /* The OPERATOR_CHOICE record is implemented as the menu_choice variable, a very simple record message. */ short menu_choice; /* The GET_CHECK record message is used by a RECEIVE to get check information from the operator. The GET_CHECK record message is used by a SEND to pass the operator's check data to the DDIF form. */ struct get_check_str { int check_amount; char check_payto[35]; char check_memo[35]; }; struct get_check_str get_check; /* The GET_DEPOSIT record message is used only by a RECEIVE to get deposit information from the operator. */ struct get_deposit_str { int deposit_amount; char deposit_memo[35]; }; struct get_deposit_str get_deposit; $STRUCTURE_DESCRIPTOR(account_desc, account); $STRUCTURE_DESCRIPTOR(update_desc, update); $STRUCTURE_DESCRIPTOR(menu_choice_desc, menu_choice); $STRUCTURE_DESCRIPTOR(get_check_desc, get_check); $STRUCTURE_DESCRIPTOR(get_deposit_desc, get_deposit); $DESCRIPTOR(account_name_desc,"account"); $DESCRIPTOR(update_name_desc,"update"); $DESCRIPTOR(operator_choice_desc,"operator_choice"); $DESCRIPTOR(get_check_name_desc,"get_check"); $DESCRIPTOR(get_deposit_name_desc,"get_deposit"); check_forms_status() /* Check the parameter for success. If not success, print error message and stop. */ { if (forms_status && ((forms_status % 2)==0)) /* if even */ { lib$signal(forms_status); exit(1); } } void print_check( struct dsc$descriptor_s *payto, int *amount, struct dsc$descriptor_s *memo) /* Send the check data to a DDIF file. */ { /* Send the static account information to be printed */ /* (i.e., the account record). */ forms_status = forms$send ( &ddif_session_desc, &account_name_desc, &1, 0,0, 0,0, 0, 0, 0, &account_desc, 0); check_forms_status(); /* Send the dynamic account information to be printed */ /* (i.e., check number). */ forms_status = forms$send ( &ddif_session_desc, &update_name_desc, &1, 0,0, 0,0, 0, 0, 0, &update_desc, 0); check_forms_status(); /* Fill in current values for GET_CHECK structure. */ strcpy (get_check.check_payto, payto->dsc$a_pointer); get_check.check_amount = *amount; strcpy (get_check.check_memo, memo->dsc$a_pointer); /* Send the check-specific information to be printed */ /* (i.e., check amount, to whom, and possibly memo). */ forms_status = forms$send ( &ddif_session_desc, &get_check_name_desc, &1, 0,0, 0,0, 0, 0, 0, &get_check_desc, 0); check_forms_status(); } main() { /* Print startup message on console */ printf ("C DECforms Sample Program starting."); /* Initialize the DECforms form & check for errors */ forms_status = forms$enable ( &forms$ar_form_table,/* Vector address */ &term_desc, /* Device name */ &session_desc, /* session id returned */ &form_file_desc, /* Name of form file */ /* The following trailing pars can be omitted */ 0, /* Name of form */ 0, /* Receive ctl msg */ 0, /* Receive ctl ct */ 0, /* Send ctl msg */ 0, /* Send ctl ct */ 0, /* Timeout */ 0, /* Parent request id */ 0); /* request options item list */ check_forms_status(); forms_status = forms$enable ( &forms$ar_form_table,/* Vector address */ &ddif_out_desc, /* where output is sent */ &ddif_session_desc, /* session id returned */ &form_file_desc, /* Name of form file */ /* The following trailing pars can be omitted */ 0, /* Name of form */ 0, /* Receive ctl msg */ 0, /* Receive ctl ct */ 0, /* Send ctl msg */ 0, /* Send ctl ct */ 0, /* Timeout */ 0, /* Parent request id */ 0); /* request options item list */ check_forms_status(); /* Tell the form all the account information: */ /* The account record, the balance and the next check number. */ forms_status = forms$send ( &session_desc, /* session id */ &account_name_desc, /* record name in form */ &1, /* Number of records sent */ 0,0, /* Receive ctl text msg/count */ 0,0, /* Send ctl text msg/count */ 0, /* timeout */ 0, /* parent request id */ 0, /* request options item list*/ &account_desc, /* the record */ 0); /* shadow record */ check_forms_status(); /* Do major program loop, until operator requests exit. */ menu_choice = 0; while (menu_choice != 1) { /* Send the current state of the dynamic account information and */ /* request the rturn of an option of what to do next: 1, 2 or 3. */ /* Note that the form will validate and return only those values. */ forms_status = forms$transceive ( &session_desc, /* session id */ &update_name_desc, /* send record name */ &1, /* send record count */ &operator_choice_desc, /* receive record name */ &1, /* receive record count */ 0,0, /* Receive ctl text msg/count */ 0,0, /* Send ctl text msg/count */ 0, /* timeout */ 0, /* parent request id */ 0, /* request options item list*/ &update_desc, 0, &menu_choice_desc, 0); check_forms_status(); if (menu_choice == 2) { /* Write a check. */ /* Ask the operator for the information and update account */ /* balance and the check number. */ /* Note that validation in the form guarantees that the */ /* amount of the check is always greater than zero and that */ /* the balance can cover the check. */ forms_status = forms$receive ( &session_desc, &get_check_name_desc, &1, 0,0, 0,0, 0, 0, 0, &get_check_desc, 0); check_forms_status(); update.balance = update.balance - get_check.check_amount; ++update.check_number; } else if (menu_choice == 3) { /* Make a deposit. */ /* Ask the operator for the deposit information and update */ /* the account balance. */ forms_status = forms$receive( &session_desc, /* session id */ &get_deposit_name_desc, /* receive record name */ &1, /* receive record count */ 0,0, /* Receive ctl text msg/count */ 0,0, /* Send ctl text msg/count */ 0, /* timeout */ 0, /* parent request id */ 0, /* request options item list*/ &get_deposit_desc, /* the record */ 0); /* shadow record */ check_forms_status(); update.balance = update.balance + get_deposit.deposit_amount; }; }; /* Clean up, print ending message on console, leave. */ forms_status = forms$disable (&ddif_session_desc); check_forms_status(); forms_status = forms$disable (&session_desc); check_forms_status(); printf("C DECforms Sample Program ending."); }