home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Unleashed / Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso / repease / rep_fld.c < prev    next >
C/C++ Source or Header  |  1995-02-14  |  29KB  |  778 lines

  1. /*==============================================================================
  2.    REP_FLD.C
  3.    Report Ease: Field functions.
  4.  
  5.    ReportEase Plus
  6.    Sub Systems, Inc.
  7.    ReportEase Plus, Copyright (c) 1993, Sub Systems, Inc. All Rights Reserved.
  8.    159 Main Street, #8C, Stoneham,  MA 02180 
  9.    (617) 438-8901.
  10.  
  11.    Software License Agreement  (1993)              
  12.    ----------------------------------
  13.    This license agreement allows the purchaser the right to modify the 
  14.    source code to incorporate in their application.
  15.    The target application must not be distributed as a standalone report writer
  16.    or a mail merge product.
  17.    Sub Systems, Inc. reserves the right to prosecute anybody found to be 
  18.    making illegal copies of the executable software or compiling the source
  19.    code for the purpose of selling there after.
  20.  
  21. ===============================================================================*/
  22. #include "windows.h"
  23.  
  24. #if defined (_WIN32)
  25.    #if !defined(WIN32)
  26.      #define WIN32
  27.    #endif
  28. #endif
  29. #if !defined(WIN32) 
  30.   #include "print.h"
  31. #endif
  32.  
  33. #include "stdio.h"
  34. #include "stdlib.h"
  35. #include "ctype.h"
  36. #include "fcntl.h"
  37. #include "io.h"
  38. #include "sys\types.h"
  39. #include "sys\stat.h"
  40. #include "string.h"
  41. #include "setjmp.h"
  42.  
  43. #include "rep.h"
  44.  
  45. #define  PREFIX extern
  46. #include "rep1.h"
  47.  
  48. /******************************************************************************
  49.     InsertDataField:
  50.     This routine calls the data field selection function in your application.
  51.     The selected data field is inserted at the current cursor position.
  52. ******************************************************************************/
  53. InsertDataField()
  54. {
  55.     struct StrField TempField;
  56.  
  57.     // find empty TempField slot
  58.     if (END_OF_EXP==(NewField=FindFieldSlot())) {
  59.        MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
  60.        return FALSE;
  61.     }
  62.     
  63.     // accept an application TempField from the user application 
  64.     InitField(&TempField);              // initialize the TempField variables 
  65.     if (!(FormArg.UserSelection)(hFrWnd,&TempField,0)) return FALSE;  // call a user routine to select a data TempField 
  66.     
  67.     // copy the TempField into the current array position 
  68.     field[NewField]=TempField;
  69.     
  70.     return TRUE;
  71. }
  72.  
  73. /******************************************************************************
  74.     InsertCalcField:
  75.     This routine allows the user to create a calculation field.
  76.     The new calculation field is inserted at the current cursor position.
  77. ******************************************************************************/
  78. InsertCalcField()
  79. {
  80.     struct StrField TempField;
  81.     
  82.     // find empty TempField slot
  83.     if (END_OF_EXP==(NewField=FindFieldSlot())) {
  84.        MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
  85.        return FALSE;
  86.     }
  87.     else {
  88.        field[NewField].InUse=TRUE;      // reserve this slot
  89.        lstrcpy(field[NewField].name,"");// reset any old name name 
  90.     }
  91.  
  92.     InitField(&TempField);              // initialize the TempField variables 
  93.     TempField.source=SRC_CALC;
  94.     if (!GetCalcField(&TempField)) return FALSE;
  95.  
  96.     // copy the TempField into the current array position 
  97.     field[NewField]=TempField;
  98.  
  99.     return TRUE;
  100. }
  101.  
  102. /******************************************************************************
  103.     InsertSysField:
  104.     This routine calls the system field selection function in your application.
  105.     The selected data field is inserted at the current cursor position.
  106. ******************************************************************************/
  107. InsertSysField()
  108. {
  109.     int  SystemFieldNo;
  110.     struct StrField TempField;
  111.  
  112.     // find empty TempField slot
  113.     if (END_OF_EXP==(NewField=FindFieldSlot())) {
  114.        MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
  115.        return FALSE;
  116.     }
  117.  
  118.     InitField(&TempField);              // initialize the field variables 
  119.  
  120.     // accept a system field to insert 
  121.     if ((SystemFieldNo=CallDialogBox("SysParam",SysParam,0L))<0) return FALSE;
  122.     
  123.     TempField.source=SRC_SYS;                     // source of field data 
  124.     lstrcpy(TempField.name,"SYS->");
  125.     lstrcat(TempField.name,SysField[SystemFieldNo].name);
  126.     TempField.type=SysField[SystemFieldNo].type;  // num/alpha etc 
  127.     TempField.SysIdx=SystemFieldNo;               // index into the system field structure 
  128.     TempField.width=SysField[SystemFieldNo].width;// width of the field 
  129.     TempField.AllowChanges=TRUE;                  // user can modify the following fields 
  130.  
  131.     // copy the TempField into the current array position 
  132.     field[NewField]=TempField;
  133.  
  134.     return TRUE;
  135. }
  136.  
  137. /******************************************************************************
  138.     InsertDlgField:
  139.     This routine calls the dialog field selection function in your application.
  140.     The selected data field is inserted at the current cursor position.
  141. ******************************************************************************/
  142. InsertDlgField()
  143. {
  144.     int   i,j,DlgFieldNo;
  145.     struct StrField TempField;
  146.  
  147.     //****************** Validate that dialog TempField table is not empty *****
  148.     j=0;
  149.     for (i=0;i<MAX_DLGS;i++) {
  150.        if (DlgField[i].InUse) {
  151.           j++;
  152.           break;
  153.        }
  154.     }
  155.     if (j==0) {
  156.        MessageBox(hFrWnd,"Dialog Field Table Empty!",NULL,MB_OK);
  157.        return FALSE;
  158.     }
  159.     
  160.     // find empty TempField slot
  161.     if (END_OF_EXP==(NewField=FindFieldSlot())) {
  162.        MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
  163.        return FALSE;
  164.     }
  165.  
  166.  
  167.     InitField(&TempField);              // initialize the TempField variables 
  168.  
  169.     // accept a system TempField to insert 
  170.     if ((DlgFieldNo=CallDialogBox("DlgParam",DlgParam,0L))<0) return FALSE;
  171.     
  172.     // fillup the TempField structure 
  173.     TempField.source=SRC_DLG;                 // source of TempField data 
  174.     lstrcpy(TempField.name,"DLG->");
  175.     lstrcat(TempField.name,DlgField[DlgFieldNo].name);
  176.     TempField.type=DlgField[DlgFieldNo].type; // num/alpha etc 
  177.     TempField.SysIdx=DlgFieldNo;              // index into the dialog TempField structure 
  178.     TempField.width=DlgField[DlgFieldNo].width;// width of the TempField 
  179.     TempField.AllowChanges=TRUE;              // user can modify the following TempFields 
  180.  
  181.     // copy the TempField into the current array position 
  182.     field[NewField]=TempField;
  183.  
  184.     return TRUE;
  185. }
  186.  
  187. /******************************************************************************
  188.     CreateFieldLabel:
  189.     This routine creates a screen field label for the given field.  The third
  190.     argument provides the width of the display rectangle within which the
  191.     label should fit.  The last argument gives the font index used to print
  192.     the label. 
  193. ******************************************************************************/
  194. CreateFieldLabel(int CurField,LPSTR label,int DispWidth,int font)
  195. {
  196.     int i,j,width,type,len,DecPlaces,digits,DecFound,temp;
  197.     int LeftSignLen,RightSignLen,CurrencySymLen;
  198.     char line[LINE_WIDTH+2],mm[3],dd[3],yy[5];
  199.     unsigned flags;
  200.  
  201.     width=field[CurField].width;
  202.     type=field[CurField].type;
  203.     flags=field[CurField].flags;
  204.     DecPlaces=field[CurField].DecPlaces;
  205.     if (DispWidth>0) DispWidth-=(2*DESC_MARGIN);      // adjust the display width of the field
  206.  
  207.     //*************** Format Alpha Fields **********************************
  208.     if (type==TYPE_TEXT) {
  209.         for (i=0;i<LINE_WIDTH;i++) label[i]='x'; // default label character
  210.         label[i]=0;
  211.         if (flags&FLAG_CAPS) lstrupr(label);
  212.         else if (flags&FLAG_SMALL) lstrlwr(label);
  213.         else if (flags&FLAG_FIRST_CAP) {
  214.            lstrlwr(label);
  215.            label[0]=toupper(label[0]);
  216.         }
  217.  
  218.         if (DispWidth==0) DispWidth=2*(DEF_RECT_WIDTH-DESC_MARGIN); // assume twice the default rectangle width
  219.         // find how many characters can fit this rectangle
  220.         if (field[CurField].source==SRC_CALC) width=LINE_WIDTH; // don't limit as we really don't know the width of calculation field
  221.         i=0;
  222.         while (DispWidth>0 && i<width && i<LINE_WIDTH) {
  223.            DispWidth=DispWidth-FrFont[font].CharWidth[label[i]];
  224.            i++;
  225.         }
  226.         if (DispWidth<0 && i>0) i--;
  227.         label[i]=0;
  228.  
  229.     }
  230.     //**************** Format numeric fields ********************************
  231.     else if (type==TYPE_NUM || type==TYPE_DBL) {
  232.         len=width;
  233.         for (i=0;i<len;i++) label[i]='9';    // default numeric character
  234.         label[i]=0;
  235.         if (DecPlaces>0) {                // insert a decimal 
  236.            len=strlen(label);
  237.            if (DecPlaces>len) {
  238.               lPad(label,DecPlaces+1);
  239.               label[0]='.';
  240.               i=1;
  241.               while (label[i]==' ') {
  242.                  label[i]='0';
  243.                  i++;
  244.               }
  245.            }
  246.            else {
  247.               lPad(&label[len-DecPlaces],DecPlaces+1);
  248.               label[len-DecPlaces]='.';
  249.            }
  250.         }
  251.         
  252.         //********************* insert comma characters *******************
  253.         if (flags&FLAG_COMMA) {             // insert comma 
  254.            len=strlen(label);
  255.            for (digits=0;digits<len;digits++) if (label[digits]=='.') break;
  256.            if (digits>0) {
  257.               strcpy(line,label);
  258.               j=0;
  259.               DecFound=FALSE;
  260.               for (i=0;i<len;i++,j++) {
  261.                   if (DecFound) {           // simply copy the remaining digits 
  262.                      label[j]=line[i];
  263.                   }
  264.                   else {                    // before decimal 
  265.                      if (line[i]=='.') {
  266.                         label[j]=line[i];
  267.                         DecFound=TRUE;
  268.                      }
  269.                      else {                 // do we need to insert comma 
  270.                         temp=digits/3;
  271.                         if (digits==temp*3 && digits>0 && j>0) {// insert comma 
  272.                            label[j]=',';
  273.                            j++;
  274.                         }
  275.                         label[j]=line[i];
  276.                         digits--;
  277.                      }
  278.                   }
  279.               }
  280.               label[j]=0;
  281.            }
  282.         }
  283.         
  284.         //******************* Apply numeric properties ************************
  285.         len=strlen(label);
  286.         LeftSignLen=lstrlen(field[CurField].NegSignPrefix);
  287.         if (lstrlen(field[CurField].PosSignPrefix)>LeftSignLen) LeftSignLen=lstrlen(field[CurField].PosSignPrefix);
  288.         
  289.         RightSignLen=lstrlen(field[CurField].NegSignSuffix);
  290.         if (lstrlen(field[CurField].PosSignSuffix)>RightSignLen) RightSignLen=lstrlen(field[CurField].PosSignSuffix);
  291.  
  292.         CurrencySymLen=lstrlen(field[CurField].CurrencySymbol);
  293.  
  294.         //******************* insert the currency symbol ********************
  295.         if (CurrencySymLen>0) {
  296.            lPad(label,len+CurrencySymLen);
  297.            for (i=0;i<CurrencySymLen;i++) label[i]=field[CurField].CurrencySymbol[i];
  298.            len+=CurrencySymLen;
  299.         }
  300.  
  301.         //******************* insert the left prefix symbol ********************
  302.         if (LeftSignLen>0) {
  303.            lPad(label,len+LeftSignLen);
  304.            for (i=0;i<lstrlen(field[CurField].PosSignPrefix);i++) label[i]=field[CurField].PosSignPrefix[i];
  305.            len+=LeftSignLen;
  306.         }
  307.  
  308.         //******************* insert the right suffiex symbol ********************
  309.         if (RightSignLen>0) {
  310.            rPad(label,len+RightSignLen);
  311.            for (i=0;i<lstrlen(field[CurField].PosSignSuffix);i++) label[len+i]=field[CurField].PosSignSuffix[i];
  312.            len+=RightSignLen;
  313.         }
  314.  
  315.         // truncate the label to fit the label rectangle
  316.         if (DispWidth>0) {
  317.            len=strlen(label);
  318.            i=len-1;
  319.            while (DispWidth>0 && i>=0) {
  320.               DispWidth=DispWidth-FrFont[font].CharWidth[(BYTE)label[i]];
  321.               if (DispWidth<=0) break;
  322.               i--;
  323.            }
  324.            if (DispWidth<0 && i<len-1) i++;
  325.            if (i>0) {  // discard digits from the left
  326.               for (j=0;j<len-i;j++) label[j]=label[j+i];
  327.               label[j]=0;
  328.               if (j==0) lstrcpy(label,"9");     // minimum one character
  329.               if (label[0]==',') label[0]='9';
  330.            }
  331.         }
  332.     }
  333.     //**************** Format date fields ***********************************
  334.     else if (type==TYPE_DATE) {
  335.         lstrcpy(dd,"dd");
  336.         lstrcpy(mm,"mm");
  337.         lstrcpy(yy,"yyyy");
  338.  
  339.         label[0]=0;
  340.  
  341.         switch (field[CurField].DateFormat) {
  342.            case DT_MMDDYY:
  343.                lstrcat(label,mm);
  344.                lstrcat(label,field[CurField].DateDelim);
  345.                lstrcat(label,dd);
  346.                lstrcat(label,field[CurField].DateDelim);
  347.                lstrcat(label,&yy[2]);
  348.                break;
  349.            case DT_DDMMYY:
  350.                lstrcat(label,dd);
  351.                lstrcat(label,field[CurField].DateDelim);
  352.                lstrcat(label,mm);
  353.                lstrcat(label,field[CurField].DateDelim);
  354.                lstrcat(label,&yy[2]);
  355.                break;
  356.            case DT_MMDDYYYY:
  357.                lstrcat(label,mm);
  358.                lstrcat(label,field[CurField].DateDelim);
  359.                lstrcat(label,dd);
  360.                lstrcat(label,field[CurField].DateDelim);
  361.                lstrcat(label,yy);
  362.                break;
  363.            case DT_MMMDDYYYY:
  364.                lstrcat(label,"mmm dd,yyyy");
  365.                break;
  366.            default:
  367.                ;
  368.         }
  369.     }
  370.     //**************** Format the logical fields *****************************
  371.     else if (type==TYPE_LOGICAL) {
  372.         label[0]=field[CurField].LogicalSymbols[0];
  373.         label[1]=0;
  374.     }
  375.     //************ Create the dummy label for the picture type field
  376.     else if (type==TYPE_PICT) {             // picture label is not drawn
  377.         for (i=0;i<width;i++) label[i]='P'; // used only to calculate the
  378.         label[i]=0;                         // width of the initial rectangle
  379.     }
  380.  
  381.     return TRUE;
  382. }    
  383.  
  384. /******************************************************************************
  385.     ModifyField:
  386.     Modify the attributes of the current field.  This routine determines the
  387.     field type and calls the appropriate routines to modify the attribute of
  388.     that type.
  389. ******************************************************************************/
  390. ModifyField()
  391. {
  392.     int CurField;
  393.     int type;
  394.  
  395.     if (SelItem<0 || item[SelItem].type!=FIELD) return FALSE;
  396.  
  397.     CurField=item[SelItem].field;
  398.  
  399.     if (!field[CurField].AllowChanges) {
  400.        MessageBox(hFrWnd,"This field can not be modified!","Protected Field",MB_OK);
  401.        return TRUE;
  402.     }
  403.  
  404.     type=field[CurField].type;
  405.     if (type==TYPE_PICT) return TRUE;  // no attributes for the picture type field
  406.  
  407.     DlgIndex=CurField;           // pass the field number to the dialog box 
  408.     DlgSec=item[SelItem].section;
  409.  
  410.     if      (type==TYPE_NUM)     CallDialogBox("NumFieldParam", NumFieldParam,0L);
  411.     else if (type==TYPE_DBL)     CallDialogBox("NumFieldParam", NumFieldParam,0L); 
  412.     else if (type==TYPE_TEXT)    CallDialogBox("TextFieldParam",TextFieldParam,0L);  
  413.     else if (type==TYPE_DATE)    CallDialogBox("DateFieldParam",DateFieldParam,0L);   
  414.     else if (type==TYPE_LOGICAL) CallDialogBox("LogFieldParam", LogFieldParam,0L);    
  415.  
  416.     // recreate the field label
  417.     CreateFieldLabel(CurField,item[SelItem].label,item[SelItem].width,item[SelItem].font);  // create field label
  418.  
  419.     FrPaint();                   // repaint the screen
  420.  
  421.     return TRUE;
  422. }
  423.  
  424. /******************************************************************************
  425.    InitField:
  426.    Initialize a field
  427. ******************************************************************************/
  428. InitField(struct StrField huge *field)
  429. {
  430.    int i;
  431.  
  432.    // fillup the default field values 
  433.    field->source=SRC_APPL;                    // source of field data 
  434.    field->name[0]=0;                          // field name 
  435.    field->InUse=TRUE;
  436.    field->FileId=0;                           // used only by host application 
  437.    field->FieldId=0;                          // used only by host application 
  438.    field->type=TYPE_TEXT;                     // num/alpha etc 
  439.    field->SumType=SUM_NONE;                   // summary type: total,average etc 
  440.    field->SysIdx=-1;                          // index into the system field structure 
  441.    field->width=15;                           // width of the field 
  442.    field->AllowChanges=TRUE;                  // user can modify the following fields 
  443.    field->DecPlaces=0;                        // number of decimal places 
  444.    field->DateFormat=DT_MMDDYY;               // date format 
  445.    field->DateDelim[0]='/';                   // date delimiter character 
  446.    field->DateDelim[1]=0;
  447.    field->flags=FLAG_COMMA;
  448.    lstrcpy(field->CurrencySymbol,"");
  449.    field->LogicalSymbols[0]='Y';              // logical TRUE and FALSE symbols 
  450.    field->LogicalSymbols[1]='N';
  451.    lstrcpy(field->NegSignPrefix,"-");         // negative/positive sign prefix/suffix
  452.    field->NegSignSuffix[0]=0;
  453.    field->PosSignPrefix[0]=0;
  454.    field->PosSignSuffix[0]=0;
  455.    field->CalcExp[0]=END_OF_EXP;              // expression for calculated fields 
  456.    field->CharData=NULL;                      // character data, pointer to an object of size = field->width+1 
  457.    field->NumData=0;                          // numeric data 
  458.    field->DblData=0;                          // double data 
  459.    field->HoldNum=0;                          // long accumulater: total,minimum,maximum,etc...
  460.    field->HoldDbl=0;                          // double accumulater: total,minimum,maximum,etc...
  461.    field->count=0;                            // records per break 
  462.    field->misc=0;                             // miscellaneous field 
  463.    field->ParaChar[0]=DEF_PARA_BREAK;         // default para break character
  464.    field->ParaChar[1]=0;                      
  465.  
  466.    for (i=0;i<sizeof(field->reserved);i++) field->reserved[i]=0;
  467.  
  468.    return TRUE;
  469. }
  470.  
  471. /******************************************************************************
  472.     FindFieldSlot:
  473.     Find a slot for the new field.  If successful, the fuction returns the
  474.     index into the field array. Otherwise, it returns END_OF_EXP.
  475. ******************************************************************************/
  476. int FindFieldSlot()
  477. {
  478.     int FieldIndex=0;
  479.  
  480.     for (FieldIndex=0;FieldIndex<TotalFields;FieldIndex++) {
  481.        if (!(field[FieldIndex].InUse) && FieldIndex!=0 && FieldIndex!=32) return FieldIndex;
  482.     }
  483.     
  484.     if (TotalFields>=MAX_FIELDS) return END_OF_EXP;
  485.  
  486.     if (TotalFields==0 || TotalFields==32) {  // do not use field index 0 or 32 
  487.        InitField(&field[TotalFields]);
  488.        field[TotalFields].source=SRC_NONE;
  489.        field[TotalFields].InUse=FALSE;
  490.        TotalFields++;
  491.     }
  492.     
  493.     if (TotalFields>=MAX_FIELDS) return END_OF_EXP;
  494.  
  495.     InitField(&field[TotalFields]);
  496.     field[TotalFields].source=SRC_NONE;       // new field slot 
  497.     field[TotalFields].InUse=FALSE;
  498.     TotalFields++;
  499.  
  500.     return TotalFields-1;
  501. }
  502.  
  503. /******************************************************************************
  504.     DeleteField:
  505.     Mark a field as deleted.
  506. ******************************************************************************/
  507. void DeleteField(int FieldNo)
  508. {
  509.    int i;
  510.  
  511.    if (FieldNo>=MAX_FIELDS) return;
  512.    if (!field[FieldNo].InUse) return;         // field already deleted 
  513.  
  514.    if (field[FieldNo].source==SRC_CALC) {     // delete the referenced fields 
  515.        i=0;
  516.        while(field[FieldNo].CalcExp[i]!=END_OF_EXP) {
  517.           if (field[FieldNo].CalcExp[i]<MAX_FIELDS) DeleteField(field[FieldNo].CalcExp[i]);
  518.           i++;
  519.        }
  520.    }
  521.    
  522.    field[FieldNo].source=SRC_NONE;
  523.    field[FieldNo].InUse=FALSE;
  524.    FrModified=TRUE;
  525. }
  526.  
  527. /******************************************************************************
  528.     ReleaseSymbols:
  529.     Relase the field symbols used in the given expression.
  530. ******************************************************************************/
  531. ReleaseSymbols(int far *exp)
  532. {
  533.     int i=0;
  534.  
  535.     while(exp[i]!=END_OF_EXP) {               // delete the symbols for the previous expression 
  536.        if (exp[i]<MAX_FIELDS) DeleteField(exp[i]);
  537.        i++;
  538.     }
  539.     return TRUE;
  540. }
  541.  
  542. /******************************************************************************
  543.     GetCalcField:
  544.     Get Data for a new calculation field.
  545. ******************************************************************************/
  546. GetCalcField(struct StrField huge *CurField)
  547. {
  548.     
  549.     if (!CallDialogBox("FieldNameParam",FieldNameParam,0L)) return FALSE;
  550.     
  551.     lstrcpy(CurField->name,msg);      // the name returned in the 'msg' variable 
  552.  
  553.     return ModifyFieldExp(CurField); 
  554. }
  555.  
  556. /******************************************************************************
  557.     ModifyFieldExp:
  558.     Modify a field expression.
  559. ******************************************************************************/
  560. ModifyFieldExp(struct StrField huge *CurField)
  561. {
  562.     int NewExp[NAME_WIDTH+2];
  563.     int i,ExpType,ResultType;
  564.  
  565.     if (SelItem>=0 && item[SelItem].section>=SEC_FTR_LVL9) ExpType=EXP_FOOTER;
  566.     else                                                   ExpType=EXP_OTHER;
  567.     
  568.     if ((ResultType=ModifyExp(CurField->CalcExp,NewExp,CurField->name,ExpType))<0) return FALSE;
  569.  
  570.     CurField->type=ResultType;
  571.  
  572.     i=0;
  573.     while(NewExp[i]!=END_OF_EXP) {
  574.        CurField->CalcExp[i]=NewExp[i];
  575.        i++;
  576.     }
  577.     CurField->CalcExp[i]=NewExp[i];
  578.  
  579.     FrModified=TRUE;
  580.  
  581.     if (i==0) return FALSE;      // zero length expression 
  582.     else      return TRUE;
  583. }
  584.  
  585. /******************************************************************************
  586.     EditFieldExp:
  587.     Modify the expression for the current calculation field.
  588. ******************************************************************************/
  589. EditFieldExp()
  590. {
  591.     int CurField;
  592.  
  593.     if (SelItem<0 || item[SelItem].type!=FIELD) return FALSE;
  594.     CurField=item[SelItem].field;
  595.     if (field[CurField].source!=SRC_CALC) return FALSE;
  596.  
  597.     return ModifyFieldExp(&field[CurField]); 
  598. }
  599.  
  600. /******************************************************************************
  601.     CreateDlgField:
  602.     Create a dialog field.
  603. ******************************************************************************/
  604. CreateDlgField()
  605. {
  606.     int fld;
  607.  
  608.     for (fld=0;fld<MAX_DLGS;fld++) {    // find an empty slot 
  609.        if (!(DlgField[fld].InUse))  break;
  610.     }
  611.  
  612.     if (fld==MAX_DLGS) {
  613.        MessageBox(hFrWnd,"Dialog Field Table Full!",NULL,MB_OK);
  614.        return TRUE;
  615.     }
  616.  
  617.     //******************** Initialize field data **************************
  618.     DlgField[fld].InUse=FALSE;         // will be set to TRUE after accept name 
  619.     DlgField[fld].name[0]=0;           // will accept name sortly 
  620.     DlgField[fld].prompt[0]=0;         // prompt to get data from the user 
  621.     DlgField[fld].type=TYPE_TEXT;      // field type, see TYPE_ constants 
  622.     DlgField[fld].PromptOrder=fld;     // prompt order 
  623.     DlgField[fld].CharData[0]=0;       // character data 
  624.     DlgField[fld].NumData=0;           // numeric data 
  625.     DlgField[fld].DblData=0;           // double data 
  626.     DlgField[fld].x=0;                 // cooridinates of the dialog box (future use)
  627.     DlgField[fld].y=0;
  628.     DlgField[fld].width=20;            // width of the field box
  629.     DlgField[fld].ValExp[0]=END_OF_EXP;// validation expression (future use) 
  630.     
  631.     DlgIndex=fld;                      // pass the index to the dialog box 
  632.     if (!CallDialogBox("CreateDlgParam",CreateDlgParam,0L)) return FALSE;
  633.       
  634.     DlgField[fld].InUse=TRUE;
  635.     // set other default parameters 
  636.     strcpy(DlgField[fld].prompt,DlgField[fld].name);
  637.     if (DlgField[fld].type==TYPE_NUM || DlgField[fld].type==TYPE_DBL) 
  638.                                                DlgField[fld].width=12;
  639.     else if (DlgField[fld].type==TYPE_DATE)    DlgField[fld].width=8;
  640.     else if (DlgField[fld].type==TYPE_LOGICAL) DlgField[fld].width=3;
  641.     else if (DlgField[fld].type==TYPE_PICT)    DlgField[fld].width=10;
  642.  
  643.     return TRUE;
  644. }
  645.  
  646. /******************************************************************************
  647.     ModifyDlgField:
  648.     Modify parameters for a specified dialog field.
  649. ******************************************************************************/
  650. ModifyDlgField()
  651. {
  652.     int i,j;
  653.  
  654.     //****************** Accept a dialog field to modify *****************
  655.     j=0;
  656.     for (i=0;i<MAX_DLGS;i++) {
  657.        if (DlgField[i].InUse) {
  658.           j++;
  659.           break;
  660.        }
  661.     }
  662.     if (j==0) {
  663.        MessageBox(hFrWnd,"Dialog Field Table Empty!",NULL,MB_OK);
  664.        return FALSE;
  665.     }
  666.  
  667.     if ((DlgIndex=CallDialogBox("DlgParam",DlgParam,(DWORD)(LPSTR)"Select Dialog Field"))<0) return FALSE;
  668.  
  669.     CallDialogBox("ModifyDlgParam",ModifyDlgParam,0L);
  670.        
  671.     return TRUE;
  672. }
  673.  
  674. /******************************************************************************
  675.     DeleteDlgField:
  676.     Delete a dialog field. This routine ensures that the specified dialog
  677.     field to delete is not reference anywhere.
  678. ******************************************************************************/
  679. DeleteDlgField()
  680. {
  681.     int i,j,fld;
  682.     char string[100];
  683.  
  684.     //****************** Accept a dialog field to modify *****************
  685.     j=0;
  686.     for (i=0;i<MAX_DLGS;i++) {
  687.        if (DlgField[i].InUse) {
  688.           j++;
  689.           break;
  690.        }
  691.     }
  692.     if (j==0) {
  693.        MessageBox(hFrWnd,"Dialog Field Table Empty!",NULL,MB_OK);
  694.        return FALSE;
  695.     }
  696.  
  697.     if ((fld=CallDialogBox("DlgParam",DlgParam,(DWORD)(LPSTR)"Select Dialog Field"))<0) return FALSE;
  698.  
  699.     //******* Check the report selection criteria ****************
  700.     if (DlgFieldInUse(FormHdr.SelExp,fld)) {
  701.          MessageBox(hFrWnd,"Field in Use by Report Selection Expression!",NULL,MB_OK);
  702.          return FALSE;
  703.     }
  704.  
  705.     //******* Check the Section Print criteria ****************
  706.     for (i=0;i<MAX_SECTIONS;i++) {
  707.        if (!section[i].InUse) continue;
  708.  
  709.        if (DlgFieldInUse(section[i].SelExp,fld)) {
  710.             sprintf(string,"Field in Use by Criteria for Section: %s !",SectionName[i]);
  711.             MessageBox(hFrWnd,string,NULL,MB_OK);
  712.             return FALSE;
  713.        }
  714.     }
  715.  
  716.     //******* Check other dialog field definition ****************
  717.     for (i=0;i<MAX_DLGS;i++) {
  718.        if (i==fld) continue;     
  719.        if (!DlgField[i].InUse) continue;
  720.  
  721.        if (DlgFieldInUse(DlgField[i].ValExp,fld)) {
  722.             sprintf(string,"Field in Use by Dialog Field: %s !",DlgField[i].name);
  723.             MessageBox(hFrWnd,string,NULL,MB_OK);
  724.             return FALSE;
  725.        }
  726.     }
  727.  
  728.     //******* check the field table *****************************
  729.  
  730.     for (i=0;i<TotalFields;i++) {
  731.        if (!(field[i].InUse)) continue;
  732.  
  733.        if (field[i].source==SRC_DLG && field[i].SysIdx==fld) {
  734.           MessageBox(hFrWnd,"This Dialog Field is Being Used in the Layout, Can Not Delete",NULL,MB_OK);
  735.           return FALSE;
  736.        }
  737.        else if (field[i].source==SRC_CALC) {
  738.           if (DlgFieldInUse(field[i].CalcExp,fld)) {
  739.                sprintf(string,"Field in Use by %s !",field[i].name);
  740.                MessageBox(hFrWnd,string,NULL,MB_OK);
  741.                return FALSE;
  742.           }
  743.        }
  744.     }
  745.  
  746.     //***************** Delete the field **************************
  747.     ReleaseSymbols(DlgField[fld].ValExp);
  748.     DlgField[fld].InUse=FALSE;
  749.  
  750.     FrModified=TRUE;
  751.  
  752.     return TRUE;
  753. }
  754.  
  755. /******************************************************************************
  756.     DlgFieldInUse:
  757.     This routine scans the given expression to check if it uses a specified
  758.     dialog field.  The routine return TRUE or FALSE value.
  759. ******************************************************************************/
  760. DlgFieldInUse(int far *exp,int fld)
  761. {
  762.     int j;
  763.     int RefField;
  764.  
  765.     j=0;
  766.     while (exp[j]!=END_OF_EXP) {
  767.        RefField=exp[j];
  768.        if ( RefField<TotalFields 
  769.             && field[RefField].InUse
  770.             && field[RefField].source==SRC_DLG 
  771.             && field[RefField].SysIdx==fld) return TRUE;
  772.        j++;
  773.     }
  774.  
  775.     return FALSE;
  776. }
  777.  
  778.