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 >
Wrap
C/C++ Source or Header
|
1995-02-14
|
29KB
|
778 lines
/*==============================================================================
REP_FLD.C
Report Ease: Field functions.
ReportEase Plus
Sub Systems, Inc.
ReportEase Plus, Copyright (c) 1993, Sub Systems, Inc. All Rights Reserved.
159 Main Street, #8C, Stoneham, MA 02180
(617) 438-8901.
Software License Agreement (1993)
----------------------------------
This license agreement allows the purchaser the right to modify the
source code to incorporate in their application.
The target application must not be distributed as a standalone report writer
or a mail merge product.
Sub Systems, Inc. reserves the right to prosecute anybody found to be
making illegal copies of the executable software or compiling the source
code for the purpose of selling there after.
===============================================================================*/
#include "windows.h"
#if defined (_WIN32)
#if !defined(WIN32)
#define WIN32
#endif
#endif
#if !defined(WIN32)
#include "print.h"
#endif
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
#include "fcntl.h"
#include "io.h"
#include "sys\types.h"
#include "sys\stat.h"
#include "string.h"
#include "setjmp.h"
#include "rep.h"
#define PREFIX extern
#include "rep1.h"
/******************************************************************************
InsertDataField:
This routine calls the data field selection function in your application.
The selected data field is inserted at the current cursor position.
******************************************************************************/
InsertDataField()
{
struct StrField TempField;
// find empty TempField slot
if (END_OF_EXP==(NewField=FindFieldSlot())) {
MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
return FALSE;
}
// accept an application TempField from the user application
InitField(&TempField); // initialize the TempField variables
if (!(FormArg.UserSelection)(hFrWnd,&TempField,0)) return FALSE; // call a user routine to select a data TempField
// copy the TempField into the current array position
field[NewField]=TempField;
return TRUE;
}
/******************************************************************************
InsertCalcField:
This routine allows the user to create a calculation field.
The new calculation field is inserted at the current cursor position.
******************************************************************************/
InsertCalcField()
{
struct StrField TempField;
// find empty TempField slot
if (END_OF_EXP==(NewField=FindFieldSlot())) {
MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
return FALSE;
}
else {
field[NewField].InUse=TRUE; // reserve this slot
lstrcpy(field[NewField].name,"");// reset any old name name
}
InitField(&TempField); // initialize the TempField variables
TempField.source=SRC_CALC;
if (!GetCalcField(&TempField)) return FALSE;
// copy the TempField into the current array position
field[NewField]=TempField;
return TRUE;
}
/******************************************************************************
InsertSysField:
This routine calls the system field selection function in your application.
The selected data field is inserted at the current cursor position.
******************************************************************************/
InsertSysField()
{
int SystemFieldNo;
struct StrField TempField;
// find empty TempField slot
if (END_OF_EXP==(NewField=FindFieldSlot())) {
MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
return FALSE;
}
InitField(&TempField); // initialize the field variables
// accept a system field to insert
if ((SystemFieldNo=CallDialogBox("SysParam",SysParam,0L))<0) return FALSE;
TempField.source=SRC_SYS; // source of field data
lstrcpy(TempField.name,"SYS->");
lstrcat(TempField.name,SysField[SystemFieldNo].name);
TempField.type=SysField[SystemFieldNo].type; // num/alpha etc
TempField.SysIdx=SystemFieldNo; // index into the system field structure
TempField.width=SysField[SystemFieldNo].width;// width of the field
TempField.AllowChanges=TRUE; // user can modify the following fields
// copy the TempField into the current array position
field[NewField]=TempField;
return TRUE;
}
/******************************************************************************
InsertDlgField:
This routine calls the dialog field selection function in your application.
The selected data field is inserted at the current cursor position.
******************************************************************************/
InsertDlgField()
{
int i,j,DlgFieldNo;
struct StrField TempField;
//****************** Validate that dialog TempField table is not empty *****
j=0;
for (i=0;i<MAX_DLGS;i++) {
if (DlgField[i].InUse) {
j++;
break;
}
}
if (j==0) {
MessageBox(hFrWnd,"Dialog Field Table Empty!",NULL,MB_OK);
return FALSE;
}
// find empty TempField slot
if (END_OF_EXP==(NewField=FindFieldSlot())) {
MessageBox(hFrWnd,"Ran out of TempField table!",NULL,MB_OK);
return FALSE;
}
InitField(&TempField); // initialize the TempField variables
// accept a system TempField to insert
if ((DlgFieldNo=CallDialogBox("DlgParam",DlgParam,0L))<0) return FALSE;
// fillup the TempField structure
TempField.source=SRC_DLG; // source of TempField data
lstrcpy(TempField.name,"DLG->");
lstrcat(TempField.name,DlgField[DlgFieldNo].name);
TempField.type=DlgField[DlgFieldNo].type; // num/alpha etc
TempField.SysIdx=DlgFieldNo; // index into the dialog TempField structure
TempField.width=DlgField[DlgFieldNo].width;// width of the TempField
TempField.AllowChanges=TRUE; // user can modify the following TempFields
// copy the TempField into the current array position
field[NewField]=TempField;
return TRUE;
}
/******************************************************************************
CreateFieldLabel:
This routine creates a screen field label for the given field. The third
argument provides the width of the display rectangle within which the
label should fit. The last argument gives the font index used to print
the label.
******************************************************************************/
CreateFieldLabel(int CurField,LPSTR label,int DispWidth,int font)
{
int i,j,width,type,len,DecPlaces,digits,DecFound,temp;
int LeftSignLen,RightSignLen,CurrencySymLen;
char line[LINE_WIDTH+2],mm[3],dd[3],yy[5];
unsigned flags;
width=field[CurField].width;
type=field[CurField].type;
flags=field[CurField].flags;
DecPlaces=field[CurField].DecPlaces;
if (DispWidth>0) DispWidth-=(2*DESC_MARGIN); // adjust the display width of the field
//*************** Format Alpha Fields **********************************
if (type==TYPE_TEXT) {
for (i=0;i<LINE_WIDTH;i++) label[i]='x'; // default label character
label[i]=0;
if (flags&FLAG_CAPS) lstrupr(label);
else if (flags&FLAG_SMALL) lstrlwr(label);
else if (flags&FLAG_FIRST_CAP) {
lstrlwr(label);
label[0]=toupper(label[0]);
}
if (DispWidth==0) DispWidth=2*(DEF_RECT_WIDTH-DESC_MARGIN); // assume twice the default rectangle width
// find how many characters can fit this rectangle
if (field[CurField].source==SRC_CALC) width=LINE_WIDTH; // don't limit as we really don't know the width of calculation field
i=0;
while (DispWidth>0 && i<width && i<LINE_WIDTH) {
DispWidth=DispWidth-FrFont[font].CharWidth[label[i]];
i++;
}
if (DispWidth<0 && i>0) i--;
label[i]=0;
}
//**************** Format numeric fields ********************************
else if (type==TYPE_NUM || type==TYPE_DBL) {
len=width;
for (i=0;i<len;i++) label[i]='9'; // default numeric character
label[i]=0;
if (DecPlaces>0) { // insert a decimal
len=strlen(label);
if (DecPlaces>len) {
lPad(label,DecPlaces+1);
label[0]='.';
i=1;
while (label[i]==' ') {
label[i]='0';
i++;
}
}
else {
lPad(&label[len-DecPlaces],DecPlaces+1);
label[len-DecPlaces]='.';
}
}
//********************* insert comma characters *******************
if (flags&FLAG_COMMA) { // insert comma
len=strlen(label);
for (digits=0;digits<len;digits++) if (label[digits]=='.') break;
if (digits>0) {
strcpy(line,label);
j=0;
DecFound=FALSE;
for (i=0;i<len;i++,j++) {
if (DecFound) { // simply copy the remaining digits
label[j]=line[i];
}
else { // before decimal
if (line[i]=='.') {
label[j]=line[i];
DecFound=TRUE;
}
else { // do we need to insert comma
temp=digits/3;
if (digits==temp*3 && digits>0 && j>0) {// insert comma
label[j]=',';
j++;
}
label[j]=line[i];
digits--;
}
}
}
label[j]=0;
}
}
//******************* Apply numeric properties ************************
len=strlen(label);
LeftSignLen=lstrlen(field[CurField].NegSignPrefix);
if (lstrlen(field[CurField].PosSignPrefix)>LeftSignLen) LeftSignLen=lstrlen(field[CurField].PosSignPrefix);
RightSignLen=lstrlen(field[CurField].NegSignSuffix);
if (lstrlen(field[CurField].PosSignSuffix)>RightSignLen) RightSignLen=lstrlen(field[CurField].PosSignSuffix);
CurrencySymLen=lstrlen(field[CurField].CurrencySymbol);
//******************* insert the currency symbol ********************
if (CurrencySymLen>0) {
lPad(label,len+CurrencySymLen);
for (i=0;i<CurrencySymLen;i++) label[i]=field[CurField].CurrencySymbol[i];
len+=CurrencySymLen;
}
//******************* insert the left prefix symbol ********************
if (LeftSignLen>0) {
lPad(label,len+LeftSignLen);
for (i=0;i<lstrlen(field[CurField].PosSignPrefix);i++) label[i]=field[CurField].PosSignPrefix[i];
len+=LeftSignLen;
}
//******************* insert the right suffiex symbol ********************
if (RightSignLen>0) {
rPad(label,len+RightSignLen);
for (i=0;i<lstrlen(field[CurField].PosSignSuffix);i++) label[len+i]=field[CurField].PosSignSuffix[i];
len+=RightSignLen;
}
// truncate the label to fit the label rectangle
if (DispWidth>0) {
len=strlen(label);
i=len-1;
while (DispWidth>0 && i>=0) {
DispWidth=DispWidth-FrFont[font].CharWidth[(BYTE)label[i]];
if (DispWidth<=0) break;
i--;
}
if (DispWidth<0 && i<len-1) i++;
if (i>0) { // discard digits from the left
for (j=0;j<len-i;j++) label[j]=label[j+i];
label[j]=0;
if (j==0) lstrcpy(label,"9"); // minimum one character
if (label[0]==',') label[0]='9';
}
}
}
//**************** Format date fields ***********************************
else if (type==TYPE_DATE) {
lstrcpy(dd,"dd");
lstrcpy(mm,"mm");
lstrcpy(yy,"yyyy");
label[0]=0;
switch (field[CurField].DateFormat) {
case DT_MMDDYY:
lstrcat(label,mm);
lstrcat(label,field[CurField].DateDelim);
lstrcat(label,dd);
lstrcat(label,field[CurField].DateDelim);
lstrcat(label,&yy[2]);
break;
case DT_DDMMYY:
lstrcat(label,dd);
lstrcat(label,field[CurField].DateDelim);
lstrcat(label,mm);
lstrcat(label,field[CurField].DateDelim);
lstrcat(label,&yy[2]);
break;
case DT_MMDDYYYY:
lstrcat(label,mm);
lstrcat(label,field[CurField].DateDelim);
lstrcat(label,dd);
lstrcat(label,field[CurField].DateDelim);
lstrcat(label,yy);
break;
case DT_MMMDDYYYY:
lstrcat(label,"mmm dd,yyyy");
break;
default:
;
}
}
//**************** Format the logical fields *****************************
else if (type==TYPE_LOGICAL) {
label[0]=field[CurField].LogicalSymbols[0];
label[1]=0;
}
//************ Create the dummy label for the picture type field
else if (type==TYPE_PICT) { // picture label is not drawn
for (i=0;i<width;i++) label[i]='P'; // used only to calculate the
label[i]=0; // width of the initial rectangle
}
return TRUE;
}
/******************************************************************************
ModifyField:
Modify the attributes of the current field. This routine determines the
field type and calls the appropriate routines to modify the attribute of
that type.
******************************************************************************/
ModifyField()
{
int CurField;
int type;
if (SelItem<0 || item[SelItem].type!=FIELD) return FALSE;
CurField=item[SelItem].field;
if (!field[CurField].AllowChanges) {
MessageBox(hFrWnd,"This field can not be modified!","Protected Field",MB_OK);
return TRUE;
}
type=field[CurField].type;
if (type==TYPE_PICT) return TRUE; // no attributes for the picture type field
DlgIndex=CurField; // pass the field number to the dialog box
DlgSec=item[SelItem].section;
if (type==TYPE_NUM) CallDialogBox("NumFieldParam", NumFieldParam,0L);
else if (type==TYPE_DBL) CallDialogBox("NumFieldParam", NumFieldParam,0L);
else if (type==TYPE_TEXT) CallDialogBox("TextFieldParam",TextFieldParam,0L);
else if (type==TYPE_DATE) CallDialogBox("DateFieldParam",DateFieldParam,0L);
else if (type==TYPE_LOGICAL) CallDialogBox("LogFieldParam", LogFieldParam,0L);
// recreate the field label
CreateFieldLabel(CurField,item[SelItem].label,item[SelItem].width,item[SelItem].font); // create field label
FrPaint(); // repaint the screen
return TRUE;
}
/******************************************************************************
InitField:
Initialize a field
******************************************************************************/
InitField(struct StrField huge *field)
{
int i;
// fillup the default field values
field->source=SRC_APPL; // source of field data
field->name[0]=0; // field name
field->InUse=TRUE;
field->FileId=0; // used only by host application
field->FieldId=0; // used only by host application
field->type=TYPE_TEXT; // num/alpha etc
field->SumType=SUM_NONE; // summary type: total,average etc
field->SysIdx=-1; // index into the system field structure
field->width=15; // width of the field
field->AllowChanges=TRUE; // user can modify the following fields
field->DecPlaces=0; // number of decimal places
field->DateFormat=DT_MMDDYY; // date format
field->DateDelim[0]='/'; // date delimiter character
field->DateDelim[1]=0;
field->flags=FLAG_COMMA;
lstrcpy(field->CurrencySymbol,"");
field->LogicalSymbols[0]='Y'; // logical TRUE and FALSE symbols
field->LogicalSymbols[1]='N';
lstrcpy(field->NegSignPrefix,"-"); // negative/positive sign prefix/suffix
field->NegSignSuffix[0]=0;
field->PosSignPrefix[0]=0;
field->PosSignSuffix[0]=0;
field->CalcExp[0]=END_OF_EXP; // expression for calculated fields
field->CharData=NULL; // character data, pointer to an object of size = field->width+1
field->NumData=0; // numeric data
field->DblData=0; // double data
field->HoldNum=0; // long accumulater: total,minimum,maximum,etc...
field->HoldDbl=0; // double accumulater: total,minimum,maximum,etc...
field->count=0; // records per break
field->misc=0; // miscellaneous field
field->ParaChar[0]=DEF_PARA_BREAK; // default para break character
field->ParaChar[1]=0;
for (i=0;i<sizeof(field->reserved);i++) field->reserved[i]=0;
return TRUE;
}
/******************************************************************************
FindFieldSlot:
Find a slot for the new field. If successful, the fuction returns the
index into the field array. Otherwise, it returns END_OF_EXP.
******************************************************************************/
int FindFieldSlot()
{
int FieldIndex=0;
for (FieldIndex=0;FieldIndex<TotalFields;FieldIndex++) {
if (!(field[FieldIndex].InUse) && FieldIndex!=0 && FieldIndex!=32) return FieldIndex;
}
if (TotalFields>=MAX_FIELDS) return END_OF_EXP;
if (TotalFields==0 || TotalFields==32) { // do not use field index 0 or 32
InitField(&field[TotalFields]);
field[TotalFields].source=SRC_NONE;
field[TotalFields].InUse=FALSE;
TotalFields++;
}
if (TotalFields>=MAX_FIELDS) return END_OF_EXP;
InitField(&field[TotalFields]);
field[TotalFields].source=SRC_NONE; // new field slot
field[TotalFields].InUse=FALSE;
TotalFields++;
return TotalFields-1;
}
/******************************************************************************
DeleteField:
Mark a field as deleted.
******************************************************************************/
void DeleteField(int FieldNo)
{
int i;
if (FieldNo>=MAX_FIELDS) return;
if (!field[FieldNo].InUse) return; // field already deleted
if (field[FieldNo].source==SRC_CALC) { // delete the referenced fields
i=0;
while(field[FieldNo].CalcExp[i]!=END_OF_EXP) {
if (field[FieldNo].CalcExp[i]<MAX_FIELDS) DeleteField(field[FieldNo].CalcExp[i]);
i++;
}
}
field[FieldNo].source=SRC_NONE;
field[FieldNo].InUse=FALSE;
FrModified=TRUE;
}
/******************************************************************************
ReleaseSymbols:
Relase the field symbols used in the given expression.
******************************************************************************/
ReleaseSymbols(int far *exp)
{
int i=0;
while(exp[i]!=END_OF_EXP) { // delete the symbols for the previous expression
if (exp[i]<MAX_FIELDS) DeleteField(exp[i]);
i++;
}
return TRUE;
}
/******************************************************************************
GetCalcField:
Get Data for a new calculation field.
******************************************************************************/
GetCalcField(struct StrField huge *CurField)
{
if (!CallDialogBox("FieldNameParam",FieldNameParam,0L)) return FALSE;
lstrcpy(CurField->name,msg); // the name returned in the 'msg' variable
return ModifyFieldExp(CurField);
}
/******************************************************************************
ModifyFieldExp:
Modify a field expression.
******************************************************************************/
ModifyFieldExp(struct StrField huge *CurField)
{
int NewExp[NAME_WIDTH+2];
int i,ExpType,ResultType;
if (SelItem>=0 && item[SelItem].section>=SEC_FTR_LVL9) ExpType=EXP_FOOTER;
else ExpType=EXP_OTHER;
if ((ResultType=ModifyExp(CurField->CalcExp,NewExp,CurField->name,ExpType))<0) return FALSE;
CurField->type=ResultType;
i=0;
while(NewExp[i]!=END_OF_EXP) {
CurField->CalcExp[i]=NewExp[i];
i++;
}
CurField->CalcExp[i]=NewExp[i];
FrModified=TRUE;
if (i==0) return FALSE; // zero length expression
else return TRUE;
}
/******************************************************************************
EditFieldExp:
Modify the expression for the current calculation field.
******************************************************************************/
EditFieldExp()
{
int CurField;
if (SelItem<0 || item[SelItem].type!=FIELD) return FALSE;
CurField=item[SelItem].field;
if (field[CurField].source!=SRC_CALC) return FALSE;
return ModifyFieldExp(&field[CurField]);
}
/******************************************************************************
CreateDlgField:
Create a dialog field.
******************************************************************************/
CreateDlgField()
{
int fld;
for (fld=0;fld<MAX_DLGS;fld++) { // find an empty slot
if (!(DlgField[fld].InUse)) break;
}
if (fld==MAX_DLGS) {
MessageBox(hFrWnd,"Dialog Field Table Full!",NULL,MB_OK);
return TRUE;
}
//******************** Initialize field data **************************
DlgField[fld].InUse=FALSE; // will be set to TRUE after accept name
DlgField[fld].name[0]=0; // will accept name sortly
DlgField[fld].prompt[0]=0; // prompt to get data from the user
DlgField[fld].type=TYPE_TEXT; // field type, see TYPE_ constants
DlgField[fld].PromptOrder=fld; // prompt order
DlgField[fld].CharData[0]=0; // character data
DlgField[fld].NumData=0; // numeric data
DlgField[fld].DblData=0; // double data
DlgField[fld].x=0; // cooridinates of the dialog box (future use)
DlgField[fld].y=0;
DlgField[fld].width=20; // width of the field box
DlgField[fld].ValExp[0]=END_OF_EXP;// validation expression (future use)
DlgIndex=fld; // pass the index to the dialog box
if (!CallDialogBox("CreateDlgParam",CreateDlgParam,0L)) return FALSE;
DlgField[fld].InUse=TRUE;
// set other default parameters
strcpy(DlgField[fld].prompt,DlgField[fld].name);
if (DlgField[fld].type==TYPE_NUM || DlgField[fld].type==TYPE_DBL)
DlgField[fld].width=12;
else if (DlgField[fld].type==TYPE_DATE) DlgField[fld].width=8;
else if (DlgField[fld].type==TYPE_LOGICAL) DlgField[fld].width=3;
else if (DlgField[fld].type==TYPE_PICT) DlgField[fld].width=10;
return TRUE;
}
/******************************************************************************
ModifyDlgField:
Modify parameters for a specified dialog field.
******************************************************************************/
ModifyDlgField()
{
int i,j;
//****************** Accept a dialog field to modify *****************
j=0;
for (i=0;i<MAX_DLGS;i++) {
if (DlgField[i].InUse) {
j++;
break;
}
}
if (j==0) {
MessageBox(hFrWnd,"Dialog Field Table Empty!",NULL,MB_OK);
return FALSE;
}
if ((DlgIndex=CallDialogBox("DlgParam",DlgParam,(DWORD)(LPSTR)"Select Dialog Field"))<0) return FALSE;
CallDialogBox("ModifyDlgParam",ModifyDlgParam,0L);
return TRUE;
}
/******************************************************************************
DeleteDlgField:
Delete a dialog field. This routine ensures that the specified dialog
field to delete is not reference anywhere.
******************************************************************************/
DeleteDlgField()
{
int i,j,fld;
char string[100];
//****************** Accept a dialog field to modify *****************
j=0;
for (i=0;i<MAX_DLGS;i++) {
if (DlgField[i].InUse) {
j++;
break;
}
}
if (j==0) {
MessageBox(hFrWnd,"Dialog Field Table Empty!",NULL,MB_OK);
return FALSE;
}
if ((fld=CallDialogBox("DlgParam",DlgParam,(DWORD)(LPSTR)"Select Dialog Field"))<0) return FALSE;
//******* Check the report selection criteria ****************
if (DlgFieldInUse(FormHdr.SelExp,fld)) {
MessageBox(hFrWnd,"Field in Use by Report Selection Expression!",NULL,MB_OK);
return FALSE;
}
//******* Check the Section Print criteria ****************
for (i=0;i<MAX_SECTIONS;i++) {
if (!section[i].InUse) continue;
if (DlgFieldInUse(section[i].SelExp,fld)) {
sprintf(string,"Field in Use by Criteria for Section: %s !",SectionName[i]);
MessageBox(hFrWnd,string,NULL,MB_OK);
return FALSE;
}
}
//******* Check other dialog field definition ****************
for (i=0;i<MAX_DLGS;i++) {
if (i==fld) continue;
if (!DlgField[i].InUse) continue;
if (DlgFieldInUse(DlgField[i].ValExp,fld)) {
sprintf(string,"Field in Use by Dialog Field: %s !",DlgField[i].name);
MessageBox(hFrWnd,string,NULL,MB_OK);
return FALSE;
}
}
//******* check the field table *****************************
for (i=0;i<TotalFields;i++) {
if (!(field[i].InUse)) continue;
if (field[i].source==SRC_DLG && field[i].SysIdx==fld) {
MessageBox(hFrWnd,"This Dialog Field is Being Used in the Layout, Can Not Delete",NULL,MB_OK);
return FALSE;
}
else if (field[i].source==SRC_CALC) {
if (DlgFieldInUse(field[i].CalcExp,fld)) {
sprintf(string,"Field in Use by %s !",field[i].name);
MessageBox(hFrWnd,string,NULL,MB_OK);
return FALSE;
}
}
}
//***************** Delete the field **************************
ReleaseSymbols(DlgField[fld].ValExp);
DlgField[fld].InUse=FALSE;
FrModified=TRUE;
return TRUE;
}
/******************************************************************************
DlgFieldInUse:
This routine scans the given expression to check if it uses a specified
dialog field. The routine return TRUE or FALSE value.
******************************************************************************/
DlgFieldInUse(int far *exp,int fld)
{
int j;
int RefField;
j=0;
while (exp[j]!=END_OF_EXP) {
RefField=exp[j];
if ( RefField<TotalFields
&& field[RefField].InUse
&& field[RefField].source==SRC_DLG
&& field[RefField].SysIdx==fld) return TRUE;
j++;
}
return FALSE;
}