home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / FORMGE.ZIP / FORMGEN.C < prev    next >
Text File  |  1989-04-20  |  48KB  |  1,360 lines

  1. /* formgen.c */
  2.  
  3. /*
  4.  Formgen lets you interactively create a data entry form for use with a C
  5.  software application. It generates three C functions for you:
  6.  
  7.              (1) a display-the-form function
  8.              (2) a fill-the-form function
  9.              (3) an edit-the-form function (for data entry)
  10.  
  11.  This version of formgen is IBM PC-specific, and uses video buffering to
  12.  increase the speed of forms. The video (and field i/o) routines are
  13.  contained in "iolib.c".
  14.  
  15.  Programs which use the generated forms must also include iolib, unless
  16.  you change the "get" and "say" commands to operate with something else
  17.  (which is easy to do).  If you use the "editor-in-a-box" data type
  18.  ("ed"), you must also link in ioed.obj.  This function was separated from
  19.  the others so that screens which do not use it aren't penalized for its
  20.  size.
  21.  
  22.  This program, iolib and ioed are:
  23.  Copyright (c) 1989, John Queern, Belleville IL, (CIS 70120,107)
  24.  Placed in the public domain, April 1989.
  25.  
  26.  You may use this program for whatever you like (including commercial
  27.  applications). Just don't sell it. Pass it on--it's free.
  28.  Improve it--it's fun!
  29.  
  30. */
  31. /*  Notes:
  32.  
  33.     Data entry field information has been generalized to permit you
  34.     to add new field types easily. A data field description structure
  35.     is used to describe each "standard" data format and provide
  36.     default "get" and "say" command templates for the display and
  37.     edit screens:
  38.  
  39.         struct FIELDTYPE {
  40.             char    descr[20];          e.g., "i" for integer
  41.             char    *saycommand;        default display command template
  42.             char    *getcommand;        default edit command template
  43.         }
  44.  
  45.     Special codes which may be used in "say" and "get" command templates:
  46.  
  47.                 #X, #Y  - insert screen coordinates here
  48.                 #N      - insert variable name here
  49.                 #W      - insert width here
  50.                 #D      - insert decimals here
  51.  
  52.     Note: X and Y are integer values which are automatically generated
  53.     for you based on screen position. The rest are all strings, and may
  54.     actually be used for anything useful. For example, our "ed" field
  55.     type (the editor-in-a-box) uses #D to represent the number of lines
  56.     in the edit window.
  57.  
  58.     When you create an actual entry field on a screen, formgen
  59.     keeps track of it in a VARTYPE record (which you will fill in
  60.     when you create the variable):
  61.  
  62.         struct VARTYPE {
  63.             char    type[21];       data type (may match FIELDTYPE entry)
  64.             char    name[31];       name of this one
  65.             char    width[7];       width of field
  66.             char    decimals[7];    decimals (or lines, if "ed")
  67.             int     x,y;            position on screen (where token placed)
  68.             int     flagnum;        flag number on screen
  69.             char    saycomm[46];    actual say command for this var
  70.             char    getcomm[46];    actual get command fro this var
  71.         }
  72.  
  73.     When you select the F2 function ("Field"), formgen checks the
  74.     existing variable table to see if there's a field already at
  75.     that position. If so, it opens up an edit window and allows you
  76.     to edit the contents of the field record.
  77.     If not, formgen opens up an edit window for adding the record.
  78.  
  79.     The presence of a data entry field is marked on the form using
  80.     a graphic icon which signifies the anchor point for the entry
  81.     field (normally, the left side or upper left hand corner), followed
  82.     by the field table index value for the entry.  The field table is
  83.     kept updated (by realign()) to reflect current screen positions.
  84.  
  85. Future enhancements being considered (your opinion?):
  86.  
  87.        Allow the user to specify/override the field edit sequence (to go
  88.        in columns, for example, if desired);
  89.  
  90. */
  91.  
  92. #include <conio.h>
  93. #include <ctype.h>
  94. #include <process.h>
  95. #include <stdio.h>
  96. #include <stdlib.h>
  97. #include <string.h>
  98. #include "iolib.h"
  99. #include "ioed.h"
  100.  
  101. #define     TRUE    1
  102. #define     FALSE   0
  103. #define     NEW     1
  104. #define     OLD     0
  105. #define     MAXVAR  200
  106. #define     FMARKER '\020'      /* quasi-graphic field anchor char */
  107.  
  108. struct FIELDTYPE {
  109.     char    descr[20];      /* field description, e.g., int */
  110.     char    *saycommand;    /* default "say" command line for field type */
  111.     char    *getcommand;    /* default "get" command line for field type */
  112. } field[] = {
  113. /* Note: you may add your own "standard" field type definitions here: */
  114. /* lim:      +-------------------------------------------+ 45 chars      */
  115.  
  116.     "c",    "gotoxy(#X,#Y); cprintf(\"%c\",#N);",         /* char     */
  117.             "rcode = getachar(#X,#Y,&#N);",
  118.     "s",    "gotoxy(#X,#Y); cprintf(\"%-#Ws\",#N);",      /* string   */
  119.             "rcode = getstring(#X,#Y,&col,#N,#W);",
  120.     "i",    "gotoxy(#X,#Y); cprintf(\"%#Wd\",#N);",       /* integer  */
  121.             "rcode = getint(#X,#Y,&#N,#W);",
  122.     "f",    "gotoxy(#X,#Y); cprintf(\"%#W.#Dd\",#N);",    /* float    */
  123.             "rcode = getfloat(#X,#Y,&#N,#W,#D);",
  124.     "ed",   "redraw((char *)#N,#X,#Y,#W,#D);",            /* box editor */
  125.             "rcode=edit((char*)#N,#X,#Y,&xp,&yp,#W,#D);",
  126.  
  127.     "","",""   /* NULLs to mark the end of the table */
  128. };
  129.  
  130. struct VARTYPE {
  131.     char    type[21];       /* data type (may match FIELDTYPE entry) */
  132.     char    name[31];       /* name of this one */
  133.     char    width[7];       /* width of field */
  134.     char    decimals[7];    /* decimals (if appl) */
  135.     char    saycomm[46];    /* actual say command for this var */
  136.     char    getcomm[46];    /* actual get command fro this var */
  137.     int     x,y;            /* position on screen (where token placed) */
  138.     int     flagnum;        /* flag number displayed on screen (key) */
  139. }  var[MAXVAR];
  140.  
  141. /* function prototypes */
  142. void funkey_help(void);
  143. void savefile(void);
  144. void getfile(char *infname);
  145. void advance(int n);
  146. void encode(void);
  147. void display_colors(void);
  148. void fill_colors(void);
  149. void edit_colors(void);
  150. void getcolors(void);
  151. void display_parms(void);
  152. void fill_parms(void);
  153. void edit_parms(void);
  154. void getparms(void);
  155. void display_var(void);
  156. void fill_var(struct VARTYPE *v);
  157. void edit_var(struct VARTYPE *v, int age);
  158. int varcmpxy(struct VARTYPE *a, struct VARTYPE *b);
  159. int varcmp(struct VARTYPE *a, struct VARTYPE *b);
  160. void sortxy(void);
  161. void sortnum(void);
  162. void decode(char *str, struct VARTYPE *v);
  163. void realign(void);
  164. void addfield(int x,int y);
  165.  
  166. char    ch,
  167.         blank[]=
  168.   "                                                                          ",
  169.         bar[] =
  170.   "/*----------------------------------------------------------------------*/",
  171.         keyhelp[10][9] = {       /* function key labels: */
  172.             "1 Help ",
  173.             "2 Field",
  174.             "3 Color",
  175.             "4 Parms",
  176.             "5 DONE ",
  177.             "6 SelBx",
  178.             "7 MkBox",
  179.             "8 ClrBx",
  180.             "9 HLine",
  181.             "10 VLin" },
  182.         screen[25][81],
  183.         color[9][16] = {        /* default form colors */
  184.             "",                 
  185.             "NOCLEAR",          /* background (for clearing screen) */
  186.             "",
  187.             "WHITE",            /* form itself */
  188.             "BLUE",
  189.             "BLUE",             /* field fill */
  190.             "LIGHTGRAY",
  191.             "BLUE",             /* field edit */
  192.             "LIGHTGRAY"
  193.         },
  194.         infname[81],
  195.         otfname[81],
  196.         w[81],
  197.         d[81],
  198.         line[101],
  199.         temp[101],
  200.         parm[10][61] = {            /* form parameters: */
  201.             "",                     /* 0. (unused)                      */
  202.             "display_x",            /* 1. record display procedure name */
  203.             "fill_x(struct X *x)",  /* 2. field fill procedure name     */
  204.             "edit_x(struct X *x)",  /* 3. field edit procedure name     */
  205.             "",                     /* 4. extra 1st stmt for fill/edit  */
  206.             "",                     /* 5. extra last stmt for fill/edit */
  207.             "",                     /* 6. extra statement for display   */
  208.             "",                     /* 7.  "    "    "                  */
  209.             "0",                    /* 8. screen buffer to use          */
  210.             ""                      /* 9. (unused)                      */
  211.         };
  212.  
  213. int     x,y,
  214.         i,j,o,
  215.         p,q,z,n,r,
  216.         lines,
  217.         vars,
  218.         video;
  219.  
  220. FILE    *infile, *otfile;
  221.  
  222. /*=======================================================================*/
  223.  
  224. main(int argc,char *argv[])
  225. {
  226.     int     rcode,col=0,xp,yp;
  227.     char    choice,*p;
  228.  
  229.     /* init stuff */
  230.     binit(3);
  231.     textcolor(YELLOW);
  232.     textbackground(BLACK);
  233.     bfore=YELLOW;
  234.     bback=BLACK;
  235.     insertx=70;
  236.     inserty=24;
  237.     clrscr();
  238.     cprintf("           FORMGEN C Screen Generator\r\n\n");
  239.  
  240.     if (argc>1) strcpy(infname,argv[1]);
  241.     else {
  242.         cprintf("Work file to load (CR to bypass)? ");
  243.         gets(infname);
  244.     }
  245.     if (infname[0] != 0) getfile(infname);
  246.     xp=yp=0;
  247.     trimblanks=FALSE;  /* avoid constant trim/untrim during loop */
  248.  
  249.     do {   /* edit loop */
  250.         funkey_help();
  251.         rcode = edit((char *)screen,1,1,&xp,&yp,80,22);
  252.         if (vars>0) realign();  /* realign field positions */
  253.         switch (rcode) {
  254.             case 12 :                   /* F2 - add field */
  255.                 addfield(xp,yp);
  256.                 break;
  257.             case 13 :                   /* F3 - get colors */
  258.                 getcolors();
  259.                 break;
  260.             case 14 :                   /* F4 - get parameters */
  261.                 getparms();
  262.                 break;
  263.             case 7 :                    /* ctrl-w */
  264.             case 8 :                    /* End    */
  265.             case 15 :                   /* F5 - code gen / exit */
  266.                 gotoxy(1,24);
  267.                 clreol();
  268.                 cprintf("Do you wish to generate code now (Y/N)? ");
  269.                 choice=toupper(getche());
  270.                 if (choice != 'N') {
  271.                     gotoxy(1,24);
  272.                     clreol();
  273.                     cprintf("Generate code to (S)creen, (P)rinter or (F)ile? ");
  274.                     choice=toupper(getche());
  275.                     if (choice=='S') {
  276.                         otfile = stdout;
  277.                         clrscr();
  278.                         video=TRUE;
  279.                     }
  280.                     else if (choice=='P') {
  281.                         otfile = stdprn;
  282.                         video = FALSE;
  283.                     }
  284.                     else if (choice=='F') {
  285.                         gotoxy(1,24);
  286.                         clreol();
  287.                         cprintf("Active file: %s\r\n",infname);
  288.                         gotoxy(1,25);
  289.                         clreol();
  290.                         cprintf("File to save generated code in [.C]? ");
  291.                         strcpy(otfname,infname);
  292.                         p=strstr(otfname,".");
  293.                         if (p!=NULL) *p=0;
  294.                         col=0;
  295.                         getstring(48,25,&col,otfname,25);
  296.                         if (otfname[0]==0) break;
  297.                         p=strstr(otfname,".");
  298.                         if (p==NULL) strcat(otfname,".c");
  299.                         otfile=fopen(otfname,"w");
  300.                         if (otfile==NULL) {
  301.                             gotoxy(1,24);
  302.                             clreol();
  303.                             cprintf("Unable to open file. Press a key.");
  304.                             getch();
  305.                             break;
  306.                         }
  307.                     }
  308.                     else break;
  309.                     encode();
  310.                     video=FALSE;
  311.                     if (choice=='F') fclose(otfile);
  312.                 }
  313.                 gotoxy(1,24);
  314.                 clreol();
  315.                 cprintf("Do you wish to continue editing (Y/N)? ");
  316.                 choice=toupper(getche());
  317.                 gotoxy(1,24);
  318.                 clreol();
  319.                 if (choice=='N') {
  320.                     gotoxy(1,24);
  321.                     clreol();
  322.                     cprintf("Do you want to save your work file (Y/N)? ");
  323.                     choice=toupper(getche());
  324.                     if (choice != 'N') savefile();
  325.                     clrscr();
  326.                     exit(0);
  327.                 }
  328.                 break;
  329.             default:
  330.                 ;
  331.         }
  332.     } while (TRUE); /* escape using F5 or End to exit */
  333.  
  334. }
  335.  
  336. /*=======================================================================*/
  337.  
  338. void funkey_help(void)
  339. /* display function key help on 25th line */
  340. {
  341.     int     i;
  342.  
  343.     textcolor(BLUE);
  344.     textbackground(LIGHTGRAY);
  345.     for (i=0; i<10; i++) {
  346.         gotoxy(i*8+1,25);
  347.         cprintf("%s",keyhelp[i]);
  348.     }
  349.     textcolor(YELLOW);
  350.     textbackground(BLACK);
  351. }
  352.  
  353. /*=======================================================================*/
  354.  
  355. void savefile(void)
  356. /* save work file for future use */
  357. {
  358.     char    *p;
  359.     int     i,col;
  360.  
  361.     col=0;
  362.     gotoxy(1,25);
  363.     clreol();
  364.     cprintf("File to save work sheet in [.FRM]? ");
  365.     strcpy(otfname,infname);
  366.     p=strstr(otfname,".");
  367.     if (p!=NULL) *p=0;
  368.     getstring(48,25,&col,otfname,25);
  369.     if (otfname[0]==0) return;
  370.     p=strstr(otfname,".");
  371.     if (p==NULL) strcat(otfname,".frm");
  372.     otfile=fopen(otfname,"w");
  373.     if (otfile!=NULL) {
  374.         for (i=0;i<22; i++) {
  375.             trim(screen[i]);
  376.             fprintf(otfile,"%s\n",screen[i]);
  377.         }
  378.         for (i=1; i<=8; i++) {
  379.             trim(color[i]);
  380.             fprintf(otfile,"%s\n",color[i]);
  381.         }
  382.         for (i=0; i<10; i++) {
  383.             trim(parm[i]);
  384.             fprintf(otfile,"%s\n",parm[i]);
  385.         }
  386.         /* save variable records */
  387.         for (i=0; i<vars; i++) {
  388.             fprintf(otfile,"%s\n",var[i].type);
  389.             fprintf(otfile,"%s\n",var[i].name);
  390.             fprintf(otfile,"%s\n",var[i].width);
  391.             fprintf(otfile,"%s\n",var[i].decimals);
  392.             fprintf(otfile,"%s\n",var[i].saycomm);
  393.             fprintf(otfile,"%s\n",var[i].getcomm);
  394.             fprintf(otfile,"%d %d %d\n",var[i].x,var[i].y,var[i].flagnum);
  395.         }
  396.  
  397.         fclose(otfile);
  398.     }
  399.     else {
  400.         cprintf("Unable to create output file. Press a key...");
  401.         getch();
  402.     }
  403. }
  404.  
  405. /*=======================================================================*/
  406.  
  407. void getfile(char *infname)
  408. /* load input file (if desired) */
  409. {
  410.     int     i;
  411.  
  412.     if (strstr(infname,".") == NULL) strcat(infname,".frm");
  413.     infile = fopen(infname,"r");
  414.     if (infile==NULL) {
  415.         printf("\nNew file.\n");
  416.         return;
  417.     }
  418.     for (i=0;i<22; i++) {
  419.             fgets(screen[i],80,infile);
  420.             trim(screen[i]);
  421.             pad(screen[i],78);
  422.     }
  423.     /* get colors */
  424.     for (i=1; i<=8; i++) {
  425.         fgets(color[i],15,infile);
  426.         trim(color[i]);
  427.     }
  428.     strcpy(parm[8],"2");  /* default current buffer */
  429.     /* read parameters */
  430.     for (i=0; i<10; i++) {
  431.         fgets(parm[i],60,infile);
  432.         trim(parm[i]);
  433.     }
  434.     /* read any variable records which are present */
  435.     vars=0;
  436.     while (fgets(temp,100,infile) != NULL) {
  437.         trim(temp); strcpy(var[vars].type,temp);
  438.         fgets(temp,100,infile); trim(temp); strcpy(var[vars].name,temp);
  439.         fgets(temp,100,infile); trim(temp); strcpy(var[vars].width,temp);
  440.         fgets(temp,100,infile); trim(temp); strcpy(var[vars].decimals,temp);
  441.         fgets(temp,100,infile); trim(temp); strcpy(var[vars].saycomm,temp);
  442.         fgets(temp,100,infile); trim(temp); strcpy(var[vars].getcomm,temp);
  443.         fgets(temp,100,infile);
  444.         if (sscanf(temp,"%d %d %d",&var[vars].x,&var[vars].y,&var[vars].flagnum)
  445.             != 0) vars++;
  446.     }
  447.  
  448.     fclose(infile);
  449. }
  450.  
  451. /*=======================================================================*/
  452.  
  453. int varcmpxy(struct VARTYPE *a, struct VARTYPE *b)
  454. /* compare variable records and return: -1 if a<b, 0 if a=b, and +1 if a>b,
  455.    where the comparison is based on an ordering by row (y), then column (x) */
  456. {
  457.     int     result;
  458.  
  459.     if (a->y > b->y) result=1;
  460.     else if (b->y > a->y) result=-1;
  461.     else if (a->x > b-> x) result=1;
  462.     else if (b->x > a->x) result=-1;
  463.     else result=0;
  464.  
  465.     return(result);
  466. }
  467.  
  468.  
  469. void sortxy(void)
  470. /* sort variable table so that the variables are in y/x sequence */
  471. {
  472.     qsort(var,vars,sizeof(var[0]),varcmpxy);
  473. }
  474.  
  475.  
  476. int varcmp(struct VARTYPE *a, struct VARTYPE *b)
  477. /* compare variable records and return: -1 if a<b, 0 if a=b, and +1 if a>b,
  478.    where the comparison is based on the field number (index) value */
  479. {
  480.     int     result;
  481.  
  482.     if (a->flagnum > b->flagnum) result=1;
  483.     else if (b->flagnum > a->flagnum) result=-1;
  484.     else result=0;
  485.  
  486.     return(result);
  487. }
  488.  
  489. void sortnum(void)
  490. /* sort variable table by field number */
  491. {
  492.     qsort(var,vars,sizeof(var[0]),varcmp);
  493. }
  494.  
  495. /*=======================================================================*/
  496.  
  497. void decode(char *str, struct VARTYPE *v)
  498. /* decode any #-parameters in str, and expand them using the data in v  */
  499. /* NOTE: this routine destroys str, replacing it with a decoded version
  500.    THEREFORE: don't send it your original pattern; send it a copy which
  501.    has room for the expansion. */
  502. /*
  503.     Codes which are expanded:
  504.  
  505.                 #X, #Y  - replaced by screen coordinates
  506.                 #N      - replaced by variable name
  507.                 #W      - replaced by field width
  508.                 #D      - replaced by "decimals" entry
  509. */
  510. {
  511.     char    *cptr,*pptr,newstr[100],temp[46];
  512.     int     match;
  513.  
  514.     temp[0]=newstr[0]=0;
  515.     pptr = str;
  516.     cptr = strstr(str,"#");
  517.     while (cptr != NULL) {          /* found a #-combo */
  518.         match = TRUE;
  519.         switch (*(cptr+1)) {
  520.             case 'X' : sprintf(temp,"%d",v->x);
  521.                        break;
  522.             case 'Y' : sprintf(temp,"%d",v->y);
  523.                        break;
  524.             case 'N' : strcpy(temp,v->name);
  525.                        break;
  526.             case 'W' : strcpy(temp,v->width);
  527.                        break;
  528.             case 'D' : strcpy(temp,v->decimals);
  529.                        break;
  530.             default:   strcpy(temp,"#");
  531.                        match=FALSE;
  532.         }
  533.         *cptr=0;                /* cut off string before the # */
  534.         strcat(newstr,pptr);    /* copy up through the # */
  535.         strcat(newstr,temp);    /* add the decoded # value */
  536.         cptr++;                 /* advance past the # */
  537.         if (match) cptr++;      /* advance past the code char */
  538.         pptr = cptr;            /* mark start of next substring */
  539.         cptr = strstr(cptr,"#");    /* find next # */
  540.     }
  541.     strcat(newstr,pptr);        /* add any remaining text */
  542.     strcpy(str,newstr);         /* and send back the results */
  543. }
  544.  
  545. /*=======================================================================*/
  546.  
  547. void advance(int n)
  548. /* advance linecounter n lines; pause if using video and lines>20 */
  549. {
  550.     lines += n;
  551.     if (video && (lines>20)) {
  552.         lines=0;
  553.         printf("Press a key to continue...");
  554.         getch();
  555.         clrscr();
  556.     }
  557. }
  558.  
  559. /*=======================================================================*/
  560.  
  561. void encode(void)
  562. /* generate C source code for present display */
  563. /* assumes destination file (otfile) has been set up by caller */
  564. {
  565.     char    *cptr;
  566.     int     i,gets;
  567.  
  568.     /* chop off file type, if given */
  569.     cptr = strstr(infname,".");
  570.     if (cptr != NULL) *cptr=0;
  571.  
  572.     /* trim all arguments */
  573.     for (i=0;i<22; i++) trim(screen[i]);
  574.     for (i=1; i<=8; i++) trim(color[i]);
  575.     for (i=0; i<10; i++) trim(parm[i]);
  576.  
  577.     /* sort the field variables so they appear in y/x order */
  578.     sortxy();
  579.  
  580.     /* generate reminders/comments */
  581.     if (!video) {
  582.         fprintf(otfile,bar);
  583.         fprintf(otfile,"\n");
  584.         fprintf(otfile,"/* \n");
  585.         fprintf(otfile,"  Variables used: \n");
  586.         for (i=0; i<vars; i++) {
  587.             if (var[i].x == -1) continue;  /* unused field */
  588.             switch (var[i].type[0]) {
  589.                 case 'c' : sprintf(temp,"char \t%s;",var[i].name);
  590.                            break;
  591.                 case 's' : sprintf(temp,"char \t%s[%s+1];",var[i].name,
  592.                            var[i].width);
  593.                            break;
  594.                 case 'i' : sprintf(temp,"int  \t%s;",var[i].name);
  595.                            break;
  596.                 case 'f' : sprintf(temp,"float \t%s;",var[i].name);
  597.                            break;
  598.                 case 'e' : sprintf(temp,"char \t%s[(%s+1)*%s];",var[i].name,
  599.                            var[i].width,var[i].decimals);
  600.                            break;
  601.                 default:   sprintf(temp,"%s \t%s;",var[i].type,var[i].name);
  602.             }
  603.             fprintf(otfile,"    %s\n",temp);
  604.         }
  605.         fprintf(otfile,"*/\n");
  606.     }
  607.  
  608.     /*** create the screen form subroutine ***/
  609.     fprintf(otfile,bar);
  610.     fprintf(otfile,"\n");
  611.     fprintf(otfile,"\nvoid %s(void)\n",parm[1]);
  612.     fprintf(otfile,"/* screen code generated by formgen using: %s */\n",infname);
  613.     fprintf(otfile,"{\n");
  614.     lines=7;
  615.  
  616.     if (strcmp(color[1],"NOCLEAR")==0) {   /* don't clear the screen */
  617.         fprintf(otfile,"    savescreen(%s);\n",parm[8]);
  618.         advance(1);
  619.     }
  620.     else {
  621.         if (color[1][0]!=0) {
  622.             fprintf(otfile,"    bfore = %s; ",color[1]);
  623.             fprintf(otfile,"textcolor(%s);\n",color[1]);
  624.             advance(1);
  625.         }
  626.         if (color[2][0]!=0) {
  627.             fprintf(otfile,"    bback = %s; ",color[2]);
  628.             fprintf(otfile,"textbackground(%s);\n",color[2]);
  629.             advance(1);
  630.         }
  631.         fprintf(otfile,
  632.           "    /* change next line from bclear() to savescreen() if you */\n");
  633.         fprintf(otfile,
  634.           "    /* want the form to pop up over existing background      */\n");
  635.         fprintf(otfile,"    bclear(%s);\n",parm[8]);
  636.         advance(2);
  637.     }
  638.  
  639.  
  640.     if (color[3][0]!=0) {
  641.         fprintf(otfile,"    bfore = %s; ",color[3]);
  642.         fprintf(otfile,"textcolor(%s);\n",color[3]);
  643.         advance(1);
  644.     }
  645.     if (color[4][0]!=0) {
  646.         fprintf(otfile,"    bback = %s; ",color[4]);
  647.         fprintf(otfile,"textbackground(%s);\n",color[4]);
  648.         advance(1);
  649.     }
  650.  
  651.     for (y=0; y<20; y++) {
  652.         if (nonblank(screen[y])) {
  653.             strcpy(line,screen[y]);
  654.  
  655.             x=0;
  656.             z=strlen(line)-1;
  657.             while ((line[x]==' ') && (x<=z)) x++; /* x=first pos used */
  658.             while (line[z]==' ') z--; /* z=last pos used */
  659.  
  660.             /* remove any imbedded field markers */
  661.             cptr = strchr(line,FMARKER);
  662.             while (cptr != NULL) {
  663.                 *cptr = ' ';
  664.                 /* also remove the field number--assume any numeric
  665.                    digits immediately following the marker are part
  666.                    of the field number */
  667.                 cptr++;
  668.                 while (isdigit(*cptr)) *(cptr++)=' ';
  669.                 /* and find the next marker */
  670.                 cptr = strchr(line,FMARKER);
  671.             }
  672.  
  673.             /* process remaining (constant) string--for the background image */
  674.             /* isolate string in temp */
  675.             strcpy(temp,line+x);
  676.             temp[z-x+1]=0;
  677.  
  678.             fprintf(otfile,"    bwrite(%s,%d,%d,\"%s\");\n",
  679.                 parm[8],x,y,temp);
  680.             advance(1);
  681.  
  682.         } /* if nonblank */
  683.     } /* for */
  684.  
  685.     if (strcmp(color[1],"NOCLEAR")!=0) {   /* if using color[1] */
  686.         if (color[1][0]!=0) {
  687.             fprintf(otfile,"    bfore = %s; ",color[1]);
  688.             fprintf(otfile,"textcolor(%s);\n",color[1]);
  689.             advance(1);
  690.         }
  691.         if (color[2][0]!=0) {
  692.             fprintf(otfile,"    bback = %s; ",color[2]);
  693.             fprintf(otfile,"textbackground(%s);\n",color[2]);
  694.             advance(1);
  695.         }
  696.     }
  697.     fprintf(otfile,"    restorescreen(%s);\n",parm[8]);
  698.     advance(1);
  699.     if (parm[6][0]!=0) {
  700.         fprintf(otfile,"    %s\n",parm[6]);
  701.         advance(1);
  702.     }
  703.     if (parm[7][0]!=0) {
  704.         fprintf(otfile,"    %s\n",parm[7]);
  705.         advance(1);
  706.     }
  707.     fprintf(otfile,"}\n\n");
  708.     fprintf(otfile,"%s\n\n",bar);
  709.     advance(4);
  710.  
  711.     if (video) {
  712.         printf("Press a key to continue...");
  713.         getch();
  714.         clrscr();
  715.     }
  716.  
  717.     /*** create form fill subroutine ***/
  718.     if (vars>0 && strcmp(parm[2],"UNUSED")!=0) {
  719.         fprintf(otfile,"void %s\n",parm[2]);
  720.         fprintf(otfile,"{\n");
  721.         lines=5;
  722.         if (parm[4][0]!=0) {
  723.             fprintf(otfile,"    %s\n",parm[4]);
  724.             advance(1);
  725.         }
  726.         if (color[5][0]!=0) {
  727.             fprintf(otfile,"    bfore = %s; ",color[5]);
  728.             fprintf(otfile,"textcolor(%s);\n",color[5]);
  729.             advance(1);
  730.         }
  731.         if (color[6][0]!=0) {
  732.             fprintf(otfile,"    bback = %s; ",color[6]);
  733.             fprintf(otfile,"textbackground(%s);\n",color[6]);
  734.             advance(1);
  735.         }
  736.  
  737.         /* generate the sequence of "say" lines, 1 for ea. var */
  738.         for (i=0; i<vars; i++) {
  739.             if (var[i].x == -1) continue;  /* unused field */
  740.             strcpy(temp,var[i].saycomm);
  741.             decode(temp,&var[i]);
  742.             fprintf(otfile,"    %s\n",temp);
  743.             advance(1);
  744.         }
  745.  
  746.         fprintf(otfile,"\n");
  747.         if (strcmp(color[1],"NOCLEAR")!=0) {   /* if using color[1] */
  748.             if (color[1][0]!=0) {
  749.                 fprintf(otfile,"    bfore = %s; ",color[1]);
  750.                 fprintf(otfile,"textcolor(%s);\n",color[1]);
  751.                 advance(1);
  752.             }
  753.             if (color[2][0]!=0) {
  754.                 fprintf(otfile,"    bback = %s; ",color[2]);
  755.                 fprintf(otfile,"textbackground(%s);\n",color[2]);
  756.                 advance(1);
  757.             }
  758.         }
  759.         if (parm[5][0]!=0) {
  760.             fprintf(otfile,"    %s\n",parm[5]);
  761.             advance(1);
  762.         }
  763.         fprintf(otfile,"}\n\n%s\n\n",bar);
  764.     }   /* if gotsay */
  765.  
  766.     if (video) {
  767.         printf("Press a key to continue...");
  768.         getch();
  769.         clrscr();
  770.     }
  771.  
  772.     /*** create the form edit subroutine ***/
  773.     if (vars>0 && strcmp(parm[3],"UNUSED")!=0) {
  774.         fprintf(otfile,"void %s\n",parm[3]);
  775.         fprintf(otfile,"{\n");
  776.         fprintf(otfile,"    int    rcode,fieldnumber,col,xp,yp;\n\n");
  777.         lines=4;
  778.         if (parm[4][0]!=0) {
  779.             fprintf(otfile,"    %s\n",parm[4]);
  780.             advance(1);
  781.         }
  782.         if (color[7][0]!=0) {
  783.             fprintf(otfile,"    bfore = %s; ",color[7]);
  784.             fprintf(otfile,"textcolor(%s);\n",color[7]);
  785.             advance(1);
  786.         }
  787.         if (color[8][0]!=0) {
  788.             fprintf(otfile,"    bback = %s; ",color[8]);
  789.             fprintf(otfile,"textbackground(%s);\n",color[8]);
  790.             advance(1);
  791.         }
  792.  
  793.         /* generate switch-case statement */
  794.         fprintf(otfile,"    fieldnumber = 0;\n");
  795.         fprintf(otfile,"    do {\n");
  796.         fprintf(otfile,"        col = xp = yp = rcode = 0;\n");
  797.         fprintf(otfile,"        switch (fieldnumber) {\n");
  798.         advance(4);
  799.  
  800.         gets = 0;  /* count actual entries as you go */
  801.         for (i=0; i<vars; i++) {
  802.             if (var[i].getcomm[0]==0) continue;  /* no get here */
  803.             if (var[i].x == -1) continue;        /* unused field */
  804.  
  805.             gets++;
  806.             /* generate code for one field */
  807.             fprintf(otfile,"          case %d:\n",gets-1);
  808.             strcpy(temp,var[i].getcomm);
  809.             decode(temp,&var[i]);
  810.             fprintf(otfile,"            %s\n",temp);
  811.             fprintf(otfile,"            break;\n");
  812.             advance(3);
  813.  
  814.         } /* end of switch-case items */
  815.  
  816.         fprintf(otfile,"        }  /* switch fieldnumber */\n\n");
  817.  
  818.         if (video) {
  819.             printf("Press a key to continue...");
  820.             getch();
  821.             clrscr();
  822.             lines=0;
  823.         }
  824.  
  825.         /* now add the logic for advancing to the next field */
  826.         fprintf(otfile,"        switch (rcode) {\n");
  827.         fprintf(otfile,"            case 0:\n");
  828.         fprintf(otfile,"            case 1:\n");
  829.         fprintf(otfile,"            case 5:\n");
  830.         fprintf(otfile,"            case 6:\n");
  831.         fprintf(otfile,"            case 10:\n");
  832.         fprintf(otfile,"                fieldnumber++;\n");
  833.         fprintf(otfile,"                break;\n");
  834.         fprintf(otfile,"            case 3:\n");
  835.         fprintf(otfile,"            case 4:\n");
  836.         fprintf(otfile,"            case 9:\n");
  837.         fprintf(otfile,"                fieldnumber--;\n");
  838.         fprintf(otfile,"                break;\n");
  839.         fprintf(otfile,"            case 2:\n");
  840.         fprintf(otfile,"            case 7:\n");
  841.         fprintf(otfile,"            case 8:\n");
  842.         fprintf(otfile,"                rcode = 8; /* exit loop */\n");
  843.         fprintf(otfile,"                break;\n");
  844.         fprintf(otfile,"        }  /* switch rcode */\n\n");
  845.  
  846.         if (video) {
  847.             printf("Press a key to continue...");
  848.             getch();
  849.             clrscr();
  850.             lines=0;
  851.         }
  852.  
  853.         /* add code to permit field number wrap-around */
  854.  
  855.         fprintf(otfile,"        if (fieldnumber<0) fieldnumber = %d;\n",
  856.             gets-1);
  857.         fprintf(otfile,"        if (fieldnumber>%d) fieldnumber = 0;\n",
  858.             gets-1);
  859.         advance(2);
  860.  
  861.         /* terminate do loop with a while condition */
  862.         fprintf(otfile,"    } while (rcode != 8);\n");
  863.         advance(6);
  864.  
  865.         if (strcmp(color[1],"NOCLEAR")!=0) {   /* if using color[1] */
  866.             if (color[1][0]!=0) {
  867.                 fprintf(otfile,"    bfore = %s; ",color[1]);
  868.                 fprintf(otfile,"textcolor(%s);\n",color[1]);
  869.                 advance(1);
  870.             }
  871.             if (color[2][0]!=0) {
  872.                 fprintf(otfile,"    bback = %s; ",color[2]);
  873.                 fprintf(otfile,"textbackground(%s);\n",color[2]);
  874.                 advance(1);
  875.             }
  876.         }
  877.         fprintf(otfile,"    /* insert any special instructions here */\n\n");
  878.         if (parm[5][0]!=0) {
  879.             fprintf(otfile,"    %s\n",parm[5]);
  880.             advance(1);
  881.         }
  882.         fprintf(otfile,"}\n\n");
  883.     }
  884.  
  885.     if (video) {
  886.         printf("Press a key to continue...");
  887.         getch();
  888.         clrscr();
  889.     }
  890.  
  891.     sortnum();  /* resort the fields in field number order */
  892. }
  893.  
  894. /*======================================================================*/
  895.  
  896. void display_colors(void)
  897. {
  898.     bclear(2);
  899.     bwrite(2,10,3,"Set Display Color(s)");
  900.     bfore=BLUE;
  901.     bback=LIGHTGRAY;
  902.     bwrite(2,8,4,"╔═══════════════════════════════════════════════════════════════════╗");
  903.     bwrite(2,8,5,"║ SCREEN  (for initial screen clear, or NOCLEAR to avoid clearing)  ║");
  904.     bwrite(2,8,6,"║ Foreground:                      Background:                      ║");
  905.     bwrite(2,8,7,"╠═══════════════════════════════════════════════════════════════════╣");
  906.     bwrite(2,8,8,"║ FORM                                                              ║");
  907.     bwrite(2,8,9,"║ Foreground:                      Background:                      ║");
  908.     bwrite(2,8,10,"╠═══════════════════════════════════════════════════════════════════╣");
  909.     bwrite(2,8,11,"║ FIELD FILL                                                        ║");
  910.     bwrite(2,8,12,"║ Foreground:                      Background:                      ║");
  911.     bwrite(2,8,13,"╠═══════════════════════════════════════════════════════════════════╣");
  912.     bwrite(2,8,14,"║ FIELD EDIT                                                        ║");
  913.     bwrite(2,8,15,"║ Foreground:                      Background:                      ║");
  914.     bwrite(2,8,16,"║           NOTE: use CAPITAL LETTERS for color names               ║");
  915.     bwrite(2,8,17,"╚═══════════════════════════════════════════════════════════════════╝");
  916.     restorescreen(2);
  917.     bfore=YELLOW;
  918.     bback=BLACK;
  919. }
  920.  
  921. /*=======================================================================*/
  922.  
  923. void fill_colors(void)
  924. {
  925.     textcolor(WHITE);
  926.     textbackground(BLUE);
  927.     gotoxy(21,6);
  928.     cprintf("%-15s",color[1]);
  929.     gotoxy(54,6);
  930.     cprintf("%-15s",color[2]);
  931.     gotoxy(21,9);
  932.     cprintf("%-15s",color[3]);
  933.     gotoxy(54,9);
  934.     cprintf("%-15s",color[4]);
  935.     gotoxy(21,12);
  936.     cprintf("%-15s",color[5]);
  937.     gotoxy(54,12);
  938.     cprintf("%-15s",color[6]);
  939.     gotoxy(21,15);
  940.     cprintf("%-15s",color[7]);
  941.     gotoxy(54,15);
  942.     cprintf("%-15s",color[8]);
  943.  
  944.     textcolor(YELLOW);
  945.     textbackground(BLACK);
  946. }
  947.  
  948. /*=======================================================================*/
  949.  
  950. void edit_colors(void)
  951. {
  952.     int     rcode,fieldnumber,col;
  953.  
  954.     textcolor(WHITE);
  955.     textbackground(BLUE);
  956.     fieldnumber=0;
  957.  
  958.     do {
  959.         col=0;
  960.         switch (fieldnumber) {
  961.             case 0: rcode=getstring(21,6,&col,color[1],15);break;
  962.             case 1: rcode=getstring(54,6,&col,color[2],15);break;
  963.             case 2: rcode=getstring(21,9,&col,color[3],15);break;
  964.             case 3: rcode=getstring(54,9,&col,color[4],15);break;
  965.             case 4: rcode=getstring(21,12,&col,color[5],15);break;
  966.             case 5: rcode=getstring(54,12,&col,color[6],15);break;
  967.             case 6: rcode=getstring(21,15,&col,color[7],15);break;
  968.             case 7: rcode=getstring(54,15,&col,color[8],15);break;
  969.         }
  970.         switch (rcode) {
  971.             case 2:
  972.             case 7:
  973.             case 8: rcode=8;
  974.                     break;
  975.             case 3:
  976.             case 4: if (fieldnumber>0) fieldnumber--;
  977.                     else fieldnumber=7;
  978.                     break;
  979.             default:
  980.                     if (fieldnumber<7) fieldnumber++;
  981.                     else fieldnumber=0;
  982.                     break;
  983.         }
  984.     } while (rcode != 8);
  985.  
  986.     textcolor(YELLOW);
  987.     textbackground(BLACK);
  988.  
  989. }
  990.  
  991. /*=======================================================================*/
  992.  
  993. void getcolors(void)
  994. {
  995.     savescreen(1);
  996.     display_colors();
  997.     fill_colors();
  998.     edit_colors();
  999.     restorescreen(1);
  1000. }
  1001.  
  1002. /*=======================================================================*/
  1003.  
  1004. void display_parms(void)
  1005. {
  1006.     bclear(1);
  1007.     bwrite(1,25,2,"Miscellaneous FORMGEN Parameters");
  1008.     bfore=BLUE;
  1009.     bback=LIGHTGRAY;
  1010.     bwrite(1,1,3,"╔═════════════════════════════════════════════════════════════════════════════╗");
  1011.     bwrite(1,1,4,"║   FUNCTION NAMES                                                            ║");
  1012.     bwrite(1,1,5,"║     (omit parameter list for Display fncn, (void) will be assumed)          ║");
  1013.     bwrite(1,1,6,"║   Display:                                                                  ║");
  1014.     bwrite(1,1,7,"║   Fill:                                                                     ║");
  1015.     bwrite(1,1,8,"║   Edit:                                                                     ║");
  1016.     bwrite(1,1,9,"╠═════════════════════════════════════════════════════════════════════════════╣");
  1017.     bwrite(1,1,10,"║   Screen Buffer to use:                                                     ║");
  1018.     bwrite(1,1,11,"║   (0-4)                                                                     ║");
  1019.     bwrite(1,1,12,"╠═════════════════════════════════════════════════════════════════════════════╣");
  1020.     bwrite(1,1,13,"║   EXTRA LINES (added to top and/or bottom of fill and edit functions)       ║");
  1021.     bwrite(1,1,14,"║   First:                                                                    ║");
  1022.     bwrite(1,1,15,"║   Last:                                                                     ║");
  1023.     bwrite(1,1,16,"╠═════════════════════════════════════════════════════════════════════════════╣");
  1024.     bwrite(1,1,17,"║   EXTRA LINES (added to the end of the display function)                    ║");
  1025.     bwrite(1,1,18,"║   1:                                                                        ║");
  1026.     bwrite(1,1,19,"║   2:                                                                        ║");
  1027.     bwrite(1,1,20,"║                                                                             ║");
  1028.     bwrite(1,1,21,"╚═════════════════════════════════════════════════════════════════════════════╝");
  1029.     restorescreen(1);
  1030.     bfore=YELLOW;
  1031.     bback=BLACK;
  1032. }
  1033.  
  1034. /*=======================================================================*/
  1035.  
  1036. void fill_parms(void)
  1037. {
  1038.     textcolor(WHITE);
  1039.     textbackground(BLUE);
  1040.     gotoxy(14,6);
  1041.     cprintf("%-60s",parm[1]);
  1042.     gotoxy(14,7);
  1043.     cprintf("%-60s",parm[2]);
  1044.     gotoxy(14,8);
  1045.     cprintf("%-60s",parm[3]);
  1046.     gotoxy(14,11);
  1047.     cprintf("%-60s",parm[8]);
  1048.     gotoxy(11,14);
  1049.     cprintf("%-60s",parm[4]);
  1050.     gotoxy(11,15);
  1051.     cprintf("%-60s",parm[5]);
  1052.     gotoxy(7,18);
  1053.     cprintf("%-60s",parm[6]);
  1054.     gotoxy(7,19);
  1055.     cprintf("%-60s",parm[7]);
  1056.     textcolor(YELLOW);
  1057.     textbackground(BLACK);
  1058. }
  1059.  
  1060. /*=======================================================================*/
  1061.  
  1062. void edit_parms(void)
  1063. {
  1064.     int     rcode,fieldnumber,col;
  1065.  
  1066.     textcolor(WHITE);
  1067.     textbackground(BLUE);
  1068.     fieldnumber=1;
  1069.     do {
  1070.         col=0;
  1071.         switch (fieldnumber) {
  1072.             case 1: rcode=getstring(14,6,&col,parm[1],60);break;
  1073.             case 2: rcode=getstring(14,7,&col,parm[2],60);break;
  1074.             case 3: rcode=getstring(14,8,&col,parm[3],60);break;
  1075.             case 4: rcode=getstring(14,11,&col,parm[8],60);break;
  1076.             case 5: rcode=getstring(11,14,&col,parm[4],60);break;
  1077.             case 6: rcode=getstring(11,15,&col,parm[5],60);break;
  1078.             case 7: rcode=getstring(7,18,&col,parm[6],60);break;
  1079.             case 8: rcode=getstring(7,19,&col,parm[7],60);break;
  1080.         }
  1081.         switch (rcode) {
  1082.             case 0:
  1083.             case 1:
  1084.             case 5:
  1085.             case 6:
  1086.             case 10:
  1087.                 if (fieldnumber<8) fieldnumber++;
  1088.                 else fieldnumber=1;
  1089.                 break;
  1090.             case 3:
  1091.             case 4:
  1092.             case 9:
  1093.                 if (fieldnumber>1) fieldnumber--;
  1094.                 else fieldnumber=9;
  1095.                 break;
  1096.             case 2:
  1097.             case 7:
  1098.             case 8:
  1099.                 rcode=8;
  1100.         }
  1101.     } while (rcode != 8);
  1102.     textcolor(YELLOW);
  1103.     textbackground(BLACK);
  1104.  
  1105. }
  1106.  
  1107. /*=======================================================================*/
  1108.  
  1109. void getparms(void)
  1110. {
  1111.     savescreen(2);
  1112.     display_parms();
  1113.     fill_parms();
  1114.     edit_parms();
  1115.     restorescreen(2);
  1116. }
  1117.  
  1118. /*=======================================================================*/
  1119.  
  1120. void display_var(void)
  1121. /* screen code generated by formgen using: var */
  1122. {
  1123.     int     i;
  1124.  
  1125.     savescreen(1);
  1126.     bfore = RED;
  1127.     bback = LIGHTGRAY;
  1128.     i=0;
  1129.     while (field[i].descr[0]!=0 && i<24) {
  1130.         bwrite(1,71,i+1,field[i].descr);
  1131.         i++;
  1132.     }
  1133.     bfore = BLUE;
  1134.     bwrite(1,5,1,"╓─────────────────────────────────────────────────────────────────────╖");
  1135.     bwrite(1,5,2,"║    Variable Name:                                                   ║");
  1136.     bwrite(1,5,3,"║    Field Width:                  Decimals:                          ║");
  1137.     bwrite(1,5,4,"║    Data Type:                                                       ║");
  1138.     bwrite(1,5,5,"║    Display Command:                                                 ║");
  1139.     bwrite(1,5,6,"║    Entry Command(*):                                                ║");
  1140.     bwrite(1,5,7,"║                                                                     ║");
  1141.     bwrite(1,5,8,"║    (*) leave blank if no entry allowed                              ║");
  1142.     bwrite(1,5,9,"║    Special Sequences: #X, #Y -- insert screen row, column           ║");
  1143.     bwrite(1,5,10,"║                       #N     -- insert variable name                ║");
  1144.     bwrite(1,5,11,"║                       #W, #D -- insert width, decimals              ║");
  1145.     bwrite(1,5,12,"╙─────────────────────────────────────────────────────────────────────╜");
  1146.  
  1147.     restorescreen(1);
  1148.     bfore = YELLOW;
  1149.     bback = BLACK;
  1150. }
  1151.  
  1152. /*----------------------------------------------------------------------*/
  1153.  
  1154. void fill_var(struct VARTYPE *v)
  1155. {
  1156.     textcolor(WHITE);
  1157.     textbackground(BLUE);
  1158.     gotoxy(28,2);
  1159.     cprintf("%-30s",v->name);
  1160.     gotoxy(28,3);
  1161.     cprintf("%-6s",v->width);gotoxy(51,3);
  1162.     cprintf("%-6s",v->decimals);
  1163.     gotoxy(28,4);
  1164.     cprintf("%-20s",v->type);
  1165.     gotoxy(28,5);
  1166.     cprintf("%-45s",v->saycomm);
  1167.     gotoxy(28,6);
  1168.     cprintf("%-45s",v->getcomm);
  1169.  
  1170. }
  1171.  
  1172. /*----------------------------------------------------------------------*/
  1173.  
  1174. void edit_var(struct VARTYPE *v, int age)
  1175. {
  1176.     int rcode,fieldnumber,col,f,savetrim;
  1177.  
  1178.     textcolor(WHITE);
  1179.     textbackground(BLUE);
  1180.     fieldnumber = 0;
  1181.     savetrim = trimblanks;
  1182.     trimblanks = TRUE;
  1183.     do {
  1184.         col = 0;
  1185.         switch (fieldnumber) {
  1186.             case  0:    rcode=getstring(28,2,&col,v->name,30);
  1187.                           break;
  1188.             case  1:    rcode=getstring(28,3,&col,v->width,6);
  1189.                           break;
  1190.             case  2:    rcode=getstring(51,3,&col,v->decimals,6);
  1191.                           break;
  1192.             case  3:    rcode=getstring(28,4,&col,v->type,20);
  1193.                         if (age==NEW) {   /* look up reference commands */
  1194.                             f=0;
  1195.                             while (field[f].descr[0]!=0
  1196.                               && strcmp(field[f].descr,v->type)!=0) f++;
  1197.                             if (strcmp(field[f].descr,v->type)==0) {
  1198.                                 strcpy(v->saycomm,field[f].saycommand);
  1199.                                 strcpy(v->getcomm,field[f].getcommand);
  1200.                                 fill_var(v);
  1201.                             }
  1202.                             else {  /* if not found, look for prev use */
  1203.                                 f=0;
  1204.                                 while (strcmp(var[f].type,v->type)!=0) f++;
  1205.                                 if (var[f].flagnum != v->flagnum) {
  1206.                                     /* not the one we're working on--
  1207.                                        so use it to initialize templates */
  1208.                                     strcpy(v->saycomm,var[f].saycomm);
  1209.                                     strcpy(v->getcomm,var[f].getcomm);
  1210.                                     fill_var(v);
  1211.                                 }
  1212.                             }
  1213.                         }
  1214.                           break;
  1215.             case  4:    rcode=getstring(28,5,&col,v->saycomm,45);
  1216.                           break;
  1217.             case  5:    rcode=getstring(28,6,&col,v->getcomm,45);
  1218.                           break;
  1219.         }  /* switch fieldnumber */
  1220.  
  1221.         switch (rcode) {
  1222.             case 0:
  1223.             case 1:
  1224.             case 5:
  1225.             case 6:
  1226.             case 10:
  1227.                 fieldnumber++;
  1228.                 break;
  1229.             case 3:
  1230.             case 4:
  1231.             case 9:
  1232.                 fieldnumber--;
  1233.                 break;
  1234.             case 2:
  1235.             case 7:
  1236.             case 8:
  1237.                 rcode = 8; /* exit loop */
  1238.                 break;
  1239.         }  /* switch rcode */
  1240.  
  1241.         if (fieldnumber<0) fieldnumber = 5;
  1242.         if (fieldnumber>5) fieldnumber = 0;
  1243.     } while (rcode != 8);
  1244.     trimblanks=savetrim;
  1245.  
  1246. }
  1247.  
  1248. /*----------------------------------------------------------------------*/
  1249.  
  1250. void realign(void)
  1251. /* realign x,y coordinates in the field variable table based on the current
  1252.    picture presented in the screen buffer; mark any fields which no longer
  1253.    appear with x,y values of -1,-1 (off screen); Note: there is currently
  1254.    no provision to purge these unused fields from the work file.
  1255. */
  1256. {
  1257.     int     i,n,x,y;
  1258.     char    ch,*pptr,*cptr,*fptr;
  1259.  
  1260.     /* reset all marker positions to 0 first */
  1261.     for (i=0; i<vars; i++) var[i].x = var[i].y = -1;
  1262.  
  1263.     /* now scan the screen buffer looking for markers, and post their
  1264.        current position in the variable table */
  1265.     for (y=0; y<20; y++) {
  1266.         /* scan screen[y] for field markers; if found, update position */
  1267.         cptr = strchr(screen[y],FMARKER);
  1268.         while (cptr != NULL) {
  1269.             /* read the field number--assume any numeric
  1270.                 digits immediately following the marker are part
  1271.                 of the field number */
  1272.             fptr=cptr; /* save flag position */
  1273.             x=cptr-screen[y];  /* save x coordinate */
  1274.             cptr++;
  1275.             pptr=cptr; /* beginning of number */
  1276.             while (isdigit(*cptr)) cptr++;
  1277.             ch=*cptr; /* save first non-digit */
  1278.             *cptr=0;  /* and temporarily terminate here */
  1279.             sscanf(pptr,"%d",&n);  /* read the number */
  1280.             *cptr=ch; /* restore the original char */
  1281.             /* update var[n] with current x,y position */
  1282.  
  1283.             if (n>=0 && n<vars) {
  1284.                 /* cross check to ensure this is the right field */
  1285.                 if (var[n].flagnum != n) {
  1286.                     gotoxy(1,23);
  1287.                     clreol();
  1288.                     cprintf("WARNING: field sequence out of order. Press a key.");
  1289.                     getch();
  1290.                     gotoxy(1,23);
  1291.                     clreol();
  1292.                 }
  1293.                 else {
  1294.                     var[n].x = x;
  1295.                     var[n].y = y;
  1296.                 }
  1297.             }
  1298.             /* and find the next marker */
  1299.             cptr = strchr(++fptr,FMARKER);
  1300.         }   /* while */
  1301.     }  /* for */
  1302.     /* now scan the table and look for var's which have disappeared */
  1303.     /* (possible future addition? right now, they're dragged along) */
  1304.  
  1305. }
  1306.  
  1307. /*----------------------------------------------------------------------*/
  1308.  
  1309. void addfield(int x, int y)
  1310. /* add a field at position x,y  (where 0,0) is the upper left hand corner */
  1311. {
  1312.     int     i;
  1313.     char    *cptr,*tptr;
  1314.  
  1315.     /* look for a field already at x,y */
  1316.     for (i=0; i<vars; i++) if (var[i].x==x && var[i].y==y) break;
  1317.  
  1318.     /* if found, edit it --
  1319.        future: allow user to delete or move it as well */
  1320.     if (i<vars && var[i].x==x && var[i].y==y) {
  1321.         savescreen(2);
  1322.         display_var();
  1323.         fill_var(&var[i]);
  1324.         edit_var(&var[i],OLD);
  1325.         restorescreen(2);
  1326.     }
  1327.  
  1328.     /* if not found, add the field (provided vars < MAXVAR) */
  1329.     else {
  1330.         if (vars>=MAXVAR) {
  1331.             gotoxy(1,23);
  1332.             clreol();
  1333.             cprintf("** maximum fields already in use "
  1334.                     "...press a key **");
  1335.             getch();
  1336.             return;
  1337.         }
  1338.         vars++;
  1339.         var[vars-1].x=x;
  1340.         var[vars-1].y=y;
  1341.         var[vars-1].flagnum=vars-1;
  1342.         savescreen(2);
  1343.         display_var();
  1344.         fill_var(&var[vars-1]);
  1345.         edit_var(&var[vars-1],NEW);
  1346.         restorescreen(2);
  1347.  
  1348.         /* mark the field by placing a field marker in the line */
  1349.         cptr=&(screen[y][x]);
  1350.         pad(screen[y],80);  /* expand length first */
  1351.         *(cptr++)=FMARKER;
  1352.         /* add the var index number */
  1353.         sprintf(temp,"%d",vars-1);
  1354.         tptr=temp;
  1355.         while (*tptr != 0) *(cptr++) = *(tptr++);
  1356.         /* trim(screen[y]); */
  1357.     }
  1358.  
  1359. }
  1360.