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