home *** CD-ROM | disk | FTP | other *** search
- /*==============================================================================
- REP_REP.C
- Report Ease: Report Executer Routines.
-
- 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 "dos.h"
- #include "math.h"
- #include "setjmp.h"
-
- #include "rep.h"
-
- #define PREFIX extern
- #include "rep1.h"
-
- extern BOOL ReportEaseActive; // TRUE when report ease has been called
-
- /******************************************************************************
- RepInit:
- This routine is called by the user application to initialize a report
- run. The parameters are passed using the StrRep structure.
- The routine returns a 0 value if the report is successfully initialized.
- Otherwise it returns an error code (see ERR_ in the rew.h file).
-
- This routine uses the input structure parameter (RepArg) to pass the
- field information to the application routine. It returns the pointer
- to two arrays:
-
- 1. field: Huge pointer to the field table. This table contains field information
- about each field used by the form. The elements of a field
- is defined using the StrField structure. Your application will need
- to fill in the field data before calling the RepRec routine.
-
- The number of fields in this table is given by the TotalFields variable
- within the StrRep structure.
-
- 2. SortField: Huge pointer to the sort field table. This table contains field information
- about each sort field used by the form. The elements of a field
- is defined using the StrField structure. Your application should
- sort the records as specified by these fields.
-
- The number of fields in this table is given by the TotalSortFields variable
- within the StrRep structure.
-
-
- *******************************************************************************/
- int WINAPI _export RepInit(struct StrRep far *ArgPtr)
- {
- LPSTR SaveCharPtr;
- int j,i,select,len,result,HorzWidth,PrtResX,PrtResY;
- int CompExp[NAME_WIDTH+2],LastSym,FieldIndex,fld,CurField;
- int SecItem,FirstY,LastY,WrapItem,LastItem,AdjX,AdjY;
- struct StrItem TempItem;
- POINT pt;
-
- // prepare to return an error code
- #if defined (WIN32)
- if (setjmp(FrAbort)==-1) return ErrorCode; // Fatal error return location
- #else
- if (Catch((LPCATCHBUF)&FrAbort)==-1) return ErrorCode; // Fatal error return location
- #endif
-
- // check if ReportEase alread active
- if (ReportEaseActive) {
- MessageBox(hFrParentWnd,"Report Ease Already Active!",NULL,MB_OK);
- return ERR_DUPLICATE;
- }
-
- SessionType='R'; // Report Run session
- ReportStage=IN_INIT; // in initialization
- RepArg=*ArgPtr; // store the argument pointer
-
- //****************** check if the input file exists ****************
- if (access(RepArg.file,6)==-1) {
- AbortFr("Form File Not Found!",ERR_NO_FILE);
- }
-
- //* Transfer the some input parameter variables to the global area *
- strcpy(FrFileName,ArgPtr->file); // current report file name
- FrShowHorBar=TRUE; // show horizontal scroll bar
- FrShowVerBar=TRUE; // show vertical scroll bar
-
- //hFrInst=ArgPtr->hInst; // uncomment for STATIC linking
- //hFrPrevInst=ArgPtr->hPrevInst; // uncomment for STATIC linking
-
- hFrWnd=NULL; // windows not opened yet
- hFrParentWnd=ArgPtr->hParentWnd; // Handle to the parent window
-
- //***************** Select the output device **********************
- if (ArgPtr->device=='A') { // ask user for the output device
- select=CallDialogBox("DeviceParam",DeviceParam,0);
- if (select<0) return ERR_NO_DEVICE;
- if (select==0) ArgPtr->device='S';
- else ArgPtr->device='P';
- }
-
- if (ArgPtr->device=='S') UseScreen=TRUE;
- else {
- UseScreen=FALSE;
- FrShowHorBar=FALSE; // show horizontal scroll bar
- FrShowVerBar=FALSE; // show vertical scroll bar
- }
-
- //***************** Other initialization and file input
- if (0!=(result=InitFr(RepArg.style,RepArg.x,RepArg.y,RepArg.width,RepArg.height))) return result;
- if (UseScreen) {
- FormHdr.RulerType=RULER_OFF; // turnoff the ruler
- GetWinDimension(); // recalculate the window dimensions
- }
-
- AllocRepMem(); // allocate/reallocate arrays
-
- //****************** accept the dialog fields ***************************
- if (!AcceptDlgField()) {
- ReportStatus=REP_ABORT; // user cancellation
- RepExit();
- return ERR_SUSPEND;
- }
-
- //****************** initialize the temporary fields ***************************
- for (i=0;i<MAX_TEMP_FIELDS;i++) {
- InitField(&TempField[i]);
- TempField[i].InUse=FALSE;
- }
-
- //***************** Stuff the sort fields *******************************
- for(i=0;i<TotalBreakFields;i++) { // allocate space for the character sort fields
- FieldIndex=BreakField[i].SortField; // index into the field table
- SaveCharPtr=SortField[i].CharData; // this field already allocated
- SortField[i]=field[FieldIndex];
- SortField[i].CharData=SaveCharPtr;
- }
-
- //***************** Assign the constant string and dialog fields **********
- for (fld=0;fld<TotalFields;fld++) {
- if (field[fld].type==TYPE_TEXT) field[fld].CharData[0]=0;// initialize
-
- if (field[fld].source==SRC_CONST) {
- if (field[fld].type==TYPE_TEXT) {
- lstrcpy(field[fld].CharData,&field[fld].name[1]); // exclude the initial quote
- len=lstrlen(field[fld].CharData);
- if (len>0) field[fld].CharData[len-1]=0; // exclude the ending quotes
- }
- }
- else if (field[fld].source==SRC_DLG) { // assign fields
- if (field[fld].type==TYPE_TEXT) {
- lstrcpy(field[fld].CharData,DlgField[field[fld].SysIdx].CharData);
- }
- else {
- field[fld].NumData=DlgField[field[fld].SysIdx].NumData;
- field[fld].DblData=DlgField[field[fld].SysIdx].DblData;
- }
- }
- }
-
- //***************** compile the report selection criteria ****************
- LastSym=CompileExp(FormHdr.SelExp,CompExp);// compile the expression
-
- if (LastSym!=END_OF_EXP) { // error encountered
- AbortFr("Invalid Report Selection Expression!",ERR_BAD_EXP);
- }
- i=0;
- while(CompExp[i]!=END_OF_EXP) { // transfer to the structure
- FormHdr.SelExp[i]=CompExp[i];
- i++;
- }
- FormHdr.SelExp[i]=CompExp[i];
-
- //***************** compile the field expressions *********************
- for (j=0;j<TotalFields;j++) {
- if (field[j].source==SRC_CALC) {
- LastSym=CompileExp(field[j].CalcExp,CompExp);// compile the expression
-
- if (LastSym!=END_OF_EXP) { // error encountered
- AbortFr("Invalid Field Calculation Expression!",ERR_BAD_EXP);
- }
- i=0;
- while(CompExp[i]!=END_OF_EXP) { // transfer to the structure
- field[j].CalcExp[i]=CompExp[i];
- i++;
- }
- field[j].CalcExp[i]=CompExp[i];
- }
- }
-
- //***************** compile the section selection expressions *********************
- for (j=0;j<MAX_SECTIONS;j++) {
- if (section[j].InUse) {
- LastSym=CompileExp(section[j].SelExp,CompExp);// compile the expression
-
- if (LastSym!=END_OF_EXP) { // error encountered
- AbortFr("Invalid Section Selection Expression!",ERR_BAD_EXP);
- }
- i=0;
- while(CompExp[i]!=END_OF_EXP) { // transfer to the structure
- section[j].SelExp[i]=CompExp[i];
- i++;
- }
- section[j].SelExp[i]=CompExp[i];
- }
- }
-
- //***************** Initialize the user fields ****************************
- for (fld=0;fld<TotalFields;fld++) {
- SaveCharPtr=UserField[fld].CharData; // this field already allocated
- UserField[fld]=field[fld];
- UserField[fld].CharData=SaveCharPtr;
- if (field[fld].type==TYPE_TEXT) lstrcpy(UserField[fld].CharData,field[fld].CharData);
- }
-
-
- //********************* initialize the section and section items ***********
- for (i=0;i<MAX_SECTIONS;i++) { // initialize the section pointers
- if (!section[i].InUse) continue;
-
- SecItem=section[i].ScrItem; // section position in the item table
- item[SecItem].y=item[SecItem].y+FormHdr.SecBannerHeight;
- item[SecItem].height=item[SecItem].height-FormHdr.SecBannerHeight;
- section[i].FirstItem=SecItem;
- section[i].ItemCount=1; // include the section item
-
- // calculate first and last Y position of items within the section
- FirstY=LastY=-1; // initialize
- for (j=section[i].FirstItem+1;j<TotalItems;j++) {
- if (item[j].section!=i) break; // next section begins
- section[i].ItemCount++;
-
- if (item[j].type==GROUP) continue; // ignore group items
- if (FirstY==-1) FirstY=item[j].y; // find the first item position
- else if (item[j].y<FirstY) FirstY=item[j].y;
-
- if (item[j].y+item[j].height>LastY) LastY=item[j].y+item[j].height;
-
- // initialize the field variables
- if (item[j].type==FIELD) {
- CurField=item[j].field;
- field[CurField].section=UserField[CurField].section=i;
- if (i<SEC_FTR_LVL9) field[CurField].SumType=UserField[CurField].SumType=SUM_NONE;
- }
- }
-
- // adjust the item Y positions within the section
- if (!(section[i].flags&SFLAG_TRIM_BEFORE)) FirstY=item[SecItem].y;
- if (!(section[i].flags&SFLAG_TRIM_AFTER)) LastY=item[SecItem].y+item[SecItem].height;
-
- if (FirstY==-1 || LastY==-1) {
- section[i].ItemCount=0;
- section[i].height=0;
- }
- else {
- section[i].height=LastY-FirstY;
- for (j=section[i].FirstItem;j<TotalItems;j++) {
- if (item[j].section!=i) break; // next section begins
- item[j].y-=FirstY; // position relative to the section beginning
- }
-
- // set the section item to begin at relative zero
- j=section[i].FirstItem;
- item[j].y=0; // set the section beginning to zero
- item[j].height=LastY-FirstY+1;
- }
-
- // move the wrap field at the last position
- if (i==SEC_DETAIL1 && section[i].ItemCount>0) {
- WrapItem=-1;
- LastItem=section[i].FirstItem+section[i].ItemCount-1;
- for (j=section[i].FirstItem;j<=LastItem;j++) {
- if (item[j].type==GROUP || item[j].type==SECTION) continue; // ignore group items
-
- if (WrapItem!=-1) { // check any item after the wrap item
- if (item[j].y>=item[WrapItem].y+item[WrapItem].height-DESC_MARGIN) WrapItem=-1; // discard this wrap item
- }
-
- if (item[j].type!=FIELD) continue;
- CurField=item[j].field;
- if (field[CurField].type==TYPE_TEXT
- && field[CurField].flags&(FLAG_WRAP|FLAG_WORD_WRAP)) WrapItem=j;
- }
- if (WrapItem!=-1 && WrapItem!=LastItem) { // reloate the wrap item
- HugeMove(&(item[WrapItem]),&TempItem,sizeof(struct StrItem));
- HugeMove(&(item[LastItem]),&(item[WrapItem]),sizeof(struct StrItem));
- HugeMove(&TempItem,&(item[LastItem]),sizeof(struct StrItem));
- WrapItem=LastItem;
- }
- LastWrapItem=WrapItem;
- }
-
- }
-
-
- //***************** other initialization **********************************
- GetSystemDateTime(); // get the system date and time
-
- // initialize month array
- MonthName[0]="Jan";MonthName[1]="Feb";MonthName[2]="Mar";
- MonthName[3]="Apr";MonthName[4]="May";MonthName[5]="Jun";
- MonthName[6]="Jul";MonthName[7]="Aug";MonthName[8]="Sep";
- MonthName[9]="Oct";MonthName[10]="Nov";MonthName[11]="Dec";
-
- RecCount=0; // First rec to be read by the application
- PageCount=1; // first page
- ScrPage=0; // screen page being displayed
- CurX=0; // current displacement toward x direction
- CurHeight=0; // current Y displacement
- CurCol=0; // current column for multiple column sections
- TrialMode=FALSE; // trial mode prints trial records
- hMetaFile=NULL; // current screen page in memory meta file
- PageAdvanced=FALSE; // set after page is advanced
- AdvancingPage=FALSE; // set during page advance
- ReportStatus=REP_RESUMED;
-
- //*************** initialize the page variables *******************
- LeftMargin=(int)((FormHdr.LeftMargin)*UNITS_PER_INCH); // margins logical in units
- RightMargin=(int)((FormHdr.RightMargin)*UNITS_PER_INCH);
- TopMargin=(int)((FormHdr.TopMargin)*UNITS_PER_INCH);
- BottomMargin=(int)((FormHdr.BottomMargin)*UNITS_PER_INCH);
-
- PrintWidth=(int)(PrintWidthInches*UNITS_PER_INCH); // width of the printed area
-
- // adjust left and top margin for the hidden areas
- Escape(hPrtDC,GETPRINTINGOFFSET,0,NULL,&pt); // actual offset where printing begins
- PrtResX=GetDeviceCaps(hPrtDC,LOGPIXELSX); // number of pixels per inch of X direction
- PrtResY=GetDeviceCaps(hPrtDC,LOGPIXELSY); // number of pixels per inch of Y direction
- AdjX=MulDiv(pt.x,UNITS_PER_INCH,PrtResX); // printing area begin position
- AdjY=MulDiv(pt.y,UNITS_PER_INCH,PrtResY);
-
- LeftMargin-=AdjX; // margin relative to printing area
- TopMargin-=AdjY;
- for (i=0;i<TotalItems;i++) item[i].x-=AdjX; // x relative to printing area
-
- PageHeight=(int)(PrintHeightInches*UNITS_PER_INCH)+TopMargin; // height of the printed page
- if (section[SEC_FTR_PAGE].InUse) PrintHeight=PageHeight-section[SEC_FTR_PAGE].height;
- else PrintHeight=PageHeight;
-
- if (PrintHeight<=0) {
- MessageBox(hFrWnd,"Page Too Small!",NULL,MB_OK);
- return ERR_PRINTER;
- }
-
-
- //******************** set additional window characteristics ****************
- if (UseScreen) {
- //******************** set the left margin on the screen ****************
- FrWinOrgX=FrWinOrgY=0;
- FrSetViewWindow(); // set the logical window origin
-
- //******************* set scroll bars **********************************
- HorzWidth=PrintWidth-FrWinWidth;
- if (HorzWidth>0) {
- HorScrollPos=HOR_SCROLL_MIN+(int)((long)FrWinOrgX*(HOR_SCROLL_MAX-HOR_SCROLL_MIN)/HorzWidth);
- if (HorScrollPos>HOR_SCROLL_MAX) HorScrollPos=HOR_SCROLL_MAX;
- SetScrollPos(hFrWnd,SB_HORZ,HorScrollPos,TRUE);
- }
- SetScrollPos(hFrWnd,SB_VERT,VER_SCROLL_MIN,TRUE);
-
- //****************** Create a new meta file **********************
- if (NULL==(hMetaDC=CreateMetaFile(NULL))) AbortFr("Error creating metafile",ERR_NO_FILE);
- ShowScrRepStatus(); // show screen reporting status
- RepInitMenu(hFrMenu); // initialize the menu bar
- }
-
- //***************** Initialize the system fields ****************************
- for (fld=0;fld<TotalFields;fld++) {
- if (field[fld].source==SRC_SYS) {
- StuffSysField(&field[fld]);
- StuffSysField(&UserField[fld]);
- }
- }
-
- //***************** stuff the return fields*******************************
- RepArg.field=UserField; // field to be filled by the user application
- RepArg.TotalFields=TotalFields;
- RepArg.SortField=SortField;
- RepArg.TotalSortFields=TotalBreakFields;
- lstrcpy(RepArg.DataSetName,FormHdr.DataSetName);
-
- (*ArgPtr)=RepArg; // return the updated structure
-
- return 0;
- }
-
- /******************************************************************************
- RepRec:
- This routine is called by the user application to print each record.
- The field data for the record must be passed using the 'field' array
- as returned by the RepInit routine.
-
- Your application should fill in the data for only the fields of SOURCE
- type equal to SCR_APPL. The data in other fields must not be modified in
- any way.
-
- Only the following elements in the field structure can be used to pass data:
-
- CharData (char far *) to pass the character string data.
- The character data being copied to the CharData pointer
- should not be larger than the 'width' as specified in
- the field structure. This variable (width) holds the character
- field width as specified by your application during the
- form edit process.
-
- NumData (long) to pass numeric, logical and date data.
- (date should be passed either as YYMMDD or YYYYMMDD format).
-
- DblData (double) to pass float numeric data.
-
- No other element of field structure should be modified.
- *******************************************************************************/
- int WINAPI _export RepRec()
- {
- int sec,BreakSort;
- struct StrField TempField,huge *SaveField=NULL;
- int LastSym;
- int fld;
-
- // prepare to return an error code
- #if defined (WIN32)
- if (setjmp(FrAbort)==-1) { // Fatal error return location
- #else
- if (Catch((LPCATCHBUF)&FrAbort)==-1) { // Fatal error return location
- #endif
- if (SaveField!=NULL) {
- field=SaveField;
- SaveField=NULL;
- }
- return ErrorCode;
- }
-
- ReportStage=IN_RECORDS; // processing records
-
- //******************** Apply record selection criteria ******************
- EvaluateSystemFields(); // update system fields
-
- if (FormHdr.SelExp[0]!=END_OF_EXP) {
- SaveField=field; // activate user fields
- field=UserField;
-
- LastSym=RunExp(FormHdr.SelExp,&TempField,TRUE); // run the expression and return the output in the field
-
- field=SaveField; // activate the original field
- SaveField=NULL;
-
- if (LastSym!=END_OF_EXP || TempField.type!=TYPE_LOGICAL) { // error encountered
- MessageBox(hFrWnd,"Error In Record Filter",NULL,MB_OK);
- return ERR_BAD_EXP;
- }
- if (!(TempField.NumData)) return 0;// record not selected
- }
-
- //************ calculate the break fields *********
- SaveField=field; // activate user fields
- field=UserField;
- CalculateBreakFields();
- field=SaveField; // activate the original field
- SaveField=NULL;
-
-
- //******************** Initialize for the first record *******************
- if (RecCount==0) InitFirstRec();
-
- //************************ Check for sort breaks ***********************
- BreakSort=PrintSortFooters();
-
- //**************** copy the user field to the global field ***************
- for (fld=0;fld<TotalFields;fld++) {
- if (field[fld].type==TYPE_TEXT) lstrcpy(field[fld].CharData,UserField[fld].CharData);
- else if (field[fld].type==TYPE_DBL) field[fld].DblData=UserField[fld].DblData;
- else field[fld].NumData=UserField[fld].NumData;
- }
-
- //******************* Evaluate the calculation fields ******************
- CalculateFields(0,MAX_SECTIONS-1); // calculate all fields for all section
-
- //************************* Print sort headers **************************
- PrintSortHeaders(BreakSort);
-
- //************************* Print the detail sections **********************
- for (sec=SEC_DETAIL1;sec<=SEC_DETAIL9;sec++) PrintSection(sec);
-
- //************************* Do totals ************************************
- for (fld=0;fld<TotalFields;fld++) {
- field[fld].count++;
-
- if (field[fld].SumType==SUM_MAX) {
- if (field[fld].DblData>field[fld].HoldDbl) field[fld].HoldDbl=field[fld].DblData;
- if (field[fld].NumData>field[fld].HoldNum) field[fld].HoldNum=field[fld].NumData;
- }
- else if (field[fld].SumType==SUM_MIN) {
- if (field[fld].DblData<field[fld].HoldDbl) field[fld].HoldDbl=field[fld].DblData;
- if (field[fld].NumData<field[fld].HoldNum) field[fld].HoldNum=field[fld].NumData;
- }
- else {
- field[fld].HoldDbl+=field[fld].DblData;
- field[fld].HoldNum+=field[fld].NumData;
- }
-
- }
-
- if (UseScreen) {
- // show progress
- if ( (RecCount<50 && RecCount%5==0) || RecCount%10==0) ShowScrRepStatus(); // show print progress
- ProcessUserCommands(); // process any pending messages
- }
-
- RecCount++; // increment number of records printed
-
- return 0;
- }
-
- /*****************************************************************************
- RepExit:
- *****************************************************************************/
- int WINAPI _export RepExit()
- {
- int CurSort,CurSec,FooterSec;
-
- // prepare to return an error code
- #if defined (WIN32)
- if (setjmp(FrAbort)==-1) return ErrorCode; // Fatal error return location
- #else
- if (Catch((LPCATCHBUF)&FrAbort)==-1) return ErrorCode; // Fatal error return location
- #endif
-
- if (ReportStatus!=REP_ABORT && RecCount>0) {
- ReportStage=IN_TOTALS; // printing totals
-
- //******************** calculate the footer fields ********************
- CalculateFields(SEC_FTR_LVL9,SEC_FTR_REP);
-
- //******************** print sort footers ******************************
- for (CurSort=(TotalBreakFields-1);CurSort>=0;CurSort--) {
- CurSec=BreakField[CurSort].section;
- FooterSec=SEC_FTR_LVL1-(CurSec-SEC_HDR_LVL1);
- PrintSection(FooterSec); // print section footer
- }
-
- PrintSection(SEC_FTR_REP); // print the report footers
-
- CurHeight=PrintHeight; // print last page footer
- PageAdvanced=AdvancingPage=TRUE;
- PrintSection(SEC_FTR_PAGE);
- }
-
- if (ReportStatus!=REP_ABORT) {
- if (UseScreen) {
- ReportStage=IN_EXIT;
- TransferMetaFile(); // transfer the last metafile page to disk
- RepInitMenu(hFrMenu); // redisplay the menu
- PaintRepScr(); // show screen
- }
- else {
- ReportStage=IN_EXIT;
- Escape(hFrDC,NEWFRAME,0,0L,0L);
- }
- }
-
- if (UseScreen && ReportStatus!=REP_ABORT)
- return 0; // do cleanup later
- else return RepCleanup(); // do cleanup now
- }
-
- /*****************************************************************************
- RepCleanup:
- Release the report resources
- *****************************************************************************/
- int RepCleanup()
- {
- int i;
- char string[85];
- int fld;
- HMETAFILE hMeta;
-
- //******* release printer window resources *********
- if (!UseScreen) {
- if (RecCount>0) {
- PrintProc(hFrDC,0); // show the last status
- Escape(hFrDC,ENDDOC,0,0L,0L); // end of print job
- if (hFrWnd) EnableWindow(hFrWnd,TRUE); // activate the parent window
- DestroyWindow(hAbortWnd); // destroy the abort window
- FreeProcInstance(lpProc); // free the process instances
- FreeProcInstance(lpAbortDlg);
- }
- if (ReportStatus!=REP_ABORT) {
- wsprintf(string,"%ld Record(s) Printed",RecCount);
- MessageBox(hFrWnd,string,"Report Over",MB_ICONSTOP);
- }
- }
-
- //*********************** Do cleanup ***********************************
- // free up space taken by the character fields
- for(fld=0;fld<TotalFields;fld++) { // allocate space for the character fields
- if (field[fld].type==TYPE_TEXT && field[fld].CharData!=NULL) OurFree(field[fld].CharData);
- if (UserField[fld].type==TYPE_TEXT && UserField[fld].CharData!=NULL) OurFree(UserField[fld].CharData);
- }
-
- for(i=0;i<TotalBreakFields;i++) { // allocate space for the character fields
- if (SortField[i].type==TYPE_TEXT) OurFree(SortField[i].CharData);
- }
-
- //*********** free up addtional global memory blocks ****
- GlobalUnlock(hSortField);
- GlobalFree(hSortField);
-
- GlobalUnlock(hUserField);
- GlobalFree(hUserField);
-
- //*********** free up screen arrays *******************************
- if (UseScreen) {
- GlobalUnlock(hPageLoc);
- GlobalFree(hPageLoc);
-
- OurFree(FileBuf); // free the file buffer
-
- // close the last metafile device context and delete the memory metafile
- if (hMetaDC && NULL!=(hMeta=CloseMetaFile(hMetaDC))) DeleteMetaFile(hMeta);
-
- unlink(MetaFile); // delete meta files
- unlink(TempMetaFile); // delete temporary meta file
- unlink(ScrMetaFile); // delete screen meta file
- unlink(PrtMetaFile); // delete selective print file
- }
-
- FrModified=FALSE;
- CloseFr();
-
- return 0;
- }
-
- /******************************************************************************
- PrintSortFooters:
- Check if sort break has taken places. If so, write the old sort footers.
- *******************************************************************************/
- PrintSortFooters()
- {
- int CurSort,CurSec,BreakSort,FooterSec;
- int CurField;
-
-
- for (CurSort=0;CurSort<TotalBreakFields;CurSort++) {
- CurField=BreakField[CurSort].CompField;
-
- if (field[CurField].type==TYPE_TEXT &&
- lstrcmp(UserField[CurField].CharData,field[CurField].CharData)!=0) break;
- else if (field[CurField].type==TYPE_DBL &&
- UserField[CurField].DblData!=field[CurField].DblData) break;
- else if (UserField[CurField].NumData!=field[CurField].NumData) break;
- }
-
- if (CurSort==TotalBreakFields) return CurSort; // no sort breaks
-
-
- BreakSort=CurSort;
-
- //******************** calculate the footer fields ********************
- CalculateFields(SEC_FTR_LVL9,SEC_FTR_REP);
-
- //***************** write sort section footers ************************
- for (CurSort=(TotalBreakFields-1);CurSort>=BreakSort;CurSort--) {
- CurSec=BreakField[CurSort].section;
- FooterSec=SEC_FTR_LVL1-(CurSec-SEC_HDR_LVL1);
- PrintSection(FooterSec); // print section footer
- }
-
- return BreakSort;
- }
-
- /******************************************************************************
- PrintSortHeaders:
- This routine prints sort headers for all levels below the specified level.
- *******************************************************************************/
- PrintSortHeaders(int BreakSort)
- {
- int CurSort,CurSec,FooterSec;
- int fld;
-
- if (BreakSort>=TotalBreakFields) return TRUE; // no sort breaks
-
- //***************** write sort section headers ***************************
- for (CurSort=BreakSort;CurSort<TotalBreakFields;CurSort++) {
- CurSec=BreakField[CurSort].section;
- PrintSection(CurSec); // print section headers
-
- FooterSec=SEC_FTR_LVL1-(CurSec-SEC_HDR_LVL1);
-
- for(fld=0;fld<TotalFields;fld++) { // clear accumulaters
- if (field[fld].InUse && field[fld].section==FooterSec) {
- if (!(FLAG_RETAIN&field[fld].flags)) {
- field[fld].HoldNum=0;
- field[fld].HoldDbl=0;
- field[fld].count=0;
- if (field[fld].SumType==SUM_MIN || field[fld].SumType==SUM_MAX) {
- field[fld].HoldNum=field[fld].NumData;
- field[fld].HoldDbl=field[fld].DblData;
- }
- }
- }
- }
- }
-
- return TRUE;
- }
-
- /*****************************************************************************
- EvaluateSystemFields:
- Evaludate system fields
- *****************************************************************************/
- EvaluateSystemFields()
- {
- int fld;
-
- // evaluate system fields ********
- for (fld=0;fld<TotalFields;fld++) {
- if (field[fld].source==SRC_SYS) {
- StuffSysField(&UserField[fld]);
- }
- }
- return TRUE;
- }
-
- /*****************************************************************************
- CalculateFields:
- Do calculation and assin systems fields
- *****************************************************************************/
- CalculateFields(int FirstSec,int LastSec)
- {
- int fld,LastSym;
- struct StrField TempField;
-
-
- // evaluate calculated fields ****
- for (fld=0;fld<TotalFields;fld++) {
- if (field[fld].source==SRC_CALC && field[fld].section>=FirstSec && field[fld].section<=LastSec) {
-
- LastSym=RunExp(field[fld].CalcExp,&TempField,TRUE); // run the expression and return the output in the field
- if (LastSym!=END_OF_EXP) { // error encountered
- wsprintf(msg,"Error In Calculation Field: %s",(LPSTR)(field[fld].name));
- AbortFr(msg,ERR_BAD_EXP);
- }
-
- if (field[fld].type==TYPE_TEXT && field[fld].CharData!=NULL) {
- OurFree(field[fld].CharData);
- field[fld].CharData=NULL;
- }
-
- if (TempField.type==TYPE_TEXT) field[fld].CharData=TempField.CharData;
- else if (TempField.type==TYPE_DBL) field[fld].DblData=TempField.DblData;
- else field[fld].NumData=TempField.NumData;
- }
- }
-
- return TRUE;
- }
-
- /*****************************************************************************
- CalculateSecExp:
- Calculate the section selection expression.
- *****************************************************************************/
- CalculateSecExp(int CurSec)
- {
- int LastSym;
- struct StrField TempField;
-
- if (section[CurSec].InUse) {
- if (section[CurSec].SelExp[0]==END_OF_EXP) section[CurSec].selected=TRUE;
- else {
- LastSym=RunExp(section[CurSec].SelExp,&TempField,TRUE); // run the expression and return the output in the field
- if (LastSym!=END_OF_EXP) { // error encountered
- AbortFr("Error In Section Filter",ERR_BAD_EXP);
- }
- section[CurSec].selected=(int)TempField.NumData;
- }
- }
- else section[CurSec].selected=FALSE;
-
- return section[CurSec].selected;
- }
-
- /*****************************************************************************
- CalculateBreakFields:
- Calculation fields used for break comparison
- *****************************************************************************/
- CalculateBreakFields()
- {
- int fld,LastSym;
- struct StrField TempField;
- int i;
-
- for (i=0;i<TotalBreakFields;i++) {
- fld=BreakField[i].CompField;
- if (field[fld].source==SRC_CALC) {
- LastSym=RunExp(field[fld].CalcExp,&TempField,TRUE); // run the expression and return the output in the field
- if (LastSym!=END_OF_EXP) { // error encountered
- wsprintf(msg,"Error In Break Calculation Field: %s",(LPSTR)(field[fld].name));
- AbortFr(msg,ERR_BAD_EXP);
- }
-
- if (field[fld].type==TYPE_TEXT && field[fld].CharData!=NULL) {
- OurFree(field[fld].CharData);
- field[fld].CharData=NULL;
- }
-
- if (TempField.type==TYPE_TEXT) field[fld].CharData=TempField.CharData;
- else if (TempField.type==TYPE_DBL) field[fld].DblData=TempField.DblData;
- else field[fld].NumData=TempField.NumData;
- }
- }
-
- return TRUE;
- }
-
- /*****************************************************************************
- InitFirstRec:
- Do initialization for the first record.
- *****************************************************************************/
- InitFirstRec()
- {
- int i,CurSec;
- int fld;
-
- //***************** copy from user fields ***************************
- for (fld=0;fld<TotalFields;fld++) {
- if (field[fld].type==TYPE_TEXT) lstrcpy(field[fld].CharData,UserField[fld].CharData);
- else if (field[fld].type==TYPE_DBL) field[fld].DblData=UserField[fld].DblData;
- else field[fld].NumData=UserField[fld].NumData;
- }
-
- CalculateFields(0,MAX_SECTIONS-1); // do calculation for the first record
-
- //***************** initialize the output device ***************************
- ReportStatus=REP_RESUMED; // report in progress
- if (UseScreen) { // show the blank screen
- RepInitMenu(hFrMenu); // initialize the menu items
- CurHeight=TopMargin;
- }
- else {
- lpAbortDlg = MakeProcInstance((FARPROC)PrintAbortParam, hFrInst);
- hAbortWnd=CreateDialog(hFrInst,"PrintAbortParam",hFrWnd,(DLGPROC)lpAbortDlg);
- ShowWindow(hAbortWnd,SW_NORMAL);
-
- lpProc = MakeProcInstance((FARPROC)PrintProc, hFrInst);
- SetAbortProc(hFrDC,(ABORTPROC)lpProc);
-
- if (Escape(hFrDC,STARTDOC,strlen(FormHdr.name),FormHdr.name,NULL)<0) {
- AbortFr("Unable to Start the Print Job",ERR_PRINTER);
- }
-
- UpdateWindow(hAbortWnd);
- if (hFrWnd) EnableWindow(hFrWnd,FALSE); // disable the main window
-
- FrWinWidth=PrintWidth+LeftMargin+RightMargin; // to enable use of display routines for printing
-
- }
-
- CurHeight=TopMargin; // start printing from the top page
-
- if (RFLAG_TRIAL&FormHdr.flags && !UseScreen) PrintTrial(); // print trial run
-
- PageAdvanced=TRUE; // suppress page advance
- PrintSection(SEC_HDR_PAGE); // print page header
-
- PageAdvanced=TRUE; // suppress page advance
- PrintSection(SEC_HDR_REP); // print the report header
-
- for (i=0;i<TotalBreakFields;i++) { // print group headers
- CurSec=BreakField[i].section;
- PageAdvanced=TRUE; // suppress page advance
- PrintSection(CurSec);
- }
-
- PageAdvanced=TRUE;
-
- return TRUE;
- }
-
- /*****************************************************************************
- PrintSection:
- This routine prints lines for a specified section. The routine will
- apply the current record data to the fields found in the section.
- *****************************************************************************/
- PrintSection(int CurSec)
- {
- int FromItem,ToItem,CurItem;
-
- if (!(section[CurSec].InUse)) return FALSE; // this section not used
- if (!(CalculateSecExp(CurSec))) return FALSE; // this section not selected
-
- FromItem=section[CurSec].FirstItem;
- ToItem=FromItem+section[CurSec].ItemCount-1;
-
- if (ToItem<FromItem) return FALSE;
-
- // force to first column when not in the first detail section
- if (CurSec!=SEC_DETAIL1 && CurCol!=0) {
- CurCol=0;
- CurHeight=LastY; // update the current y location
- }
-
- // Check for page advance
- if (CurCol==0) {
- if (SFLAG_PAGE_BEF&(section[CurSec].flags)) AdvancePage(CurSec);
- else if (CurHeight+section[CurSec].height>PrintHeight) AdvancePage(CurSec);
- LastY=CurHeight; // track last Y position used for printing
- }
- CurX=CurCol*(item[section[CurSec].ScrItem].width); // x displacement
-
- // clear the height adjusment field
- for (CurItem=FromItem;CurItem<=ToItem;CurItem++) item[CurItem].HeightAdj=0;
-
- // Print each item
- for (CurItem=FromItem;CurItem<=ToItem;CurItem++) { // process each line
- if (item[CurItem].type==GROUP) continue;
- if (item[CurItem].section!=CurSec) continue;
-
- if (UseScreen) PrintItem(hMetaDC,CurItem);
- else PrintItem(hFrDC,CurItem);
-
- PageAdvanced=FALSE; // new page is dirtied now
- }
-
- // Update printed page height and horizontal column position
- if (CurSec==SEC_DETAIL1) {
- CurCol++;
- if (CurCol>=section[CurSec].columns) {
- if (SFLAG_TRIM_AFTER&(section[CurSec].flags)) CurHeight=LastY;
- else CurHeight+=section[CurSec].height;
- if (CurHeight<LastY) CurHeight=LastY;
-
- CurCol=0;
- if (section[CurSec].columns==1 && SFLAG_PAGE_AFT&(section[CurSec].flags)) CurHeight=PrintHeight+1; // force page break for the next section
- }
- }
- else {
- if (SFLAG_TRIM_AFTER&(section[CurSec].flags)) CurHeight=LastY;
- else CurHeight+=section[CurSec].height;
- if (CurHeight<LastY) CurHeight=LastY;
-
- if (SFLAG_PAGE_AFT&(section[CurSec].flags)) AdvancePage(MAX_SECTIONS);
- CurCol=0; // other sections are single column
- }
-
- return TRUE;
- }
-
- /*****************************************************************************
- PrintItem:
- Print the specified item at the specified device context. The item is
- printed relative to the current Y position
- *****************************************************************************/
- PrintItem(HDC hDC,int CurItem)
- {
-
- RECT rect;
- HPEN hPen;
- HBRUSH hBrush;
-
- // build the rectangle
- rect.left=item[CurItem].x+CurX;
- rect.right=item[CurItem].x+CurX+item[CurItem].width;
- rect.top=CurHeight+item[CurItem].y+item[CurItem].HeightAdj;
- rect.bottom=rect.top+item[CurItem].height;
-
- // fill rectangle if needed
- if (item[CurItem].flags&OFLAG_FILL) { // fill rectangle
- if (NULL!=(hBrush=CreateBrushIndirect(&(item[CurItem].brush)))) {
- FillRect(hDC,&rect,hBrush);
- DeleteObject(hBrush); // delete the temporary brush
- }
- }
-
- // draw the bounding rectangle
- if (item[CurItem].OutlineSelect) {// draw rectangle
- if (NULL!=(hPen=CreatePen(item[CurItem].OutlineStyle,item[CurItem].OutlineWidth,item[CurItem].OutlineColor))) {
- SelectObject(hDC,hPen);
- FrDrawOutline(hDC,&rect,item[CurItem].OutlineSelect);
- SelectObject(hDC,GetStockObject(BLACK_PEN));
- DeleteObject(hPen); // delete the temporary pen
- }
- }
-
- // draw the item interior
- if (item[CurItem].type==LABEL) PrintLabel(hDC,CurItem);
- else if (item[CurItem].type==FIELD) PrintField(hDC,CurItem);
- else if (item[CurItem].type==LINE) PrintLine(hDC,CurItem);
- else if (item[CurItem].type==PICT) PrintPicture(hDC,CurItem);
-
- return TRUE;
- }
-
- /******************************************************************************
- PrintLabel:
- Print a label to the specified device context
- *******************************************************************************/
- int PrintLabel(HDC hDC, int CurItem)
- {
- RECT rect;
- int LabelWidth,LabelHeight,LabelLen,x,y,flags,font;
-
- // build the bounding rectangle
- rect.left=item[CurItem].x+CurX;
- rect.right=item[CurItem].x+CurX+item[CurItem].width;
- rect.top=item[CurItem].y+CurHeight+item[CurItem].HeightAdj;
- rect.bottom=rect.top+item[CurItem].height;
-
- // Get label dimension
- font=item[CurItem].font;
- LabelWidth=GetLabelLen(item[CurItem].label,font);
- LabelHeight=FrFont[font].height;
- LabelLen=lstrlen(item[CurItem].label);
-
- // Get the label position
- flags=item[CurItem].flags;
- if (flags&OFLAG_HLEFT) x=rect.left+DESC_MARGIN;
- else if (flags&OFLAG_HRIGHT) x=rect.left+(item[CurItem].width-LabelWidth)-DESC_MARGIN;
- else {
- x=rect.left+(item[CurItem].width-LabelWidth)/2; // center
- if (x<(rect.left+DESC_MARGIN)) x=rect.left+DESC_MARGIN;
- }
- if (flags&OFLAG_VTOP) y=rect.top;
- else if (flags&OFLAG_VBOTTOM)y=rect.top+(item[CurItem].height-LabelHeight);
- else y=rect.top+(item[CurItem].height-LabelHeight)/2; // center
-
-
- // Draw the label
- SetFont(hDC,(BYTE)font);
- SetTextColor(hDC,item[CurItem].TextColor);
- SetBkMode(hDC,TRANSPARENT);
- if (LabelLen>0) TextOut(hDC,x,y,item[CurItem].label,LabelLen);
-
- // update the last Y position
- if (CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj>LastY)
- LastY=CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj;
-
- return TRUE;
- }
-
- /******************************************************************************
- PrintField:
- Format and print the current field
- *******************************************************************************/
- PrintField(HDC hDC, int CurItem)
- {
- RECT rect;
- int i,j,x,y,count,CurField,LabelLen,LabelWidth,LabelHeight,font,flags,
- SuffixWidth,PosSuffixLen,NegSuffixLen;
- LPSTR ptr;
- char string[NAME_WIDTH+1];
-
- CurField=item[CurItem].field; // field associated with the item
-
- font=item[CurItem].font;
-
- // build the bounding rectangle
- rect.left=item[CurItem].x+CurX;
- rect.right=item[CurItem].x+CurX+item[CurItem].width;
- rect.top=item[CurItem].y+CurHeight+item[CurItem].HeightAdj;
- rect.bottom=rect.top+item[CurItem].height;
-
- // print picture type field
- if (field[CurField].type==TYPE_PICT) {
- if (RepArg.DrawPicture) (RepArg.DrawPicture)(hDC,(int)field[CurField].NumData,field[CurField].FileId,field[CurField].FieldId,&rect);
- return TRUE;
- }
-
- // print word wrapped field
- if (field[CurField].type==TYPE_TEXT
- && field[CurField].flags&(FLAG_WRAP|FLAG_WORD_WRAP)) return PrintWrapField(hDC,CurItem);
-
-
- // get the formatted data
- FormatFieldData(&field[CurField],item[CurItem].label);
- if (field[CurField].type==TYPE_TEXT) {
- ptr=field[CurField].CharData; // pointer to the formatted data
- TruncateText(ptr,item[CurItem].width,font); // truncate text to fit within the label
- }
- else ptr=item[CurItem].label;
- LabelLen=lstrlen(ptr);
-
- // special numeric field format processing
- if (field[CurField].type==TYPE_NUM || field[CurField].type==TYPE_DBL) {
- // check negative sign suffix
- SuffixWidth=0;
- NegSuffixLen=lstrlen(field[CurField].NegSignSuffix);
- if (NegSuffixLen>0 && LabelLen>NegSuffixLen
- && lstrstr(&ptr[LabelLen-NegSuffixLen],field[CurField].NegSignSuffix)!=NULL)
- SuffixWidth=GetLabelLen(field[CurField].NegSignSuffix,font);
-
- // check positive sign suffix
- PosSuffixLen=lstrlen(field[CurField].PosSignSuffix);
- if (SuffixWidth==0 && PosSuffixLen>0 && LabelLen>PosSuffixLen
- && lstrstr(&ptr[LabelLen-PosSuffixLen],field[CurField].PosSignSuffix)!=NULL)
- SuffixWidth=GetLabelLen(field[CurField].PosSignSuffix,font);
-
- // process 'pad with zero' flag
- if (field[CurField].flags&FLAG_PAD_ZERO) {
- count=(item[CurItem].width-GetLabelLen(ptr,font)+SuffixWidth)/GetLabelLen("0",font); // number of zeros to insert
- if (count>0) {
- for (i=j=0;i<LabelLen;i++,j++) {
- // look for first numeric character
- if (i==j && (ptr[i]=='.' || ptr[i]==',' || (ptr[i]>='0' && ptr[i]<='9'))) { // first numeric character found
- while (count>0) {
- string[j]='0';
- j++;
- count--;
- }
- }
- string[j]=ptr[i];
- }
- string[j]=0;
- lstrcpy(ptr,string); // new string
- LabelLen=lstrlen(ptr); // new label length
- }
- }
- }
- else SuffixWidth=0;
-
- // Get field dimension
- LabelWidth=GetLabelLen(ptr,font)-SuffixWidth;
- LabelHeight=FrFont[font].height;
-
- // Get the label position
- flags=item[CurItem].flags;
- if (flags&OFLAG_HLEFT) x=rect.left+DESC_MARGIN;
- else if (flags&OFLAG_HRIGHT) x=rect.left+(item[CurItem].width-LabelWidth)-DESC_MARGIN;
- else {
- x=rect.left+(item[CurItem].width-LabelWidth)/2; // center
- if (x<(rect.left+DESC_MARGIN) ) x=rect.left+DESC_MARGIN;
- }
- if (flags&OFLAG_VTOP) y=rect.top;
- else if (flags&OFLAG_VBOTTOM)y=rect.top+(item[CurItem].height-LabelHeight);
- else y=rect.top+(item[CurItem].height-LabelHeight)/2; // center
-
-
- // Draw the label
- SetFont(hDC,(BYTE)font);
- SetTextColor(hDC,item[CurItem].TextColor);
- SetBkMode(hDC,TRANSPARENT);
- if (LabelLen>0) TextOut(hDC,x,y,ptr,LabelLen);
-
- // update the last Y position
- if (CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj>LastY)
- LastY=CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj;
-
- return TRUE;
- }
-
- /******************************************************************************
- PrintWrapField:
- Format and print a word/wrapped field
- *******************************************************************************/
- PrintWrapField(HDC hDC, int CurItem)
- {
- RECT rect;
- int x,y,FirstChar,LastChar,CurField,LabelLen,i,LastItem,CurSec,
- LabelWidth,LabelHeight,font,flags,FieldHeight,DistanceY;
- char string[LINE_WIDTH+1];
- BOOL FlexibleSize,paged=FALSE;
-
- CurField=item[CurItem].field; // field associated with the item
- FlexibleSize=field[CurField].flags&FLAG_FLEX_SIZE;
- font=item[CurItem].font;
- CurSec=item[CurItem].section;
- LastItem=section[CurSec].FirstItem+section[CurSec].ItemCount-1; // Last item in the section
-
- // build the bounding rectangle
- rect.left=item[CurItem].x+CurX;
- rect.right=item[CurItem].x+CurX+item[CurItem].width;
- rect.top=item[CurItem].y+CurHeight+item[CurItem].HeightAdj;
- rect.bottom=rect.top+item[CurItem].height;
-
- // get the formatted data
- FormatFieldData(&field[CurField],item[CurItem].label);
-
- // extract lines and print
- FirstChar=0;
- y=rect.top;
- SetFont(hDC,(BYTE)font);
- SetTextColor(hDC,item[CurItem].TextColor);
- SetBkMode(hDC,TRANSPARENT);
-
- while ((LastChar=ExtractLine(CurItem,string,FirstChar))!=-1) {
- StrTrim(string); // terminate space
-
- LabelWidth=GetLabelLen(string,font);
- LabelHeight=FrFont[font].height;
- LabelLen=lstrlen(string);
-
- // Get the label position
- flags=item[CurItem].flags;
- if (flags&OFLAG_HLEFT) x=rect.left+DESC_MARGIN;
- else if (flags&OFLAG_HRIGHT) x=rect.left+(item[CurItem].width-LabelWidth)-DESC_MARGIN;
- else x=rect.left+(item[CurItem].width-LabelWidth)/2; // center
-
- // Draw the text field
- if (LabelLen>0) TextOut(hDC,x,y,string,LabelLen);
-
- y+=LabelHeight;
- FirstChar=LastChar+1; // position for the next line
-
- // break if wrap rectangle is finished
- if ((y+LabelHeight>rect.bottom) && !FlexibleSize) break; // next line can't fit in the item rectangle
-
- // break if current page is finished
- if ((y+LabelHeight>PrintHeight)) {
- if (CurSec!=SEC_DETAIL1) break;
-
- // last break field is allowed to continue to the next page
- PageAdvanced=FALSE; // allow page advance now
- AdvancePage(CurSec); // advance page
- y=rect.top=CurHeight;
- SetFont(hDC,(BYTE)font); // set fonts again
- SetTextColor(hDC,item[CurItem].TextColor);
- SetBkMode(hDC,TRANSPARENT);
- rect.bottom=rect.top+PrintHeight; // allow full page
- paged=TRUE; // note the page advancement
- }
- }
-
- // check if Y adjustment for remaining field is needed
- FieldHeight=y-rect.top;
- if (FlexibleSize && FieldHeight!=item[CurItem].height) {
- for (i=CurItem+1;i<=LastItem;i++) {
- if (item[i].type==SECTION || item[i].type==GROUP) continue;
- if (item[i].section!=CurSec) continue;
- if (item[i].y>item[CurItem].y+item[CurItem].height-DESC_MARGIN) {
- if (paged) {
- DistanceY=item[i].y-(item[CurItem].y+item[CurItem].height); // distance between this item and end of the wrapped current item
- item[i].HeightAdj=-item[i].y+FieldHeight+DistanceY;
- }
- else item[i].HeightAdj=item[i].HeightAdj+FieldHeight-item[CurItem].height;
- }
- }
- }
-
- // update the last Y position
- if (y>LastY) LastY=y;
-
- return TRUE;
- }
-
- /******************************************************************************
- ExtractLine:
- This routine extract a line that can fit within the specified rectangle
- width. The extract line is returned using the second argument. The third
- argument tells the beginning position within the source string to start
- using.
- The routine returns the position of the last character within the source
- string.
- *******************************************************************************/
- ExtractLine(int CurItem,LPSTR string,int FirstChar)
- {
- int i,j,k,font,CurField,DataLen,len,LineWidth;
- int LastWordSrcIndex,LastWordDstIndex;
- BOOL WordWrap;
- LPSTR ptr;
- char ParaChar,CurChar;
- int far *CharWidth;
-
- // initialize variables
- font=item[CurItem].font; // font to print the field
- CharWidth=FrFont[font].CharWidth; // character width table
- CurField=item[CurItem].field; // current field
- ptr=field[CurField].CharData; // field text data pointer
- DataLen=lstrlen(ptr); // text data length
- ParaChar=field[CurField].ParaChar[0]; // paragraph break character
- if (field[CurField].flags&FLAG_WORD_WRAP) WordWrap=TRUE; // Word wrap
- else WordWrap=FALSE; // character wrap
-
- if (FirstChar>=(DataLen-1)) return -1; // no more characters left
-
- // build new string
- LineWidth=0; // unit width of the string
- j=0; // number of characters in the string
- i=FirstChar;
- LastWordSrcIndex=-1; // index of the last complete word in the source string
- LastWordDstIndex=-1; // index of the last complete word in the destination string
-
- while (TRUE) {
- if (i==DataLen) break; // all characters processed
- if (j>=LINE_WIDTH) break; // end of buffer
-
- CurChar=ptr[i];
- if (CurChar==ParaChar) { // paragraph break
- string[j]=0; // terminate the string
- return i; // return the last character index
- }
-
- // translate characters // cr/lf translation
- if (CurChar==0xA || CurChar==0xD) {
- if (j>0 && string[j-1]==' ') { // ignore
- i++;
- continue;
- }
- else CurChar=' '; // convert to spaces
- }
- else if (CurChar==0x9) { // translate tab
- for (k=0;k<TAB_CHAR_LEN-1;k++) { // expand to multiple spaces
- CurChar=' ';
- string[j]=CurChar;
- LineWidth+=CharWidth[(BYTE)CurChar];
- j++;
- if (j>=LINE_WIDTH || LineWidth>=item[CurItem].width) {
- j--;
- i--;
- break;
- }
- }
- }
-
- // process a regular character
- string[j]=CurChar;
- LineWidth+=CharWidth[(BYTE)CurChar];
- j++;
- if (j>=LINE_WIDTH || LineWidth>=item[CurItem].width) {
- j--;
- i--;
- break;
- }
- i++; // increment the source index
-
- // mark the last complete word
- if (CurChar==' ') {
- LastWordSrcIndex=i-1; // index of the last word in the source string
- LastWordDstIndex=j-1;
- }
- }
-
- // cutoff at word boundary
- if (WordWrap && LastWordSrcIndex>0 && LineWidth>=item[CurItem].width) {
- i=LastWordSrcIndex;
- j=LastWordDstIndex;
- }
-
- len=j;
- string[len]=0; // terminate the string
-
- return i; // last character processed
- }
-
- /******************************************************************************
- PrintLine:
- Print a 'line' type item
- *******************************************************************************/
- PrintLine(HDC hDC, int CurItem)
- {
- int x1,y1,x2,y2;
- HPEN hPen,hOldPen;
-
- // build the line beginning and ending coordinates
- if (item[CurItem].LineAngle==ANGLE_HORZ) { // horizontal line
- x1=item[CurItem].x+CurX;
- y1=CurHeight+item[CurItem].y+item[CurItem].HeightAdj+item[CurItem].height/2;
- x2=x1+item[CurItem].width;
- y2=y1;
- }
- else if (item[CurItem].LineAngle==ANGLE_VERT) { // vertical line
- x1=item[CurItem].x+CurX+item[CurItem].width/2;
- y1=CurHeight+item[CurItem].y+item[CurItem].HeightAdj;
- x2=x1;
- y2=y1+item[CurItem].height;
- }
- else if (item[CurItem].LineAngle==ANGLE_FDIAG) { // diagonal line
- x1=item[CurItem].x+CurX;
- y1=CurHeight+item[CurItem].y+item[CurItem].HeightAdj;
- x2=x1+item[CurItem].width;
- y2=y1+item[CurItem].height;
- }
- else { // backword diagonal line
- x1=item[CurItem].x+CurX;
- y1=CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj;
- x2=x1+item[CurItem].width;
- y2=CurHeight+item[CurItem].y;
- }
-
- // create the line pen
- if (NULL!=(hPen=CreatePen(item[CurItem].LineStyle,item[CurItem].LineWidth,item[CurItem].LineColor))) {
- hOldPen=SelectObject(hDC,hPen);
-
- // draw the line
- MoveToEx(hDC,x1,y1,NULL);
- LineTo(hDC,x2,y2);
-
- SelectObject(hDC,hOldPen);
- DeleteObject(hPen); // delete the temporary pen
- }
-
- // update the last Y position
- if (CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj>LastY)
- LastY=CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj;
-
- return TRUE;
- }
-
- /******************************************************************************
- PrintPicture:
- Draw a picture bitmap
- *******************************************************************************/
- PrintPicture(HDC hDC, int CurItem)
- {
- int pict;
- LPBITMAPINFO pInfo;
- LPSTR pImage;
-
- pict=item[CurItem].font; // index into the font structure
-
- // print a device independent bitmap
- if (NULL!=(pImage=GlobalLock(FrFont[pict].hImage))
- && NULL!=(pInfo=(LPBITMAPINFO)GlobalLock(FrFont[pict].hInfo)) ) {
-
- StretchDIBits(hDC,item[CurItem].x+CurX,CurHeight+item[CurItem].y+item[CurItem].HeightAdj,item[CurItem].width,item[CurItem].height,
- 0,0,(int)pInfo->bmiHeader.biWidth,(int)pInfo->bmiHeader.biHeight,pImage,pInfo,DIB_RGB_COLORS,SRCCOPY);
-
- GlobalUnlock(FrFont[pict].hImage);
- GlobalUnlock(FrFont[pict].hInfo);
- }
-
- // update the last Y position
- if (CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj>LastY)
- LastY=CurHeight+item[CurItem].y+item[CurItem].height+item[CurItem].HeightAdj;
-
- return TRUE;
- }
-
- /******************************************************************************
- FormatFieldData:
- This routine format the specified field to the specified width. It
- applies all applicable format to this field and returns the formatted
- string.
- ******************************************************************************/
- FormatFieldData(struct StrField huge *CurField,char far *string)
- {
- int i,j,type,SumType,len,negative,DecPlaces,digits,DecFound,temp,
- ZeroValue,LeftSignLen,RightSignLen,CurrencySymLen;
- char line[LINE_WIDTH+2],mm[3],dd[3],yy[5];
- unsigned flags;
- long NumData;
- double DblData;
-
- type=CurField->type;
- SumType=CurField->SumType;
- flags=CurField->flags;
- DecPlaces=CurField->DecPlaces;
-
- NumData=0;
- DblData=0;
-
- if (SumType==SUM_NONE) {
- if (type==TYPE_DBL) DblData=CurField->DblData;
- else NumData=CurField->NumData;
- }
- else if (SumType==SUM_COUNT) {
- if (type==TYPE_DBL) DblData=CurField->count;
- else NumData=CurField->count;
- CurField->count=0;
- }
- else if (SumType==SUM_AVERAGE) {
- if (type==TYPE_DBL) DblData=CurField->HoldDbl;
- else NumData=CurField->HoldNum;
- if (CurField->count>0) {
- if (type==TYPE_DBL) DblData/=(double)CurField->count;
- else NumData/=(long)CurField->count;
- }
- CurField->count=0;
- CurField->HoldDbl=0;
- CurField->HoldNum=0;
- }
- else {
- if (type==TYPE_DBL) DblData=CurField->HoldDbl;
- else NumData=CurField->HoldNum;
- CurField->HoldDbl=0;
- CurField->HoldNum=0;
- }
-
- //*************** Format Alpha Fields **********************************
- if (type==TYPE_TEXT) {
-
- string=CurField->CharData;
- len=strlen(string);
-
- if (flags&FLAG_CAPS) strupr(string);
- else if (flags&FLAG_SMALL) strlwr(string);
- else if (flags&FLAG_FIRST_CAP) {
- strlwr(string);
- for (i=0;i<len;i++) {
- if (i==0 || string[i-1]==' ') string[i]=toupper((string[i]));
- }
- }
-
- if (flags&FLAG_TRIM) rTrim(string);
- }
-
- //**************** Format numeric fields ********************************
- else if (type==TYPE_NUM || type==TYPE_DBL) {
- negative=ZeroValue=FALSE;
- if (type==TYPE_NUM) {
- if (NumData<0) {
- negative=TRUE;
- NumData=-NumData;
- }
- if (NumData==0) ZeroValue=TRUE;
-
- ltoa(NumData,string,10);
- if (DecPlaces>0) { // insert a decimal
- len=strlen(string);
- if (DecPlaces>len) {
- lPad(string,DecPlaces+1);
- string[0]='.';
- i=1;
- while (string[i]==' ') {
- string[i]='0';
- i++;
- }
- }
- else {
- lPad(&string[len-DecPlaces],DecPlaces+1);
- string[len-DecPlaces]='.';
- }
- }
- }
- else { // if type is equal to doubld
- if (DblData<0) {
- negative=TRUE;
- DblData=-DblData;
- }
- if (DblData==0) ZeroValue=TRUE;
-
- DoubleToStr(DblData,DecPlaces,string);
- }
-
- //********************* insert comma characters *******************
- if (flags&FLAG_COMMA) { // insert comma
- len=strlen(string);
- for (digits=0;digits<len;digits++) if (string[digits]=='.') break;
- if (digits>0) {
- strcpy(line,string);
- j=0;
- DecFound=FALSE;
- for (i=0;i<len;i++,j++) {
- if (DecFound) { // simply copy the remaining digits
- string[j]=line[i];
- }
- else { // before decimal
- if (line[i]=='.') {
- string[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
- string[j]=',';
- j++;
- }
- string[j]=line[i];
- digits--;
- }
- }
- }
- string[j]=0;
- }
- }
-
-
- //******************* apply numeric attributes *******************************
- len=strlen(string);
- LeftSignLen=lstrlen(CurField->NegSignPrefix);
- if (lstrlen(CurField->PosSignPrefix)>LeftSignLen) LeftSignLen=lstrlen(CurField->PosSignPrefix);
-
- RightSignLen=lstrlen(CurField->NegSignSuffix);
- if (lstrlen(CurField->PosSignSuffix)>RightSignLen) RightSignLen=lstrlen(CurField->PosSignSuffix);
-
- CurrencySymLen=lstrlen(CurField->CurrencySymbol);
-
- //******************* insert the currency symbol ********************
- if (CurrencySymLen>0) {
- lPad(string,len+CurrencySymLen);
- for (i=0;i<CurrencySymLen;i++) string[i]=CurField->CurrencySymbol[i];
- len+=CurrencySymLen;
- }
-
- //******************* insert the left prefix symbol ********************
- if (LeftSignLen>0) {
- lPad(string,len+LeftSignLen);
-
- if (negative) {
- for (i=0;i<lstrlen(CurField->NegSignPrefix);i++) string[i]=CurField->NegSignPrefix[i];
- }
- else {
- for (i=0;i<lstrlen(CurField->PosSignPrefix);i++) string[i]=CurField->PosSignPrefix[i];
- }
- len+=LeftSignLen;
- }
-
- //******************* insert the right suffiex symbol ********************
- if (RightSignLen>0) {
- rPad(string,len+RightSignLen);
-
- if (negative) {
- for (i=0;i<lstrlen(CurField->NegSignSuffix);i++) string[len+i]=CurField->NegSignSuffix[i];
- }
- else {
- for (i=0;i<lstrlen(CurField->PosSignSuffix);i++) string[len+i]=CurField->PosSignSuffix[i];
- }
- len+=RightSignLen;
- rTrim(string);
- }
-
- //******************** length check *********************************
- if (flags&FLAG_SUP_ZERO && ZeroValue) string[0]=0;
- }
-
- //**************** Format date fields ***********************************
-
- else if (type==TYPE_DATE) {
- if (NumData<991231L) NumData=19000000L+NumData;
- ltoa(NumData,line,10);
-
- strcpy(dd,&line[6]);
- line[6]=0;
- strcpy(mm,&line[4]);
- line[4]=0;
- strcpy(yy,line);
- string[0]=0;
-
- switch (CurField->DateFormat) {
- case DT_MMDDYY:
- strcat(string,mm);
- lstrcat(string,CurField->DateDelim);
- strcat(string,dd);
- lstrcat(string,CurField->DateDelim);
- strcat(string,&yy[2]);
- break;
- case DT_DDMMYY:
- strcat(string,dd);
- lstrcat(string,CurField->DateDelim);
- strcat(string,mm);
- lstrcat(string,CurField->DateDelim);
- strcat(string,&yy[2]);
- break;
- case DT_MMDDYYYY:
- strcat(string,mm);
- lstrcat(string,CurField->DateDelim);
- strcat(string,dd);
- lstrcat(string,CurField->DateDelim);
- strcat(string,yy);
- break;
- case DT_MMMDDYYYY:
- temp=atoi(mm);
- if (temp<1) temp=1;
- if (temp>12) temp=12;
- strcat(string,MonthName[temp-1]);
- strcat(string," ");
- if (dd[0]=='0') strcat(string,&dd[1]);
- else strcat(string,dd);
- strcat(string,", ");
- strcat(string,yy);
- break;
- default:
- ;
- }
- }
-
- //**************** Format the logical fields *****************************
-
- else if (type==TYPE_LOGICAL) {
- if (NumData) string[0]=CurField->LogicalSymbols[0];
- else string[0]=CurField->LogicalSymbols[1];
- string[1]=0;
- }
-
- return TRUE;
- }
-
- /*****************************************************************************
- AcceptDlgField:
- Accept the values for the dialog fields from the user. The fields are
- accept as specified by the PromptOrder variable.
- *****************************************************************************/
- AcceptDlgField()
- {
- int fld,idx,FieldTable[MAX_DLGS],ord,TotalDlgFields,FieldFlag;
- int result;
- char string[NAME_WIDTH+2];
-
- // sort the fields in the prompt order
- TotalDlgFields=0;
- for (ord=0;ord<MAX_DLGS;ord++) {
- for (fld=0;fld<MAX_DLGS;fld++) {
- if (DlgField[fld].InUse && DlgField[fld].PromptOrder==ord) {
- FieldTable[TotalDlgFields]=fld;
- TotalDlgFields++;
- }
- }
- }
-
- if (TotalDlgFields==0) return TRUE; // dialog fields not used
-
- idx=0;
-
- while(TRUE) { // accept/validate each field
- if (idx>=TotalDlgFields) break;
- fld=FieldTable[idx];
-
-
- ACCEPT_DATA:
-
- DlgIndex=fld; // pass information to the dialog box
- FieldFlag=idx;
- if (idx==(TotalDlgFields-1)) FieldFlag=MAX_DLGS;
- result=CallDialogBox("DlgInputParam",DlgInputParam,(DWORD)FieldFlag);
-
- if (!result) {
- if (idx<=0) return FALSE;
- idx--;
- continue;
- }
-
- //***** convert and validate *****************
- if (DlgField[fld].type==TYPE_NUM) DlgField[fld].NumData=atol(DlgField[fld].CharData);
- else if (DlgField[fld].type==TYPE_DBL) DlgField[fld].DblData=atof(DlgField[fld].CharData);
- else if (DlgField[fld].type==TYPE_LOGICAL) {
- strupr(DlgField[fld].CharData);
- StrTrim(DlgField[fld].CharData);
- if (strstr("YES,TRUE,Y,1",DlgField[fld].CharData)) DlgField[fld].NumData=1;
- else if (strstr("NO,FALSE,N,0",DlgField[fld].CharData)) DlgField[fld].NumData=0;
- else {
- MessageBox(hFrWnd,"Valid entries: YES,NO,TRUE,FALSE,Y,N,1,0",NULL,MB_OK);
- goto ACCEPT_DATA;
- }
- }
- else if (DlgField[fld].type==TYPE_DATE) {
- if (DlgField[fld].CharData[0]!='\"') { // enclose in quotes
- strcpy(string,"\"");
- strcat(string,DlgField[fld].CharData);
- strcat(string,"\"");
- }
- else strcpy(string,DlgField[fld].CharData);
-
- if (!ValidateDate(string,&(DlgField[fld].NumData)) || DlgField[fld].NumData==-1) {
- MessageBox(hFrWnd,"Invalid Date Format/Value!",NULL,MB_OK);
- goto ACCEPT_DATA;
- }
- }
-
- idx++;
- }
-
- return TRUE;
- }
-
- /*****************************************************************************
- AllocRepMem:
- Allocate memory for:
- This routine adjusts the memory blocks allocated by the AllocFormMem
- routine and allocates these new objects:
- 1. Sort Fields
- *****************************************************************************/
- AllocRepMem()
- {
- int i;
- int FieldIndex,fld;
-
- if (UseScreen) {
- if ( (NULL==(hPageLoc=GlobalAlloc(GMEM_MOVEABLE,(long)(MAX_SCR_PAGES+1)*sizeof(long))))
- || (NULL==(PageLoc=(long far *)GlobalLock(hPageLoc))) ) {
- AbortFr("Ran Out of Memory (AllocRepMem)",ERR_NO_MEM);
- }
- FileBuf=OurAlloc(BUF_SIZE); // allocate file buffer
- }
-
- //**** allocate other object arrays *************************************
- if ( (NULL==(hUserField=GlobalAlloc(GMEM_MOVEABLE,(long)(TotalFields+1)*sizeof(struct StrField))))
- || (NULL==(UserField=(struct StrField huge *)GlobalLock(hUserField)))
- || (NULL==(hSortField=GlobalAlloc(GMEM_MOVEABLE,(long)(TotalBreakFields+1)*sizeof(struct StrField))))
- || (NULL==(SortField=(struct StrField huge *)GlobalLock(hSortField))) ){
- AbortFr("Ran Out of Memory (AllocRepMem(1))",ERR_NO_MEM);
- }
-
- //***** shrink the field array ******************************************
- GlobalUnlock(hField);
- if ( (NULL==(hField=GlobalReAlloc(hField,(long)(TotalFields+1)*sizeof(struct StrField),0)))
- || (NULL==(field=(struct StrField huge *)GlobalLock(hField))) ){
- AbortFr("Ran Out of Memory (AllocRepMem(2))",ERR_NO_MEM);
- }
-
- for(fld=0;fld<TotalFields;fld++) { // allocate space for the character fields
- UserField[fld].type=field[fld].type;
-
- if (field[fld].type==TYPE_TEXT) {
-
- //***** update the width for the dialog fields **********
- if (field[fld].source==SRC_DLG) field[fld].width=DlgField[field[fld].SysIdx].width;
-
- if (NULL==(field[fld].CharData=OurAlloc(field[fld].width+2))
- || NULL==(UserField[fld].CharData=OurAlloc(field[fld].width+2)) ) {
- AbortFr("Ran Out of Memory(2)",ERR_NO_MEM);
- }
- }
- }
-
- for(i=0;i<TotalBreakFields;i++) { // allocate space for the character sort fields
- FieldIndex=BreakField[i].SortField; // index into the field table
- SortField[i].type=field[FieldIndex].type;
-
- if (field[FieldIndex].type==TYPE_TEXT) {
- if (NULL==(SortField[i].CharData=OurAlloc(field[FieldIndex].width+2))) {
- AbortFr("Ran Out of Memory(3)",ERR_NO_MEM);
- }
- }
- }
-
- return TRUE;
- }
-
- /******************************************************************************
- StuffSysField:
- Build data for the system fields
- *******************************************************************************/
- StuffSysField(struct StrField huge *field)
- {
-
- switch (field->SysIdx) {
- case SYS_PAGE:
- field->NumData=PageCount;
- if (CurHeight>=PrintHeight) (field->NumData)++;
- break;
- case SYS_DATE:
- field->NumData=SystemDate;
- break;
- case SYS_TIME:
- lstrcpy(field->CharData,SystemTime);
- break;
- case SYS_REC_COUNT:
- field->NumData=RecCount+1;
- break;
- case SYS_PARA_BREAK:
- field->CharData[0]=DEF_PARA_BREAK;
- field->CharData[1]=0;
- break;
- default:
- ;
- }
-
- return TRUE;
- }
-