Information management system with improved methods and interface for printing data5995985Abstract A system providing a Print Manager having a Form Designer which assists a user with mapping user data (e.g., "cardfile" or database data) onto a formatted output, such as a commercial form, is described. During system operation, the user employs the Form Designer as a free-hand tool for placing fields and other information anywhere on a form (e.g., label) in a WYSIWYG ("what you see is what you get") fashion. In this manner, the user can create a content description which describes how contents (i.e., user data) are laid out. The system maintains, independent of the content descriptions, a set of templates which define print styles or layouts for particular forms, such as envelopes, address labels, and the like. The content description, once defined, can be applied against various templates in a generic fashion. An interface is provided which allows the user to cycle through various templates, with the content description being automatically applied against each template. Claims What is claimed is: Description COPYRIGHT NOTICE
______________________________________
// all printing
typedef struct
int Totalcards ;
BYTE CardSelect ;
short KeyField ;
BYTE flag ;
BYTE ifLandscapeOK ;
BYTE ifLandscape ;
WORD ifManualFeedOK ;
WORD ifManualFeed ;
BYTE nCopies ;
BYTE CardCopies ;
char index1 [MAXSEARCH+4], index2 [MAXSEARCH+4];
BYTE ifDelLine ;
BYTE ifDelCard ;
double top, left ;
BYTE envFeed ;
BYTE ifPageNum ;
BYTE ifIndex ;
BYTE ifSingleIndex ;
BYTE rowStart, colStart ;
} LBPRINT;
______________________________________
As shown, the data structure stores general printing options the user is able to choose. Each functions as follows.
______________________________________
General options:
TotalCards: number of cards to be printed;
CardSelect: card range;
KeyField: printing order;
flag: label-address-envelope flag;
IfLandscapeOK: if support landscape flag;
ifLandscape: if landscape flag;
ifManualFeedOK: if printer support manual feed flag;
ifManualFeed: if manual feed flag;
nCopies: number of clpies;
CardCopies: card copies;
index1[ ]: card index range (1);
index2[ ]: card index range (2);
ifDelLine: del blank line flag;
ifDelCard: del blank card flag;
Envelope printing options:
top, left: envelope margins;
envFeed: envelope feeding flag;
Address-label options:
ifPageNum: page number flag;
ifIndex: index flag;
IfSingleIndex: single index tab per page;
rowStart, colStart:
starting row and column
______________________________________
The LBPRINT data structure, in effect, serves as a session descriptor, for a particular printing session. Next, a "template" data structure is employed to define various templates. In an exemplary embodiment, both address and label templates are formed from an identical template data structure, LBTEMPLATE. The template data structure can be constructed as follows (in the C programming language).
______________________________________
// Label-Address Template
typedef struct
char name [FORMNAMELEN+4];
// locations
double top, bottom, left, right, vert, horz;
// margins
double fmtop, fmbot, fmleft, fmrite, fmvert, fmhorz;
short row ;
short column;
short page;
BYTE ifOpposite;
BYTE ifBothSides;
BYTE ifLRMirror;
BYTE ifTBToggie;
BYTE ifRevOrder;
BYTE ifBindHole;
} LBTEMPLATE ;
______________________________________
The data structure stores information defining a template. The particular data members of the data structure function as follows.
______________________________________
name[ ]: internal name for identifing a particular template
record;
top, bottom, left,
right, vert, horz:
locations;
fmtop, fmbot,
fmleft, fmrite,
fmvert, fmhorz:
margins;
row: row;
column: column;
page: page type (1, 2, 2v, 3, 3v, 4: whole, half, quarter,
3 stripes, binding hole (same side), 2 way/3 way
vertical split;
ifOpposite:
ifopposite flag (put the second page on opposite
corner);
ifBothSides:
ifboth sides (print) flag;
ifLRMirror:
mirror left/right on reverse side flag;
ifTBToggie:
toggle top/bottom on reverse side flag;
ifRevOrder:
re-page-numbering on reverse side flag;
ifBindHole:
binding hole layout.
______________________________________
The data structure, which defines a single template record, essentially stores two sets of margins. A first set of margins, the label margins, include: top, bottom, left, right, vert, and horz. These form a set of inner margins. A second set of margins, the page margins, are defined in a corresponding manner for the form: fmtop, fmbot, fmleft, fmright, fmvert, and fmhorz. Use of these two sets of margins is perhaps best illustrated diagrammatically. FIG. 8 illustrates the "inner" and "outer" sets of margins. As shown in FIG. 8, "paper" 800 can be divided into frames or "pages," such as page 810 for a paper divided into four equal sections. Here, paper 800 represents the actual physical paper. The paper can be divided into other frames, such as three horizontal or vertical sections, or two horizontal or vertical sections. Within each page (e.g., page 810), there exists a plurality of label areas, such as area 820. Between the label areas are the inner set of margins. As shown, for instance, page 810 includes the following margins: horz 831, vert 832, top 833, and bot 834. The paper includes the following outer set of margins: fmleft 841, fmright 842, fmvert 843, fmhorz 844, fmtop 845, and fmbot 846. Here, the outer set of margins define the margins for the particular page or frame, which the paper has been divided into. The use of separate sets of margins is particularly advantageous in a "page flip" layout, such as previously illustrated. In particular, such an approach simplifies determination of layout for the flip or reverse side. The row and column data members of LBTEAPLATE indicate the number of rows and columns of labels. In FIG. 8, for instance, page 810 includes three rows and two columns of labels. The remaining data members of the data structure serve as flags or booleans. The ifOpposite member is a flag indicating "opposite corners" for a two way split. An example of a two way split with opposite corners is illustrated in FIG. 9. Note, here, that the top frame margin must match the bottom frame margin. The ifBothSides member is a flag indicating that both sides of the paper are employed for printout. In other words, this specifies that the printout is "double sided," and thus affects how pages are sent to the printer. This is supported in different ways by various printing devices, including automatically (i.e., duplex printing) and manually (i.e., the user must manually re-feed the pages). The ifLRMirror and ifTBToggle data members function similarly to the "opposite corners" data member. Here, however, the data members specify that the entire set of margins (not just top and bottom) are employed when flipping over a page. The last two data members are ifRevOrder and ifBindHole. The former serves as a flag which indicates that the page numbering should be reversed (i.e., printed in reverse order). The latter indicates what type of binding holes, if any, is employed for the form. The enumerated types include "same side" and "opposite side." The binding hole type also affects the page order on final printout. Each object which exists on a form is a "form cell." Each cell, in turn, is described by a FORMCELL record--a descriptor for the object. During system operation, the descriptor is employed as a "filter object," for filtering the Cardfile data into a final printout. In an exemplary embodiment, the FORMCELL data structure may be constructed as follows.
______________________________________
// Formcell - - functions as Filter/Envelope Object
typedef struct {
// each cell (rect) on the envelope
long type
char FieldIndex [MAXCELLFIELDS+4] ;
char buf[BUFSIZE+4] ;
long scale ;
long left, top, right, bottom ;
FFONT font ;
} FORMCELL;
______________________________________
The data structure stores information defining a template. The particular data members of the data structure function as follows.
______________________________________
type TYPE.sub.-- TEXT - generic text,
TYPE.sub.-- GRAPH - stretched bitmaps,
TYPE.sub.-- LABEL - text with card fields in it,
TYPE.sub.-- STAMP - rotatable text,
TYPE.sub.-- FRAME - rectangle frame,
TYPE.sub.-- VLINE - vertical line,
TYPE.sub.-- HLINE - horizontal line,
TYPE.sub.-- OLEOBJ - OLE (Microsoft OLE 2.x) object;
FieldIndex [ ]:
indices of the card fields in buf(TYPE.sub.-- LABEL only);
buf[ ]: 1. filename of TYPE.sub.-- GRAPH,
2. text of TYPE.sub.-- TEXT, TYPE.sub.-- STAMP,
TYPE.sub.-- LABEL, TYPE.sub.-- OLEOBJ;
scale: 1. bitmap scale factor of TYPE.sub.-- GRAPH,
2. TotalIndice of Fields of TYPE.sub.-- LABEL,
3. Line size of
TYPE.sub.-- FRAME/TYPE.sub.-- VLINE/.sub.-- HLINE;
left, top, right, bottom: define a rectangle in 2D space;
font: FFONT (font) structure.
______________________________________
As shown, type is the first data member. It stores the type of cell, such as graph, label, text, stamp, and the like. The next data member, FieldIndex serves as an index of card fields in memory (in a buffer); this is employed for cells of type "label" (i.e., those with text from card fields). For label fields, the field name for the field will be replaced with the actual contents for that field (from the underlying Cardfile). The buf data member is a buffer which stores either: (1) the file name of type "graph," or (2) the text of type "label" (text, stamp, or OLE object). The scale data member stores the scale factor for the field, (e.g., such as a scale factor for a bitmap of type "graph"). For cells of type "label," the scale data member stores the total indices of fields. Otherwise, for cell type of "frame," "vertical line," or "horizontal line," the scale data member stores the line size. Size and position of the cell is characterized by a rectangle defined by the left, top, right, and bottom data members. Collectively, these define a particular rectangle. Finally, the font data member stores a value indicating a particular font employed for the cell object. D. Methods 1. General As displayed in FIG. 10, an overall printing method 1000 of the present invention, for directing operation of the Print Manager, can be divided into the following general steps. At step 1001, the system displays the Print Manager Dialog, for getting information from the user about what is to be printed and how it is to be laid out. The method then initiates a print session (e.g., initialize globals) at step 1002. The method proceeds to step 1003 to open the database (e.g., Cardfile). Then, at step 1004, the data is retrieved from the database and sorted, as required by the user. At step 1005, the system matches the data through the filters, using the previously-described content descriptors. After the data matching step, the method still has to figure out how the data are to be laid out on page. Thus, at this point, the method sets up a page sequence, at step 1006. Each page includes one or more cards. For instance, the first page might include cards 1-5, while the second page includes cards 6-10. At step 1007, the method calculates page numbers, as required by the user input. In the template, how a page is split (e.g., two vertical split, three vertical split, opposite corner, and the like) is specified. This information, in turn, dictates how the page number is finally laid out and is employed for mapping a final print sequence. Finally, at step 1008, the method can initiate the print sequence for the environment. In Microsoft Windows, for instance, this would include appropriate calls to Windows' GDI (Graphic Device Independent) interface for invoking Windows print routines/drivers. 2. Specific methods The high-level method just described will be examined in further detail by describing particular subroutines or methods of the present invention which are invoked. The high-level method invokes a SortPrintCards method. Although the method sorts a selected printing card range, as needed, the method also serves as a jumping off point to other subroutines. In an exemplary embodiment, the method can be constructed as follows.
__________________________________________________________________________
1: /****************************************************************
2: 1. resort the selected printing card range (if needed)
3: 2. setup the print label page card indices
4: ****************************************************************/
5: int SortPrintCards (HFILE fh.sub.-- old, HFILE fh.sub.-- tmp)
6: {
7: LPCARDHEADER lpCardHd;
8: HANDLE hdBuf, hCardText, hdCardSelection ;
9: LPSTR lpCardText;
10:
int i, res = IDOK, icard, iStartCard, nCards, SortFlag, icopy ;
11:
HFILE fh ;
12:
HCURSOR hc ;
13:
char buf[BUFSIZE+1], buf1[BUFSIZE+1],
14:
sz[FORMNAMELEN+1], sz1[FORMNAMELEN+1] ;
15:
// step 1 - decide if there's fieldname in format at all
16:
// (FillField) and if LbPrintKeyField != Current Index
17:
(need to reSort the cards)
18:
// See if need to sort (e.g., if only bmp's, don't need to sort
19:
SortFlag = GetLbFormatSortInfo ( ) ;
20:
21:
22:
// Check sort flag, if NULL (i.e., no sort order)
23:
if (SortFlag == LBP.sub.-- SF.sub.-- NULL) {
24:
// . . .
25:
MessageBox (NULL, buf, rgchCardfile, MB.sub.-- OK .vertline. MB.sub.--
APPLMODAL);
26:
// Done
27:
return 0 ;
28:
}
29:
30:
// Set up for sort
31:
if (!AllocThree (&hCardText, CARDTEXTSIZE,
32:
&hdBuf, CARDTEXTSIZE,
33:
&hdLbFieldCells,
34:
(DWORD)nCardFieldCells*sizeof(LBFIELDCELL)))
35:
{
36:
return FALSE ;
37:
}
38:
39:
40:
hc = SetCursor (LoadCursor (NULL, IDC.sub.-- WAIT)) ;
41:
lpCardHd = (LPCARDHEADER) GlobalLock (hCards);
42:
43:
// step 2 - get all the cards to be printed
44:
if (Lbprint.CardSelect != LBP.sub.-- CURRENTCARD
45:
&& SortFlag == LBP.sub.-- SF.sub.-- CELL) {
46:
// no label cell
47:
LbPrint.CardSelect = LBP.sub.-- CURRENTCARD ;
48:
}
49:
// Index Range
50:
if (Lbprint.CardSelect == LBP.sub.-- INDEXRANGE) {
51:
if (!GetCardNumber (LbPrint.index1, LbPrint.index2))
52:
{
53:
iStartCard = nCards = 0 ;
54:
} else {
55:
iStartCard = iStartPrint
56:
nCards = iEndPrint - iStartPrint ;
57:
// iStartPrint, iEndPrint ;
58:
{
59:
} else if (Lbprint.CardSelect == LBp.sub.-- CURRENTCARD) {
60:
nCards = 1 ; // current cards
61:
iStartCard = iFirstCard ; // global
62:
63:
} else if (Lbprint.CardSelect == LBP.sub.-- SELECTEDCARDS) {
64:
// selected cards
65:
nCards = GetCB.sub.-- Selection (&hdCardSelection) ;
66:
iStartCard = 0 ;
67:
68:
} else if (Lbprint.CardSelect == LBP.sub.-- ALLCARDS
.vertline..vertline.
69:
LbPrint.CardSelect == LBP.sub.-- MARKEDCARDS) {
70:
iStartCard = 0 ;
71:
nCards = cCards ;
72:
}
73:
74:
// Check whether separate pages by index tab
75:
if (LbPrint.ifSingleIndex) ( // reset LbIndexTabs ;
76:
for (i=0; i<MAXINDEXTABS; i++) {
77:
LbIndexTabs[i] .TotalCards = 0 ;
78:
LbIndexTabs[i] .cTab = 0 ;
79:
}
80:
TotalLbIndexTabs = 0 ; // global
81:
}
82:
83:
lpCardText = GlobalLock (hCardText);
84:
85:
// Loop thru all cards
86:
for ( TotalLbCards = 0, i = iStartCard ;
87:
i < iStartCard+nCards ; i ++ ) {
88:
// Get ones user marked/selected
89:
if(Lbprint.CardSelect == LBP.sub.-- SELECTEDCARDS) {
90:
icard = *((LPINT)GlobalLock (hdCardSelection) + i) ;
91:
GlobalUnlock (hdCardSelection) ;
92:
} else {
93:
icard = i ;
94:
}
95:
// tagged card only
96:
if (Lbprint.CardSelect == LBP.sub.-- MARKEDCARDS) {
97:
if (!IsCardTagged (lpCardHd + icard)}
98:
continue ;
99:
}
100:
101:
// Set up for multiple copies
102:
fh = ((lpCardHd+icard)->flags & FTMPFILE) ? fh.sub.-- tmp : fh.sub.--
old;
103:
// Do actual read of data
104:
ReadCardData.sub.-- fh (fh, lpCardHd+icard, lpCardText);
105:
106:
for (icopy=0; icopy <LbPrint.CardCopies; icopy ++) {
107:
// Add each card to index seq.
108:
if (!AddLbCard(fh.sub.-- old,fh.sub.-- tmp,SortFlag,lpCardText,
hdBuf))
109:
goto out ;
110:
if (TotalLbCards >= 5000) {
111:
LoadString (hCardfileInstance, IDS.sub.-- LBTOOMANYCARDS,
LFSTR)buf1, BUFSIZE) ;
112:
wsprintf ((LPSTR)buf, (LPSTR)buf1, icard) ;
113:
res = MessageBox (NULL, buf, rgchCardfile,
114:
MB.sub.-- ICONINFORMATION .vertline. MB.sub.-- OKCANCEL .vertline.
MB.sub.-- TASKMODAL);
115:
goto out
116:
}
117:
}
118:
}
119:
out:
120:
121:
if (TotalLbCards == 0) { // did not find any card to print
122:
GenMessage (IDS.sub.-- NOCARDS, MB.sub.-- OK.vertline.MB.sub.--
ICONEXCLAMATION);
123:
}
124:
125:
GlobalUnlock (hCardText);
126:
GlobalFree (hCardText);
127:
GlobalFree (hdBuf);
128:
129:
GlobalUnlock (hCards) ;
130:
131:
SetCursor (hc) ;
132:
if (TotalLbCards < 0 .vertline..vertline. nCards > 5000 && res ==
IDCANCEL) {
133:
// user abort the print job
134:
if (TotalLbCards > 0) {
135:
TotalLbCards = -1 ;
136:
ReAllocBuf ((LFHANDLE)&hdLbCardIndex,
(DWORD)sizeof(LBCARDINDEX)) ;
137:
ReAllocBuf ((LPHANDLE)&hdLbFieldCells,
(DWORD)sizeof(LBFIELDCELL)) ;
138:
}
139:
return 0 ;
140:
}
141:
return TotalLbCards ;
As shown, the method is passed a handle to the current Cardfile. For purposes of error recovery, a temporary (temp) version is also maintained as a backup. As its first step, the method determines whether it needs to sort the data at all, by a subroutine call to a GetLbFormatSortInfo method. This call checks the content filter for determining what information there is to sort. If no field name exists in the format at all (e.g., there only exists bitmaps), then the method need not be concerned with sorting data. The result of the subroutine call is stored to SortFlag, a sort flag, at line 19. If, at line 23, there is no information to sort (i.e., SortFlag set to NULL), the method is done and may simply return 0, at line 27. A dialog box can be (optionally) displayed before the return (as shown at line 25). At lines 30-37, the method performs memory allocation (based on number of card field cells), for setting up for the sort. Continuing on to line 43, the method proceeds to get all cards to be printed. Between lines 44-72, the method checks various flags, for determining whether the selected cards are a "current card," "all cards," particular "selected cards," or cards according to an "index range." In other words, the method determines at this point what subset of the cards are to be printed. At lines 74-81, the method checks whether separate pages are to be selected by index tab (e.g., "800 Numbers" tab). Upon reaching line 85, the method has determined the range of cards to be printed. At line 86, a "for" loop is established to loop through all cards which are selected for print. At lines 88-94, the method gets the cards which the user selected. At lines 96-99, the method gets the cards which the user marked (i.e., tagged). At line 101, the passed-in file handle is stored to a local variable, fh. Then, at line 104, the method undertakes to read the actual card data from the Cardfile specified by the fh data member. At line 106, a second (nested) "for" loop is established, for adding each card to the index sequence. An "out" label is established at line 119 to "go to" in the event of an error occurring while adding cards (e.g., exceeding the number of cards permissible). At line 121, if the method did not find any cards to print (i.e., TotalLBCards equals 0), the method displays an error message at line 122. Otherwise, at least some cards have been found to print and therefore no error message will be displayed. At lines 125-131, local cleanup is performed, such as freeing memory resources and resetting the screen cursor (e.g., from the "wait" or hourglass cursor). At lines 132-140, the method tests whether the user aborted the print job. In the instance where the user has aborted the job, the method returns 0, after reinitializing/resetting global data members. Otherwise, the method has reached line 141 without error and, as a result, has appropriately setup global data structures and may return the total number of cards to print. The call to the AddLBCard subroutine (which occurred at line 108 above) will now be described in further detail. In an exemplary embodiment, the method may be constructed as follows.
__________________________________________________________________________
1: BOOL AddLbCard (HFILE fh.sub.-- old, HFILE fh.sub.-- tmp, int
SortFlag, LPSTR
Card, HANDLE hdBuf)
2:
3: LPFORMAPI lpApi ;
4: LPLBCARDINDEX
lpCardIndex ;
5: HANDLE hdCells ;
6: LPFORMCELL
lpCell ;
7: LPLBFIELDCELL
lpFCell ;
8: char szField[CARDFIELDLENGTH+4], szLine[512], ch ; // API
9: LPSTR lpBuf, lpBuf0, lpCellText, lpIndex, lpLine ;
10:
int i, j, index, nFields, iField, len,
iFieldPtr[MAXCARDFIELDS], len1,
11:
iLine, iLine0, BlankLineFlags[200] ;
12:
BOOL bBlankCard, bBlankLine ;
13:
DWORD dwTotalCells ;
14:
15:
// if del blank cards, ignore the blank cards
16:
if (lpCard == 0 .vertline..vertline. LbPrint.ifDelCard && lpCard[0]
== 0)
17:
return TRUE ;
18:
if (!ReAllocBuf (&hdLbCardIndex, (DWORD)sizeof(LBCARDINDEX)
19:
* (TotalLbCards+1))) { return FALSE ;
20:
}
21:
22:
if (!ReAllocBuf (&hdLbFieldCells, (DWORD)sizeof(LBFIELDCELL)
23:
* (TotalLbCards+1) * (nCardFieldCells+1))) {
24:
return FALSE ;
25:
}
26:
27:
lpApi = (LPFORMAPI)GlobalLock (hdLbFormalApi) ;
28:
hdCells = (HANDLE)lpApi->hCells ;
29:
lpCell = (LPFORMCELL)GlobalLock (hdCells) ;
30:
// for all format cells in the card -
31:
// replace cardfield mark
32:
// with card field content- FillField ( )
33:
// get the start offset of each field in lpCard
34:
Create.sub.-- Fields.sub.-- Ptr (lpCard, iFieldPtr, cCardField) ;
35:
36:
// Loop thru all the cardfield cells
37:
for (bBlankCard = TRUE,i = 0 ; i < nCardFieldCells ; i ++ ) {
38:
// Get index for cell
39:
index = FieldCellIndex[i] ;
40:
// global setup during GetLbFormatInfo
41:
// Fill one cell
42:
lpBuf0 = lpBuf = GlobalLock (hdBuf) ;
43:
44:
// Read how many fields
45:
nFields = (int)lpCell[index].scale ;
46:
// Grab actual data
47:
lpCellText = (LPSTR)lpCell[index].buf ;
48:
49:
if (nFields > 0) { // there're some card field names
50:
// do FillField ( )
51:
memset (&BlankLineFlags, 0, sizeof(int)*200) ;
52:
// 0: blank, 1 not blank
53:
// Determine how many lines (e.g., of text)
54:
for (iLine = 0, j = 0 ; ; ) {
55:
56:
lpCellText = sGetToken (lpCellText, szLine; `.backslash.r`, 511) ;
57:
bBlankLine = 1 ;
58:
59:
// fill field of this line
60:
61:
// Grab data from card and match to cell
62:
lpLine = szLine ;
63:
while (*lpLine) {
64:
65:
if (*lpLine != CARDFIELDMARK) { // copy in-between
66:
*lpBuf ++ = *lpLine ++ ;
67:
} else if (j >= nFields) {
68:
lpLine ++ ;
69:
} else ( // fill one field
70:
iField = (int)lpCell[index].FieldIndex[j] ;
71:
if (iField >= 0 &&iField < lpApi->TotalFields) {
72:
if (iField<lpApi->TotalFields-1) { // not last
73:
len = iFieldPtr[iField+1]-iFieldPtr[iField] ;
74:
if (len > CARDFIELDLENGTH) {
75:
len = CARDFIELDLENGTH
76:
}
77:
} else {
78:
len = CARDFIELDLENGTH ;
79:
}
80:
lstrncpy(szField, lpCard +
iFieldPtr[iField], len) ;
81:
trim.sub.-- end (szField, ".backslash.r.backslash.n") ;
82:
len = lstrlen ((LFSTR)szField) ; //content
83:
if (len > 0) {
84:
if (bBlankCard == TRUE)
85:
bBlankCard = FALSE ; // something
86:
if (LbPrint.ifDelLine != 0 && bBlankLine )
87:
bBlankLine = FALSE ;
88:
}
89:
90:
if (len > 0) {
91:
lstrncpy (lpBuf, (LPSTR)szField, len) ;
92:
lpBuf += len ;
93:
}
94:
}
95:
lpLine ++ ; // skip the field mark
96:
j ++ ; // increase field cell index
97:
}
98:
}
99:
BlankLineFlags[iLine] = !bBlankLine ;
100:
iLine ++ ;
101:
102:
if (*lpCellText == 0) {
103:
break ;
104:
} else {
105:
*lpBuf ++ = `.backslash.r` ;
106:
*lpBuf ++ = `.backslash.n` ;
107:
lpCellText ++ ; // skip .backslash.n
108:
}
109:
}
110:
*lpBuf ++ = 0 ;
111:
112:
// delete any line that doesnt have a filled-field
113:
MaybeDelBlankLine (lpBuf0, iLine, BlankLineFlags) ;
114:
} else {
115:
if (LbPrint.ifDelLine)
116:
*lpBuf0 = 0 ; // ignore the text without any fields
117:
else
118:
lpBuf0 = lpCellText ; // just copy the whole string
119:
}
120:
121:
122:
// save this cell's text
123:
len = lstrlen (lpBuf0) ;
124:
if (len == 0) {
125:
*lpBuf0 = 0 ;
126:
}
127:
//Write the stuff into a temp file
128:
dwTotalCells = (DWORD)nCardFieldCells * TotalLbCards + i ;
129:
lpFCell = (LPLBFIELDCELL)GlobalLock (hdLbFieldCells) ;
130:
lpFCell += dwTotalCells ;
131:
lpFCell->offset = .sub.-- llseek (fhLbFCell, 0, 1) ;
132:
lpFCell->size = len ;
133:
if (len > 0) {
134:
len1 = (int) .sub.-- lwrite (fhLbFCell, lpBuf0, len) ;
135:
}
136:
GlobalUnlock (hdLbFieldCells) ;
137:
*lpBuf0 = 0 ;
138:
GlobalUnlock (hdBuf) ;
139:
if (len >0 && len1 < len) {
140:
GlobalUnlock (hdLbFormatApi) ;
141:
GlobalUnlock (hdCells) ;
142:
As shown, the method is invoked with five parameters. The first two parameters are the previously-described file handles. The third parameter is a sort flag, for indicating "with" or "without" sorting. The fourth parameter is a pointer to a location in memory which stores the cards. The fifth parameter is a handle to a memory buffer, which is employed as a temporary storage area. The steps of the method are as follows. At line 16, if the particular card is blank, then it is ignored; the method at this point simply returns "true." The card will not be added to the temporary Cardfile, which is employed for printing. After some memory allocation operations (lines 18-25), the method will get the content setup in the filter, from matching cells with appropriate Cardfile data. At line 34, the method gets the start (offset) of each field in the card (in memory). Then, at line 37, a "for" loop is established for looping through all card field cells. At line 39, the method gets the index for the cell, then at line 42, it fills one cell (buffer). At line 45, the method reads how many fields exists for the cell, then at line 47 it grabs the actual data for the cell. At line 49, the method tests whether the number of fields present in the cell is greater than 1. If so, then, at line 54, a "for" loop is established for determining how many lines (e.g., lines of text) exists for the cell. This is done by grabbing the data from the card and matching it to the cell (lines 61-98). Blank lines may be (optionally) skipped (line 113), depending on the user's preference. At lines 122-143, the method saves the cells content out to a temporary file. If an error occurs (e.g., disk full), the method returns "false." Thus up to this point, the method has grabbed the field and its corresponding filter in order to get the corresponding data into the field; this is saved out to the temporary file. At lines 147-150, the method will skip the current card if it is blank and the user has selected to "delete" or "skip" blank cards. At lines 153-158, the cards can be sorted into a different sequence than is specified by the default sort. The method establishes at this point, therefore, the sequence for the card field. Finally, the method inserts the card into its proper location, according to its key field content (line 189). The total number of cards is incremented at line 193, and the method returns "true" as line 197. While the invention is described in some detail with specific reference to a single preferred embodiment and certain alternatives, there is no intent to limit the invention to that particular embodiment or those specific alternatives. Thus, the true scope of the present invention is not limited to any one of the foregoing exemplary embodiments but is instead defined by the appended claims.
|
Same subclass Same class Consider this |
||||||||||
