1 /************************************************************************/
2 /* */
3 /* Manage a list of fields. */
4 /* */
5 /************************************************************************/
6
7 # include "docBaseConfig.h"
8
9 # include <stdlib.h>
10 # include <string.h>
11
12 # include <appDebugon.h>
13
14 # include "docDocumentFieldList.h"
15 # include "docBookmarkField.h"
16 # include "docDocumentField.h"
17
18 /************************************************************************/
19 /* */
20 /* Manage a list of fields. */
21 /* */
22 /************************************************************************/
23
24 /************************************************************************/
25 /* */
26 /* Make a copy of a field. */
27 /* */
28 /************************************************************************/
29
docClaimFieldCopy(DocumentFieldList * dfl,const DocumentField * dfFrom,const SelectionScope * ss,const EditPosition * epStart)30 DocumentField * docClaimFieldCopy( DocumentFieldList * dfl,
31 const DocumentField * dfFrom,
32 const SelectionScope * ss,
33 const EditPosition * epStart )
34 {
35 DocumentField * dfTo;
36
37 dfTo= docClaimField( dfl );
38 if ( ! dfTo )
39 { XDEB(dfTo); return (DocumentField *)0; }
40
41 if ( docCopyFieldProperties( dfTo, dfFrom ) )
42 {
43 docDeleteFieldFromList( dfl, dfTo );
44 return (DocumentField *)0;
45 }
46
47 dfTo->dfPage= -1;
48 dfTo->dfSelectionScope= *ss;
49 dfTo->dfHeadPosition= *epStart;
50
51 return dfTo;
52 }
53
docGetFieldByNumber(const DocumentFieldList * dfl,int n)54 DocumentField * docGetFieldByNumber( const DocumentFieldList * dfl,
55 int n )
56 {
57 void * vdf= utilPagedListGetItemByNumber( &(dfl->dflPagedList), n );
58
59 return (DocumentField *)vdf;
60 }
61
docGetFieldKindByNumber(const DocumentFieldList * dfl,int n)62 int docGetFieldKindByNumber( const DocumentFieldList * dfl,
63 int n )
64 {
65 DocumentField * df= docGetFieldByNumber( dfl, n );
66
67 if ( ! df )
68 { return -1; }
69
70 return df->dfKind;
71 }
72
docDeleteFieldFromList(DocumentFieldList * dfl,DocumentField * df)73 void docDeleteFieldFromList( DocumentFieldList * dfl,
74 DocumentField * df )
75 {
76 if ( docGetFieldByNumber( dfl, df->dfFieldNumber ) != df )
77 { LDEB(df->dfFieldNumber); }
78
79 utilPagedListDeleteItemByNumber( &(dfl->dflPagedList), df->dfFieldNumber );
80
81 return;
82 }
83
docClaimField(DocumentFieldList * dfl)84 DocumentField * docClaimField( DocumentFieldList * dfl )
85 {
86 void * vdf;
87 int n;
88 DocumentField * df;
89
90 vdf= utilPagedListClaimNewItem( &n, &(dfl->dflPagedList) );
91 if ( ! vdf )
92 { PDEB(vdf); return (DocumentField *)0; }
93
94 df= (DocumentField *)vdf;
95 df->dfFieldNumber= n;
96
97 return df;
98 }
99
docInitFieldList(DocumentFieldList * dfl)100 void docInitFieldList( DocumentFieldList * dfl )
101 {
102 utilInitPagedList( &(dfl->dflPagedList) );
103 utilStartPagedList( &(dfl->dflPagedList), sizeof(DocumentField),
104 (InitPagedListItem)docInitDocumentField,
105 (CleanPagedListItem)docCleanDocumentField );
106 return;
107 }
108
docCleanFieldList(DocumentFieldList * dfl)109 void docCleanFieldList( DocumentFieldList * dfl )
110 { utilCleanPagedList( &(dfl->dflPagedList) ); }
111
112 /************************************************************************/
113 /* */
114 /* Remember the page where a field occurs. */
115 /* */
116 /************************************************************************/
117
docSetPageOfField(DocumentFieldList * dfl,int n,int page)118 int docSetPageOfField( DocumentFieldList * dfl,
119 int n,
120 int page )
121 {
122 DocumentField * df= docGetFieldByNumber( dfl, n );
123
124 if ( ! df )
125 { LPDEB(n,df); return -1; }
126
127 df->dfPage= page;
128
129 return 0;
130 }
131
132 /************************************************************************/
133 /* */
134 /* Look for a bookmark in the field list. */
135 /* 1) Scan in reverse order to cope with duplicate bookmarks in the */
136 /* RTF parser. */
137 /* */
138 /************************************************************************/
139
docFindBookmarkField(DocumentField ** pDf,const DocumentFieldList * dfl,const MemoryBuffer * markName)140 int docFindBookmarkField( DocumentField ** pDf,
141 const DocumentFieldList * dfl,
142 const MemoryBuffer * markName )
143 {
144 int n;
145 const int fieldCount= dfl->dflPagedList.plItemCount;
146
147 /* 1 */
148 for ( n= fieldCount- 1; n >= 0; n-- )
149 {
150 DocumentField * df= docGetFieldByNumber( dfl, n );
151
152 if ( ! df )
153 { continue; }
154
155 if ( docFieldMatchesBookmark( df, markName ) )
156 { *pDf= df; return n; }
157 }
158
159 return -1;
160 }
161
162 /************************************************************************/
163 /* */
164 /* Build a list of bookmarks to be used in a GUI. */
165 /* */
166 /************************************************************************/
167
docCompareBookmarkStrings(const void * pv1,const void * pv2)168 static int docCompareBookmarkStrings( const void * pv1,
169 const void * pv2 )
170 {
171 const char * const * ps1= (const char * const *)pv1;
172 const char * const * ps2= (const char * const *)pv2;
173
174 return strcmp( *ps1, *ps2 );
175 }
176
docMakeBookmarkList(char *** pBookmarks,int * pBookmarkCount,int includeTocMarks,const DocumentFieldList * dfl)177 int docMakeBookmarkList( char *** pBookmarks,
178 int * pBookmarkCount,
179 int includeTocMarks,
180 const DocumentFieldList * dfl )
181 {
182 int rval= 0;
183 int n;
184
185 int bookmarkCount= 0;
186 char ** bookmarks= (char **)0;
187 const int fieldCount= dfl->dflPagedList.plItemCount;
188
189 const MemoryBuffer * mbBookmark;
190
191 if ( fieldCount == 0 )
192 { goto ready; }
193
194 /* 2 */
195 bookmarks= (char **)malloc( fieldCount* sizeof(char *) );
196 if ( ! bookmarks )
197 { LXDEB(fieldCount,bookmarks); rval= -1; goto ready; }
198
199 for ( n= 0; n < fieldCount; n++ )
200 {
201 DocumentField * df= docGetFieldByNumber( dfl, n );
202 int size;
203
204 if ( ! df )
205 { continue; }
206
207 if ( df->dfKind != DOCfkBOOKMARK ||
208 docFieldGetBookmark( &mbBookmark, df ) )
209 { continue; }
210
211 size= mbBookmark->mbSize;
212 if ( size == 0 ||
213 ( ! includeTocMarks && mbBookmark->mbBytes[0] == '_' ) ||
214 size > DOCmaxBOOKMARK )
215 { continue; }
216
217 bookmarks[bookmarkCount]= (char *)malloc( size+ 1 );
218 if ( ! bookmarks[bookmarkCount] )
219 { LXDEB(size,bookmarks[bookmarkCount]); rval= -1; goto ready; }
220
221 strncpy( bookmarks[bookmarkCount],
222 (char *)mbBookmark->mbBytes, size )[size]= '\0';
223 bookmarkCount++;
224 }
225
226 /* 3 */
227 qsort( bookmarks, bookmarkCount, sizeof(char *),
228 docCompareBookmarkStrings );
229
230 *pBookmarks= bookmarks; bookmarks= (char **)0; /* steal */
231 *pBookmarkCount= bookmarkCount; bookmarkCount= 0;
232
233 ready:
234
235 if ( bookmarks )
236 {
237 for ( n= 0; n < bookmarkCount; n++ )
238 {
239 if ( bookmarks[n] )
240 { free( bookmarks[n] ); }
241 }
242
243 free( bookmarks );
244 }
245
246 return rval;
247 }
248
249