xref: /aosp_15_r20/external/libcups/cgi-bin/help-index.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Online help index routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include "cgi-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include <cups/dir.h>
17*5e7646d2SAndroid Build Coastguard Worker 
18*5e7646d2SAndroid Build Coastguard Worker 
19*5e7646d2SAndroid Build Coastguard Worker /*
20*5e7646d2SAndroid Build Coastguard Worker  * List of common English words that should not be indexed...
21*5e7646d2SAndroid Build Coastguard Worker  */
22*5e7646d2SAndroid Build Coastguard Worker 
23*5e7646d2SAndroid Build Coastguard Worker static char		help_common_words[][6] =
24*5e7646d2SAndroid Build Coastguard Worker 			{
25*5e7646d2SAndroid Build Coastguard Worker 			  "about",
26*5e7646d2SAndroid Build Coastguard Worker 			  "all",
27*5e7646d2SAndroid Build Coastguard Worker 			  "an",
28*5e7646d2SAndroid Build Coastguard Worker 			  "and",
29*5e7646d2SAndroid Build Coastguard Worker 			  "are",
30*5e7646d2SAndroid Build Coastguard Worker 			  "as",
31*5e7646d2SAndroid Build Coastguard Worker 			  "at",
32*5e7646d2SAndroid Build Coastguard Worker 			  "be",
33*5e7646d2SAndroid Build Coastguard Worker 			  "been",
34*5e7646d2SAndroid Build Coastguard Worker 			  "but",
35*5e7646d2SAndroid Build Coastguard Worker 			  "by",
36*5e7646d2SAndroid Build Coastguard Worker 			  "call",
37*5e7646d2SAndroid Build Coastguard Worker 			  "can",
38*5e7646d2SAndroid Build Coastguard Worker 			  "come",
39*5e7646d2SAndroid Build Coastguard Worker 			  "could",
40*5e7646d2SAndroid Build Coastguard Worker 			  "day",
41*5e7646d2SAndroid Build Coastguard Worker 			  "did",
42*5e7646d2SAndroid Build Coastguard Worker 			  "do",
43*5e7646d2SAndroid Build Coastguard Worker 			  "down",
44*5e7646d2SAndroid Build Coastguard Worker 			  "each",
45*5e7646d2SAndroid Build Coastguard Worker 			  "find",
46*5e7646d2SAndroid Build Coastguard Worker 			  "first",
47*5e7646d2SAndroid Build Coastguard Worker 			  "for",
48*5e7646d2SAndroid Build Coastguard Worker 			  "from",
49*5e7646d2SAndroid Build Coastguard Worker 			  "go",
50*5e7646d2SAndroid Build Coastguard Worker 			  "had",
51*5e7646d2SAndroid Build Coastguard Worker 			  "has",
52*5e7646d2SAndroid Build Coastguard Worker 			  "have",
53*5e7646d2SAndroid Build Coastguard Worker 			  "he",
54*5e7646d2SAndroid Build Coastguard Worker 			  "her",
55*5e7646d2SAndroid Build Coastguard Worker 			  "him",
56*5e7646d2SAndroid Build Coastguard Worker 			  "his",
57*5e7646d2SAndroid Build Coastguard Worker 			  "hot",
58*5e7646d2SAndroid Build Coastguard Worker 			  "how",
59*5e7646d2SAndroid Build Coastguard Worker 			  "if",
60*5e7646d2SAndroid Build Coastguard Worker 			  "in",
61*5e7646d2SAndroid Build Coastguard Worker 			  "is",
62*5e7646d2SAndroid Build Coastguard Worker 			  "it",
63*5e7646d2SAndroid Build Coastguard Worker 			  "know",
64*5e7646d2SAndroid Build Coastguard Worker 			  "like",
65*5e7646d2SAndroid Build Coastguard Worker 			  "long",
66*5e7646d2SAndroid Build Coastguard Worker 			  "look",
67*5e7646d2SAndroid Build Coastguard Worker 			  "make",
68*5e7646d2SAndroid Build Coastguard Worker 			  "many",
69*5e7646d2SAndroid Build Coastguard Worker 			  "may",
70*5e7646d2SAndroid Build Coastguard Worker 			  "more",
71*5e7646d2SAndroid Build Coastguard Worker 			  "most",
72*5e7646d2SAndroid Build Coastguard Worker 			  "my",
73*5e7646d2SAndroid Build Coastguard Worker 			  "no",
74*5e7646d2SAndroid Build Coastguard Worker 			  "now",
75*5e7646d2SAndroid Build Coastguard Worker 			  "of",
76*5e7646d2SAndroid Build Coastguard Worker 			  "on",
77*5e7646d2SAndroid Build Coastguard Worker 			  "one",
78*5e7646d2SAndroid Build Coastguard Worker 			  "or",
79*5e7646d2SAndroid Build Coastguard Worker 			  "other",
80*5e7646d2SAndroid Build Coastguard Worker 			  "out",
81*5e7646d2SAndroid Build Coastguard Worker 			  "over",
82*5e7646d2SAndroid Build Coastguard Worker 			  "said",
83*5e7646d2SAndroid Build Coastguard Worker 			  "see",
84*5e7646d2SAndroid Build Coastguard Worker 			  "she",
85*5e7646d2SAndroid Build Coastguard Worker 			  "side",
86*5e7646d2SAndroid Build Coastguard Worker 			  "so",
87*5e7646d2SAndroid Build Coastguard Worker 			  "some",
88*5e7646d2SAndroid Build Coastguard Worker 			  "sound",
89*5e7646d2SAndroid Build Coastguard Worker 			  "than",
90*5e7646d2SAndroid Build Coastguard Worker 			  "that",
91*5e7646d2SAndroid Build Coastguard Worker 			  "the",
92*5e7646d2SAndroid Build Coastguard Worker 			  "their",
93*5e7646d2SAndroid Build Coastguard Worker 			  "them",
94*5e7646d2SAndroid Build Coastguard Worker 			  "then",
95*5e7646d2SAndroid Build Coastguard Worker 			  "there",
96*5e7646d2SAndroid Build Coastguard Worker 			  "these",
97*5e7646d2SAndroid Build Coastguard Worker 			  "they",
98*5e7646d2SAndroid Build Coastguard Worker 			  "thing",
99*5e7646d2SAndroid Build Coastguard Worker 			  "this",
100*5e7646d2SAndroid Build Coastguard Worker 			  "time",
101*5e7646d2SAndroid Build Coastguard Worker 			  "to",
102*5e7646d2SAndroid Build Coastguard Worker 			  "two",
103*5e7646d2SAndroid Build Coastguard Worker 			  "up",
104*5e7646d2SAndroid Build Coastguard Worker 			  "use",
105*5e7646d2SAndroid Build Coastguard Worker 			  "was",
106*5e7646d2SAndroid Build Coastguard Worker 			  "water",
107*5e7646d2SAndroid Build Coastguard Worker 			  "way",
108*5e7646d2SAndroid Build Coastguard Worker 			  "we",
109*5e7646d2SAndroid Build Coastguard Worker 			  "were",
110*5e7646d2SAndroid Build Coastguard Worker 			  "what",
111*5e7646d2SAndroid Build Coastguard Worker 			  "when",
112*5e7646d2SAndroid Build Coastguard Worker 			  "which",
113*5e7646d2SAndroid Build Coastguard Worker 			  "who",
114*5e7646d2SAndroid Build Coastguard Worker 			  "will",
115*5e7646d2SAndroid Build Coastguard Worker 			  "with",
116*5e7646d2SAndroid Build Coastguard Worker 			  "word",
117*5e7646d2SAndroid Build Coastguard Worker 			  "would",
118*5e7646d2SAndroid Build Coastguard Worker 			  "write",
119*5e7646d2SAndroid Build Coastguard Worker 			  "you",
120*5e7646d2SAndroid Build Coastguard Worker 			  "your"
121*5e7646d2SAndroid Build Coastguard Worker 			};
122*5e7646d2SAndroid Build Coastguard Worker 
123*5e7646d2SAndroid Build Coastguard Worker 
124*5e7646d2SAndroid Build Coastguard Worker /*
125*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
126*5e7646d2SAndroid Build Coastguard Worker  */
127*5e7646d2SAndroid Build Coastguard Worker 
128*5e7646d2SAndroid Build Coastguard Worker static help_word_t	*help_add_word(help_node_t *n, const char *text);
129*5e7646d2SAndroid Build Coastguard Worker static void		help_delete_node(help_node_t *n);
130*5e7646d2SAndroid Build Coastguard Worker static void		help_delete_word(help_word_t *w);
131*5e7646d2SAndroid Build Coastguard Worker static int		help_load_directory(help_index_t *hi,
132*5e7646d2SAndroid Build Coastguard Worker 			                    const char *directory,
133*5e7646d2SAndroid Build Coastguard Worker 					    const char *relative);
134*5e7646d2SAndroid Build Coastguard Worker static int		help_load_file(help_index_t *hi,
135*5e7646d2SAndroid Build Coastguard Worker 			               const char *filename,
136*5e7646d2SAndroid Build Coastguard Worker 				       const char *relative,
137*5e7646d2SAndroid Build Coastguard Worker 				       time_t     mtime);
138*5e7646d2SAndroid Build Coastguard Worker static help_node_t	*help_new_node(const char *filename, const char *anchor, const char *section, const char *text, time_t mtime, off_t offset, size_t length) _CUPS_NONNULL(1,3,4);
139*5e7646d2SAndroid Build Coastguard Worker static int		help_sort_by_name(help_node_t *p1, help_node_t *p2);
140*5e7646d2SAndroid Build Coastguard Worker static int		help_sort_by_score(help_node_t *p1, help_node_t *p2);
141*5e7646d2SAndroid Build Coastguard Worker static int		help_sort_words(help_word_t *w1, help_word_t *w2);
142*5e7646d2SAndroid Build Coastguard Worker 
143*5e7646d2SAndroid Build Coastguard Worker 
144*5e7646d2SAndroid Build Coastguard Worker /*
145*5e7646d2SAndroid Build Coastguard Worker  * 'helpDeleteIndex()' - Delete an index, freeing all memory used.
146*5e7646d2SAndroid Build Coastguard Worker  */
147*5e7646d2SAndroid Build Coastguard Worker 
148*5e7646d2SAndroid Build Coastguard Worker void
helpDeleteIndex(help_index_t * hi)149*5e7646d2SAndroid Build Coastguard Worker helpDeleteIndex(help_index_t *hi)	/* I - Help index */
150*5e7646d2SAndroid Build Coastguard Worker {
151*5e7646d2SAndroid Build Coastguard Worker   help_node_t	*node;			/* Current node */
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker 
154*5e7646d2SAndroid Build Coastguard Worker   if (!hi)
155*5e7646d2SAndroid Build Coastguard Worker     return;
156*5e7646d2SAndroid Build Coastguard Worker 
157*5e7646d2SAndroid Build Coastguard Worker   for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
158*5e7646d2SAndroid Build Coastguard Worker        node;
159*5e7646d2SAndroid Build Coastguard Worker        node = (help_node_t *)cupsArrayNext(hi->nodes))
160*5e7646d2SAndroid Build Coastguard Worker   {
161*5e7646d2SAndroid Build Coastguard Worker     if (!hi->search)
162*5e7646d2SAndroid Build Coastguard Worker       help_delete_node(node);
163*5e7646d2SAndroid Build Coastguard Worker   }
164*5e7646d2SAndroid Build Coastguard Worker 
165*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(hi->nodes);
166*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(hi->sorted);
167*5e7646d2SAndroid Build Coastguard Worker 
168*5e7646d2SAndroid Build Coastguard Worker   free(hi);
169*5e7646d2SAndroid Build Coastguard Worker }
170*5e7646d2SAndroid Build Coastguard Worker 
171*5e7646d2SAndroid Build Coastguard Worker 
172*5e7646d2SAndroid Build Coastguard Worker /*
173*5e7646d2SAndroid Build Coastguard Worker  * 'helpFindNode()' - Find a node in an index.
174*5e7646d2SAndroid Build Coastguard Worker  */
175*5e7646d2SAndroid Build Coastguard Worker 
176*5e7646d2SAndroid Build Coastguard Worker help_node_t *				/* O - Node pointer or NULL */
helpFindNode(help_index_t * hi,const char * filename,const char * anchor)177*5e7646d2SAndroid Build Coastguard Worker helpFindNode(help_index_t *hi,		/* I - Index */
178*5e7646d2SAndroid Build Coastguard Worker              const char   *filename,	/* I - Filename */
179*5e7646d2SAndroid Build Coastguard Worker              const char   *anchor)	/* I - Anchor */
180*5e7646d2SAndroid Build Coastguard Worker {
181*5e7646d2SAndroid Build Coastguard Worker   help_node_t	key;			/* Search key */
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker  /*
185*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
186*5e7646d2SAndroid Build Coastguard Worker   */
187*5e7646d2SAndroid Build Coastguard Worker 
188*5e7646d2SAndroid Build Coastguard Worker   if (!hi || !filename)
189*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
190*5e7646d2SAndroid Build Coastguard Worker 
191*5e7646d2SAndroid Build Coastguard Worker  /*
192*5e7646d2SAndroid Build Coastguard Worker   * Initialize the search key...
193*5e7646d2SAndroid Build Coastguard Worker   */
194*5e7646d2SAndroid Build Coastguard Worker 
195*5e7646d2SAndroid Build Coastguard Worker   key.filename = (char *)filename;
196*5e7646d2SAndroid Build Coastguard Worker   key.anchor   = (char *)anchor;
197*5e7646d2SAndroid Build Coastguard Worker 
198*5e7646d2SAndroid Build Coastguard Worker  /*
199*5e7646d2SAndroid Build Coastguard Worker   * Return any match...
200*5e7646d2SAndroid Build Coastguard Worker   */
201*5e7646d2SAndroid Build Coastguard Worker 
202*5e7646d2SAndroid Build Coastguard Worker   return ((help_node_t *)cupsArrayFind(hi->nodes, &key));
203*5e7646d2SAndroid Build Coastguard Worker }
204*5e7646d2SAndroid Build Coastguard Worker 
205*5e7646d2SAndroid Build Coastguard Worker 
206*5e7646d2SAndroid Build Coastguard Worker /*
207*5e7646d2SAndroid Build Coastguard Worker  * 'helpLoadIndex()' - Load a help index from disk.
208*5e7646d2SAndroid Build Coastguard Worker  */
209*5e7646d2SAndroid Build Coastguard Worker 
210*5e7646d2SAndroid Build Coastguard Worker help_index_t *				/* O - Index pointer or NULL */
helpLoadIndex(const char * hifile,const char * directory)211*5e7646d2SAndroid Build Coastguard Worker helpLoadIndex(const char *hifile,	/* I - Index filename */
212*5e7646d2SAndroid Build Coastguard Worker               const char *directory)	/* I - Directory that is indexed */
213*5e7646d2SAndroid Build Coastguard Worker {
214*5e7646d2SAndroid Build Coastguard Worker   help_index_t	*hi;			/* Help index */
215*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* Current file */
216*5e7646d2SAndroid Build Coastguard Worker   char		line[2048],		/* Line from file */
217*5e7646d2SAndroid Build Coastguard Worker 		*ptr,			/* Pointer into line */
218*5e7646d2SAndroid Build Coastguard Worker 		*filename,		/* Filename in line */
219*5e7646d2SAndroid Build Coastguard Worker 		*anchor,		/* Anchor in line */
220*5e7646d2SAndroid Build Coastguard Worker 		*sectptr,		/* Section pointer in line */
221*5e7646d2SAndroid Build Coastguard Worker 		section[1024],		/* Section name */
222*5e7646d2SAndroid Build Coastguard Worker 		*text;			/* Text in line */
223*5e7646d2SAndroid Build Coastguard Worker   time_t	mtime;			/* Modification time */
224*5e7646d2SAndroid Build Coastguard Worker   off_t		offset;			/* Offset into file */
225*5e7646d2SAndroid Build Coastguard Worker   size_t	length;			/* Length in bytes */
226*5e7646d2SAndroid Build Coastguard Worker   int		update;			/* Update? */
227*5e7646d2SAndroid Build Coastguard Worker   help_node_t	*node;			/* Current node */
228*5e7646d2SAndroid Build Coastguard Worker   help_word_t	*word;			/* Current word */
229*5e7646d2SAndroid Build Coastguard Worker 
230*5e7646d2SAndroid Build Coastguard Worker 
231*5e7646d2SAndroid Build Coastguard Worker  /*
232*5e7646d2SAndroid Build Coastguard Worker   * Create a new, empty index.
233*5e7646d2SAndroid Build Coastguard Worker   */
234*5e7646d2SAndroid Build Coastguard Worker 
235*5e7646d2SAndroid Build Coastguard Worker   if ((hi = (help_index_t *)calloc(1, sizeof(help_index_t))) == NULL)
236*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
237*5e7646d2SAndroid Build Coastguard Worker 
238*5e7646d2SAndroid Build Coastguard Worker   hi->nodes  = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
239*5e7646d2SAndroid Build Coastguard Worker   hi->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
240*5e7646d2SAndroid Build Coastguard Worker 
241*5e7646d2SAndroid Build Coastguard Worker   if (!hi->nodes || !hi->sorted)
242*5e7646d2SAndroid Build Coastguard Worker   {
243*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(hi->nodes);
244*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(hi->sorted);
245*5e7646d2SAndroid Build Coastguard Worker     free(hi);
246*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
247*5e7646d2SAndroid Build Coastguard Worker   }
248*5e7646d2SAndroid Build Coastguard Worker 
249*5e7646d2SAndroid Build Coastguard Worker  /*
250*5e7646d2SAndroid Build Coastguard Worker   * Try loading the existing index file...
251*5e7646d2SAndroid Build Coastguard Worker   */
252*5e7646d2SAndroid Build Coastguard Worker 
253*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(hifile, "r")) != NULL)
254*5e7646d2SAndroid Build Coastguard Worker   {
255*5e7646d2SAndroid Build Coastguard Worker    /*
256*5e7646d2SAndroid Build Coastguard Worker     * Lock the file and then read the first line...
257*5e7646d2SAndroid Build Coastguard Worker     */
258*5e7646d2SAndroid Build Coastguard Worker 
259*5e7646d2SAndroid Build Coastguard Worker     cupsFileLock(fp, 1);
260*5e7646d2SAndroid Build Coastguard Worker 
261*5e7646d2SAndroid Build Coastguard Worker     if (cupsFileGets(fp, line, sizeof(line)) && !strcmp(line, "HELPV2"))
262*5e7646d2SAndroid Build Coastguard Worker     {
263*5e7646d2SAndroid Build Coastguard Worker      /*
264*5e7646d2SAndroid Build Coastguard Worker       * Got a valid header line, now read the data lines...
265*5e7646d2SAndroid Build Coastguard Worker       */
266*5e7646d2SAndroid Build Coastguard Worker 
267*5e7646d2SAndroid Build Coastguard Worker       node = NULL;
268*5e7646d2SAndroid Build Coastguard Worker 
269*5e7646d2SAndroid Build Coastguard Worker       while (cupsFileGets(fp, line, sizeof(line)))
270*5e7646d2SAndroid Build Coastguard Worker       {
271*5e7646d2SAndroid Build Coastguard Worker        /*
272*5e7646d2SAndroid Build Coastguard Worker 	* Each line looks like one of the following:
273*5e7646d2SAndroid Build Coastguard Worker 	*
274*5e7646d2SAndroid Build Coastguard Worker 	*     filename mtime offset length "section" "text"
275*5e7646d2SAndroid Build Coastguard Worker 	*     filename#anchor offset length "text"
276*5e7646d2SAndroid Build Coastguard Worker 	*     SP count word
277*5e7646d2SAndroid Build Coastguard Worker 	*/
278*5e7646d2SAndroid Build Coastguard Worker 
279*5e7646d2SAndroid Build Coastguard Worker         if (line[0] == ' ')
280*5e7646d2SAndroid Build Coastguard Worker 	{
281*5e7646d2SAndroid Build Coastguard Worker 	 /*
282*5e7646d2SAndroid Build Coastguard Worker 	  * Read a word in the current node...
283*5e7646d2SAndroid Build Coastguard Worker 	  */
284*5e7646d2SAndroid Build Coastguard Worker 
285*5e7646d2SAndroid Build Coastguard Worker           if (!node || (ptr = strrchr(line, ' ')) == NULL)
286*5e7646d2SAndroid Build Coastguard Worker 	    continue;
287*5e7646d2SAndroid Build Coastguard Worker 
288*5e7646d2SAndroid Build Coastguard Worker           if ((word = help_add_word(node, ptr + 1)) != NULL)
289*5e7646d2SAndroid Build Coastguard Worker 	    word->count = atoi(line + 1);
290*5e7646d2SAndroid Build Coastguard Worker         }
291*5e7646d2SAndroid Build Coastguard Worker 	else
292*5e7646d2SAndroid Build Coastguard Worker 	{
293*5e7646d2SAndroid Build Coastguard Worker 	 /*
294*5e7646d2SAndroid Build Coastguard Worker 	  * Add a node...
295*5e7646d2SAndroid Build Coastguard Worker 	  */
296*5e7646d2SAndroid Build Coastguard Worker 
297*5e7646d2SAndroid Build Coastguard Worker 	  filename = line;
298*5e7646d2SAndroid Build Coastguard Worker 
299*5e7646d2SAndroid Build Coastguard Worker 	  if ((ptr = strchr(line, ' ')) == NULL)
300*5e7646d2SAndroid Build Coastguard Worker             break;
301*5e7646d2SAndroid Build Coastguard Worker 
302*5e7646d2SAndroid Build Coastguard Worker 	  while (isspace(*ptr & 255))
303*5e7646d2SAndroid Build Coastguard Worker             *ptr++ = '\0';
304*5e7646d2SAndroid Build Coastguard Worker 
305*5e7646d2SAndroid Build Coastguard Worker 	  if ((anchor = strrchr(filename, '#')) != NULL)
306*5e7646d2SAndroid Build Coastguard Worker 	  {
307*5e7646d2SAndroid Build Coastguard Worker             *anchor++ = '\0';
308*5e7646d2SAndroid Build Coastguard Worker 	    mtime = 0;
309*5e7646d2SAndroid Build Coastguard Worker 	  }
310*5e7646d2SAndroid Build Coastguard Worker 	  else
311*5e7646d2SAndroid Build Coastguard Worker 	    mtime = strtol(ptr, &ptr, 10);
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker 	  offset = strtoll(ptr, &ptr, 10);
314*5e7646d2SAndroid Build Coastguard Worker 	  length = (size_t)strtoll(ptr, &ptr, 10);
315*5e7646d2SAndroid Build Coastguard Worker 
316*5e7646d2SAndroid Build Coastguard Worker 	  while (isspace(*ptr & 255))
317*5e7646d2SAndroid Build Coastguard Worker             ptr ++;
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker           if (!anchor)
320*5e7646d2SAndroid Build Coastguard Worker 	  {
321*5e7646d2SAndroid Build Coastguard Worker 	   /*
322*5e7646d2SAndroid Build Coastguard Worker 	    * Get section...
323*5e7646d2SAndroid Build Coastguard Worker 	    */
324*5e7646d2SAndroid Build Coastguard Worker 
325*5e7646d2SAndroid Build Coastguard Worker             if (*ptr != '\"')
326*5e7646d2SAndroid Build Coastguard Worker 	      break;
327*5e7646d2SAndroid Build Coastguard Worker 
328*5e7646d2SAndroid Build Coastguard Worker             ptr ++;
329*5e7646d2SAndroid Build Coastguard Worker 	    sectptr = ptr;
330*5e7646d2SAndroid Build Coastguard Worker 
331*5e7646d2SAndroid Build Coastguard Worker             while (*ptr && *ptr != '\"')
332*5e7646d2SAndroid Build Coastguard Worker 	      ptr ++;
333*5e7646d2SAndroid Build Coastguard Worker 
334*5e7646d2SAndroid Build Coastguard Worker             if (*ptr != '\"')
335*5e7646d2SAndroid Build Coastguard Worker 	      break;
336*5e7646d2SAndroid Build Coastguard Worker 
337*5e7646d2SAndroid Build Coastguard Worker             *ptr++ = '\0';
338*5e7646d2SAndroid Build Coastguard Worker 
339*5e7646d2SAndroid Build Coastguard Worker             strlcpy(section, sectptr, sizeof(section));
340*5e7646d2SAndroid Build Coastguard Worker 
341*5e7646d2SAndroid Build Coastguard Worker 	    while (isspace(*ptr & 255))
342*5e7646d2SAndroid Build Coastguard Worker               ptr ++;
343*5e7646d2SAndroid Build Coastguard Worker           }
344*5e7646d2SAndroid Build Coastguard Worker           else
345*5e7646d2SAndroid Build Coastguard Worker             section[0] = '\0';
346*5e7646d2SAndroid Build Coastguard Worker 
347*5e7646d2SAndroid Build Coastguard Worker           if (*ptr != '\"')
348*5e7646d2SAndroid Build Coastguard Worker 	    break;
349*5e7646d2SAndroid Build Coastguard Worker 
350*5e7646d2SAndroid Build Coastguard Worker           ptr ++;
351*5e7646d2SAndroid Build Coastguard Worker 	  text = ptr;
352*5e7646d2SAndroid Build Coastguard Worker 
353*5e7646d2SAndroid Build Coastguard Worker           while (*ptr && *ptr != '\"')
354*5e7646d2SAndroid Build Coastguard Worker 	    ptr ++;
355*5e7646d2SAndroid Build Coastguard Worker 
356*5e7646d2SAndroid Build Coastguard Worker           if (*ptr != '\"')
357*5e7646d2SAndroid Build Coastguard Worker 	    break;
358*5e7646d2SAndroid Build Coastguard Worker 
359*5e7646d2SAndroid Build Coastguard Worker           *ptr++ = '\0';
360*5e7646d2SAndroid Build Coastguard Worker 
361*5e7646d2SAndroid Build Coastguard Worker 	  if ((node = help_new_node(filename, anchor, section, text,
362*5e7646d2SAndroid Build Coastguard Worker 				    mtime, offset, length)) == NULL)
363*5e7646d2SAndroid Build Coastguard Worker             break;
364*5e7646d2SAndroid Build Coastguard Worker 
365*5e7646d2SAndroid Build Coastguard Worker 	  node->score = -1;
366*5e7646d2SAndroid Build Coastguard Worker 
367*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayAdd(hi->nodes, node);
368*5e7646d2SAndroid Build Coastguard Worker         }
369*5e7646d2SAndroid Build Coastguard Worker       }
370*5e7646d2SAndroid Build Coastguard Worker     }
371*5e7646d2SAndroid Build Coastguard Worker 
372*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
373*5e7646d2SAndroid Build Coastguard Worker   }
374*5e7646d2SAndroid Build Coastguard Worker 
375*5e7646d2SAndroid Build Coastguard Worker  /*
376*5e7646d2SAndroid Build Coastguard Worker   * Scan for new/updated files...
377*5e7646d2SAndroid Build Coastguard Worker   */
378*5e7646d2SAndroid Build Coastguard Worker 
379*5e7646d2SAndroid Build Coastguard Worker   update = help_load_directory(hi, directory, NULL);
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker  /*
382*5e7646d2SAndroid Build Coastguard Worker   * Remove any files that are no longer installed...
383*5e7646d2SAndroid Build Coastguard Worker   */
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker   for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
386*5e7646d2SAndroid Build Coastguard Worker        node;
387*5e7646d2SAndroid Build Coastguard Worker        node = (help_node_t *)cupsArrayNext(hi->nodes))
388*5e7646d2SAndroid Build Coastguard Worker     if (node->score < 0)
389*5e7646d2SAndroid Build Coastguard Worker     {
390*5e7646d2SAndroid Build Coastguard Worker      /*
391*5e7646d2SAndroid Build Coastguard Worker       * Delete this node...
392*5e7646d2SAndroid Build Coastguard Worker       */
393*5e7646d2SAndroid Build Coastguard Worker 
394*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRemove(hi->nodes, node);
395*5e7646d2SAndroid Build Coastguard Worker       help_delete_node(node);
396*5e7646d2SAndroid Build Coastguard Worker     }
397*5e7646d2SAndroid Build Coastguard Worker 
398*5e7646d2SAndroid Build Coastguard Worker  /*
399*5e7646d2SAndroid Build Coastguard Worker   * Add nodes to the sorted array...
400*5e7646d2SAndroid Build Coastguard Worker   */
401*5e7646d2SAndroid Build Coastguard Worker 
402*5e7646d2SAndroid Build Coastguard Worker   for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
403*5e7646d2SAndroid Build Coastguard Worker        node;
404*5e7646d2SAndroid Build Coastguard Worker        node = (help_node_t *)cupsArrayNext(hi->nodes))
405*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(hi->sorted, node);
406*5e7646d2SAndroid Build Coastguard Worker 
407*5e7646d2SAndroid Build Coastguard Worker  /*
408*5e7646d2SAndroid Build Coastguard Worker   * Save the index if we updated it...
409*5e7646d2SAndroid Build Coastguard Worker   */
410*5e7646d2SAndroid Build Coastguard Worker 
411*5e7646d2SAndroid Build Coastguard Worker   if (update)
412*5e7646d2SAndroid Build Coastguard Worker     helpSaveIndex(hi, hifile);
413*5e7646d2SAndroid Build Coastguard Worker 
414*5e7646d2SAndroid Build Coastguard Worker  /*
415*5e7646d2SAndroid Build Coastguard Worker   * Return the index...
416*5e7646d2SAndroid Build Coastguard Worker   */
417*5e7646d2SAndroid Build Coastguard Worker 
418*5e7646d2SAndroid Build Coastguard Worker   return (hi);
419*5e7646d2SAndroid Build Coastguard Worker }
420*5e7646d2SAndroid Build Coastguard Worker 
421*5e7646d2SAndroid Build Coastguard Worker 
422*5e7646d2SAndroid Build Coastguard Worker /*
423*5e7646d2SAndroid Build Coastguard Worker  * 'helpSaveIndex()' - Save a help index to disk.
424*5e7646d2SAndroid Build Coastguard Worker  */
425*5e7646d2SAndroid Build Coastguard Worker 
426*5e7646d2SAndroid Build Coastguard Worker int					/* O - 0 on success, -1 on error */
helpSaveIndex(help_index_t * hi,const char * hifile)427*5e7646d2SAndroid Build Coastguard Worker helpSaveIndex(help_index_t *hi,		/* I - Index */
428*5e7646d2SAndroid Build Coastguard Worker               const char   *hifile)	/* I - Index filename */
429*5e7646d2SAndroid Build Coastguard Worker {
430*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* Index file */
431*5e7646d2SAndroid Build Coastguard Worker   help_node_t	*node;			/* Current node */
432*5e7646d2SAndroid Build Coastguard Worker   help_word_t	*word;			/* Current word */
433*5e7646d2SAndroid Build Coastguard Worker 
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker  /*
436*5e7646d2SAndroid Build Coastguard Worker   * Try creating a new index file...
437*5e7646d2SAndroid Build Coastguard Worker   */
438*5e7646d2SAndroid Build Coastguard Worker 
439*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(hifile, "w9")) == NULL)
440*5e7646d2SAndroid Build Coastguard Worker     return (-1);
441*5e7646d2SAndroid Build Coastguard Worker 
442*5e7646d2SAndroid Build Coastguard Worker  /*
443*5e7646d2SAndroid Build Coastguard Worker   * Lock the file while we write it...
444*5e7646d2SAndroid Build Coastguard Worker   */
445*5e7646d2SAndroid Build Coastguard Worker 
446*5e7646d2SAndroid Build Coastguard Worker   cupsFileLock(fp, 1);
447*5e7646d2SAndroid Build Coastguard Worker 
448*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, "HELPV2\n");
449*5e7646d2SAndroid Build Coastguard Worker 
450*5e7646d2SAndroid Build Coastguard Worker   for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
451*5e7646d2SAndroid Build Coastguard Worker        node;
452*5e7646d2SAndroid Build Coastguard Worker        node = (help_node_t *)cupsArrayNext(hi->nodes))
453*5e7646d2SAndroid Build Coastguard Worker   {
454*5e7646d2SAndroid Build Coastguard Worker    /*
455*5e7646d2SAndroid Build Coastguard Worker     * Write the current node with/without the anchor...
456*5e7646d2SAndroid Build Coastguard Worker     */
457*5e7646d2SAndroid Build Coastguard Worker 
458*5e7646d2SAndroid Build Coastguard Worker     if (node->anchor)
459*5e7646d2SAndroid Build Coastguard Worker     {
460*5e7646d2SAndroid Build Coastguard Worker       if (cupsFilePrintf(fp, "%s#%s " CUPS_LLFMT " " CUPS_LLFMT " \"%s\"\n",
461*5e7646d2SAndroid Build Coastguard Worker                          node->filename, node->anchor,
462*5e7646d2SAndroid Build Coastguard Worker                          CUPS_LLCAST node->offset, CUPS_LLCAST node->length,
463*5e7646d2SAndroid Build Coastguard Worker 			 node->text) < 0)
464*5e7646d2SAndroid Build Coastguard Worker         break;
465*5e7646d2SAndroid Build Coastguard Worker     }
466*5e7646d2SAndroid Build Coastguard Worker     else
467*5e7646d2SAndroid Build Coastguard Worker     {
468*5e7646d2SAndroid Build Coastguard Worker       if (cupsFilePrintf(fp, "%s %d " CUPS_LLFMT " " CUPS_LLFMT " \"%s\" \"%s\"\n",
469*5e7646d2SAndroid Build Coastguard Worker                          node->filename, (int)node->mtime,
470*5e7646d2SAndroid Build Coastguard Worker                          CUPS_LLCAST node->offset, CUPS_LLCAST node->length,
471*5e7646d2SAndroid Build Coastguard Worker 			 node->section ? node->section : "", node->text) < 0)
472*5e7646d2SAndroid Build Coastguard Worker         break;
473*5e7646d2SAndroid Build Coastguard Worker     }
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker    /*
476*5e7646d2SAndroid Build Coastguard Worker     * Then write the words associated with the node...
477*5e7646d2SAndroid Build Coastguard Worker     */
478*5e7646d2SAndroid Build Coastguard Worker 
479*5e7646d2SAndroid Build Coastguard Worker     for (word = (help_word_t *)cupsArrayFirst(node->words);
480*5e7646d2SAndroid Build Coastguard Worker          word;
481*5e7646d2SAndroid Build Coastguard Worker 	 word = (help_word_t *)cupsArrayNext(node->words))
482*5e7646d2SAndroid Build Coastguard Worker       if (cupsFilePrintf(fp, " %d %s\n", word->count, word->text) < 0)
483*5e7646d2SAndroid Build Coastguard Worker         break;
484*5e7646d2SAndroid Build Coastguard Worker   }
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker   cupsFileFlush(fp);
487*5e7646d2SAndroid Build Coastguard Worker 
488*5e7646d2SAndroid Build Coastguard Worker   if (cupsFileClose(fp) < 0)
489*5e7646d2SAndroid Build Coastguard Worker     return (-1);
490*5e7646d2SAndroid Build Coastguard Worker   else if (node)
491*5e7646d2SAndroid Build Coastguard Worker     return (-1);
492*5e7646d2SAndroid Build Coastguard Worker   else
493*5e7646d2SAndroid Build Coastguard Worker     return (0);
494*5e7646d2SAndroid Build Coastguard Worker }
495*5e7646d2SAndroid Build Coastguard Worker 
496*5e7646d2SAndroid Build Coastguard Worker 
497*5e7646d2SAndroid Build Coastguard Worker /*
498*5e7646d2SAndroid Build Coastguard Worker  * 'helpSearchIndex()' - Search an index.
499*5e7646d2SAndroid Build Coastguard Worker  */
500*5e7646d2SAndroid Build Coastguard Worker 
501*5e7646d2SAndroid Build Coastguard Worker help_index_t *				/* O - Search index */
helpSearchIndex(help_index_t * hi,const char * query,const char * section,const char * filename)502*5e7646d2SAndroid Build Coastguard Worker helpSearchIndex(help_index_t *hi,	/* I - Index */
503*5e7646d2SAndroid Build Coastguard Worker                 const char   *query,	/* I - Query string */
504*5e7646d2SAndroid Build Coastguard Worker 		const char   *section,	/* I - Limit search to this section */
505*5e7646d2SAndroid Build Coastguard Worker 		const char   *filename)	/* I - Limit search to this file */
506*5e7646d2SAndroid Build Coastguard Worker {
507*5e7646d2SAndroid Build Coastguard Worker   help_index_t	*search;		/* Search index */
508*5e7646d2SAndroid Build Coastguard Worker   help_node_t	*node;			/* Current node */
509*5e7646d2SAndroid Build Coastguard Worker   help_word_t	*word;			/* Current word */
510*5e7646d2SAndroid Build Coastguard Worker   void		*sc;			/* Search context */
511*5e7646d2SAndroid Build Coastguard Worker   int		matches;		/* Number of matches */
512*5e7646d2SAndroid Build Coastguard Worker 
513*5e7646d2SAndroid Build Coastguard Worker 
514*5e7646d2SAndroid Build Coastguard Worker  /*
515*5e7646d2SAndroid Build Coastguard Worker   * Range check...
516*5e7646d2SAndroid Build Coastguard Worker   */
517*5e7646d2SAndroid Build Coastguard Worker 
518*5e7646d2SAndroid Build Coastguard Worker   if (!hi || !query)
519*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
520*5e7646d2SAndroid Build Coastguard Worker 
521*5e7646d2SAndroid Build Coastguard Worker  /*
522*5e7646d2SAndroid Build Coastguard Worker   * Reset the scores of all nodes to 0...
523*5e7646d2SAndroid Build Coastguard Worker   */
524*5e7646d2SAndroid Build Coastguard Worker 
525*5e7646d2SAndroid Build Coastguard Worker   for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
526*5e7646d2SAndroid Build Coastguard Worker        node;
527*5e7646d2SAndroid Build Coastguard Worker        node = (help_node_t *)cupsArrayNext(hi->nodes))
528*5e7646d2SAndroid Build Coastguard Worker     node->score = 0;
529*5e7646d2SAndroid Build Coastguard Worker 
530*5e7646d2SAndroid Build Coastguard Worker  /*
531*5e7646d2SAndroid Build Coastguard Worker   * Find the first node to search in...
532*5e7646d2SAndroid Build Coastguard Worker   */
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker   if (filename)
535*5e7646d2SAndroid Build Coastguard Worker   {
536*5e7646d2SAndroid Build Coastguard Worker     node = helpFindNode(hi, filename, NULL);
537*5e7646d2SAndroid Build Coastguard Worker     if (!node)
538*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
539*5e7646d2SAndroid Build Coastguard Worker   }
540*5e7646d2SAndroid Build Coastguard Worker   else
541*5e7646d2SAndroid Build Coastguard Worker     node = (help_node_t *)cupsArrayFirst(hi->nodes);
542*5e7646d2SAndroid Build Coastguard Worker 
543*5e7646d2SAndroid Build Coastguard Worker  /*
544*5e7646d2SAndroid Build Coastguard Worker   * Convert the query into a regular expression...
545*5e7646d2SAndroid Build Coastguard Worker   */
546*5e7646d2SAndroid Build Coastguard Worker 
547*5e7646d2SAndroid Build Coastguard Worker   sc = cgiCompileSearch(query);
548*5e7646d2SAndroid Build Coastguard Worker   if (!sc)
549*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
550*5e7646d2SAndroid Build Coastguard Worker 
551*5e7646d2SAndroid Build Coastguard Worker  /*
552*5e7646d2SAndroid Build Coastguard Worker   * Allocate a search index...
553*5e7646d2SAndroid Build Coastguard Worker   */
554*5e7646d2SAndroid Build Coastguard Worker 
555*5e7646d2SAndroid Build Coastguard Worker   search = calloc(1, sizeof(help_index_t));
556*5e7646d2SAndroid Build Coastguard Worker   if (!search)
557*5e7646d2SAndroid Build Coastguard Worker   {
558*5e7646d2SAndroid Build Coastguard Worker     cgiFreeSearch(sc);
559*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
560*5e7646d2SAndroid Build Coastguard Worker   }
561*5e7646d2SAndroid Build Coastguard Worker 
562*5e7646d2SAndroid Build Coastguard Worker   search->nodes  = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
563*5e7646d2SAndroid Build Coastguard Worker   search->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
564*5e7646d2SAndroid Build Coastguard Worker 
565*5e7646d2SAndroid Build Coastguard Worker   if (!search->nodes || !search->sorted)
566*5e7646d2SAndroid Build Coastguard Worker   {
567*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(search->nodes);
568*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(search->sorted);
569*5e7646d2SAndroid Build Coastguard Worker     free(search);
570*5e7646d2SAndroid Build Coastguard Worker     cgiFreeSearch(sc);
571*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
572*5e7646d2SAndroid Build Coastguard Worker   }
573*5e7646d2SAndroid Build Coastguard Worker 
574*5e7646d2SAndroid Build Coastguard Worker   search->search = 1;
575*5e7646d2SAndroid Build Coastguard Worker 
576*5e7646d2SAndroid Build Coastguard Worker  /*
577*5e7646d2SAndroid Build Coastguard Worker   * Check each node in the index, adding matching nodes to the
578*5e7646d2SAndroid Build Coastguard Worker   * search index...
579*5e7646d2SAndroid Build Coastguard Worker   */
580*5e7646d2SAndroid Build Coastguard Worker 
581*5e7646d2SAndroid Build Coastguard Worker   for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
582*5e7646d2SAndroid Build Coastguard Worker     if (node->section && section && strcmp(node->section, section))
583*5e7646d2SAndroid Build Coastguard Worker       continue;
584*5e7646d2SAndroid Build Coastguard Worker     else if (filename && strcmp(node->filename, filename))
585*5e7646d2SAndroid Build Coastguard Worker       continue;
586*5e7646d2SAndroid Build Coastguard Worker     else
587*5e7646d2SAndroid Build Coastguard Worker     {
588*5e7646d2SAndroid Build Coastguard Worker       matches = cgiDoSearch(sc, node->text);
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker       for (word = (help_word_t *)cupsArrayFirst(node->words);
591*5e7646d2SAndroid Build Coastguard Worker            word;
592*5e7646d2SAndroid Build Coastguard Worker 	   word = (help_word_t *)cupsArrayNext(node->words))
593*5e7646d2SAndroid Build Coastguard Worker         if (cgiDoSearch(sc, word->text) > 0)
594*5e7646d2SAndroid Build Coastguard Worker           matches += word->count;
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker       if (matches > 0)
597*5e7646d2SAndroid Build Coastguard Worker       {
598*5e7646d2SAndroid Build Coastguard Worker        /*
599*5e7646d2SAndroid Build Coastguard Worker 	* Found a match, add the node to the search index...
600*5e7646d2SAndroid Build Coastguard Worker 	*/
601*5e7646d2SAndroid Build Coastguard Worker 
602*5e7646d2SAndroid Build Coastguard Worker 	node->score = matches;
603*5e7646d2SAndroid Build Coastguard Worker 
604*5e7646d2SAndroid Build Coastguard Worker 	cupsArrayAdd(search->nodes, node);
605*5e7646d2SAndroid Build Coastguard Worker 	cupsArrayAdd(search->sorted, node);
606*5e7646d2SAndroid Build Coastguard Worker       }
607*5e7646d2SAndroid Build Coastguard Worker     }
608*5e7646d2SAndroid Build Coastguard Worker 
609*5e7646d2SAndroid Build Coastguard Worker  /*
610*5e7646d2SAndroid Build Coastguard Worker   * Free the search context...
611*5e7646d2SAndroid Build Coastguard Worker   */
612*5e7646d2SAndroid Build Coastguard Worker 
613*5e7646d2SAndroid Build Coastguard Worker   cgiFreeSearch(sc);
614*5e7646d2SAndroid Build Coastguard Worker 
615*5e7646d2SAndroid Build Coastguard Worker  /*
616*5e7646d2SAndroid Build Coastguard Worker   * Return the results...
617*5e7646d2SAndroid Build Coastguard Worker   */
618*5e7646d2SAndroid Build Coastguard Worker 
619*5e7646d2SAndroid Build Coastguard Worker   return (search);
620*5e7646d2SAndroid Build Coastguard Worker }
621*5e7646d2SAndroid Build Coastguard Worker 
622*5e7646d2SAndroid Build Coastguard Worker 
623*5e7646d2SAndroid Build Coastguard Worker /*
624*5e7646d2SAndroid Build Coastguard Worker  * 'help_add_word()' - Add a word to a node.
625*5e7646d2SAndroid Build Coastguard Worker  */
626*5e7646d2SAndroid Build Coastguard Worker 
627*5e7646d2SAndroid Build Coastguard Worker static help_word_t *			/* O - New word */
help_add_word(help_node_t * n,const char * text)628*5e7646d2SAndroid Build Coastguard Worker help_add_word(help_node_t *n,		/* I - Node */
629*5e7646d2SAndroid Build Coastguard Worker               const char  *text)	/* I - Word text */
630*5e7646d2SAndroid Build Coastguard Worker {
631*5e7646d2SAndroid Build Coastguard Worker   help_word_t	*w,			/* New word */
632*5e7646d2SAndroid Build Coastguard Worker 		key;			/* Search key */
633*5e7646d2SAndroid Build Coastguard Worker 
634*5e7646d2SAndroid Build Coastguard Worker 
635*5e7646d2SAndroid Build Coastguard Worker  /*
636*5e7646d2SAndroid Build Coastguard Worker   * Create the words array as needed...
637*5e7646d2SAndroid Build Coastguard Worker   */
638*5e7646d2SAndroid Build Coastguard Worker 
639*5e7646d2SAndroid Build Coastguard Worker   if (!n->words)
640*5e7646d2SAndroid Build Coastguard Worker     n->words = cupsArrayNew((cups_array_func_t)help_sort_words, NULL);
641*5e7646d2SAndroid Build Coastguard Worker 
642*5e7646d2SAndroid Build Coastguard Worker  /*
643*5e7646d2SAndroid Build Coastguard Worker   * See if the word is already added...
644*5e7646d2SAndroid Build Coastguard Worker   */
645*5e7646d2SAndroid Build Coastguard Worker 
646*5e7646d2SAndroid Build Coastguard Worker   key.text = (char *)text;
647*5e7646d2SAndroid Build Coastguard Worker 
648*5e7646d2SAndroid Build Coastguard Worker   if ((w = (help_word_t *)cupsArrayFind(n->words, &key)) == NULL)
649*5e7646d2SAndroid Build Coastguard Worker   {
650*5e7646d2SAndroid Build Coastguard Worker    /*
651*5e7646d2SAndroid Build Coastguard Worker     * Create a new word...
652*5e7646d2SAndroid Build Coastguard Worker     */
653*5e7646d2SAndroid Build Coastguard Worker 
654*5e7646d2SAndroid Build Coastguard Worker     if ((w = calloc(1, sizeof(help_word_t))) == NULL)
655*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
656*5e7646d2SAndroid Build Coastguard Worker 
657*5e7646d2SAndroid Build Coastguard Worker     if ((w->text = strdup(text)) == NULL)
658*5e7646d2SAndroid Build Coastguard Worker     {
659*5e7646d2SAndroid Build Coastguard Worker       free(w);
660*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
661*5e7646d2SAndroid Build Coastguard Worker     }
662*5e7646d2SAndroid Build Coastguard Worker 
663*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(n->words, w);
664*5e7646d2SAndroid Build Coastguard Worker   }
665*5e7646d2SAndroid Build Coastguard Worker 
666*5e7646d2SAndroid Build Coastguard Worker  /*
667*5e7646d2SAndroid Build Coastguard Worker   * Bump the counter for this word and return it...
668*5e7646d2SAndroid Build Coastguard Worker   */
669*5e7646d2SAndroid Build Coastguard Worker 
670*5e7646d2SAndroid Build Coastguard Worker   w->count ++;
671*5e7646d2SAndroid Build Coastguard Worker 
672*5e7646d2SAndroid Build Coastguard Worker   return (w);
673*5e7646d2SAndroid Build Coastguard Worker }
674*5e7646d2SAndroid Build Coastguard Worker 
675*5e7646d2SAndroid Build Coastguard Worker 
676*5e7646d2SAndroid Build Coastguard Worker /*
677*5e7646d2SAndroid Build Coastguard Worker  * 'help_delete_node()' - Free all memory used by a node.
678*5e7646d2SAndroid Build Coastguard Worker  */
679*5e7646d2SAndroid Build Coastguard Worker 
680*5e7646d2SAndroid Build Coastguard Worker static void
help_delete_node(help_node_t * n)681*5e7646d2SAndroid Build Coastguard Worker help_delete_node(help_node_t *n)	/* I - Node */
682*5e7646d2SAndroid Build Coastguard Worker {
683*5e7646d2SAndroid Build Coastguard Worker   help_word_t	*w;			/* Current word */
684*5e7646d2SAndroid Build Coastguard Worker 
685*5e7646d2SAndroid Build Coastguard Worker 
686*5e7646d2SAndroid Build Coastguard Worker   if (!n)
687*5e7646d2SAndroid Build Coastguard Worker     return;
688*5e7646d2SAndroid Build Coastguard Worker 
689*5e7646d2SAndroid Build Coastguard Worker   if (n->filename)
690*5e7646d2SAndroid Build Coastguard Worker     free(n->filename);
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker   if (n->anchor)
693*5e7646d2SAndroid Build Coastguard Worker     free(n->anchor);
694*5e7646d2SAndroid Build Coastguard Worker 
695*5e7646d2SAndroid Build Coastguard Worker   if (n->section)
696*5e7646d2SAndroid Build Coastguard Worker     free(n->section);
697*5e7646d2SAndroid Build Coastguard Worker 
698*5e7646d2SAndroid Build Coastguard Worker   if (n->text)
699*5e7646d2SAndroid Build Coastguard Worker     free(n->text);
700*5e7646d2SAndroid Build Coastguard Worker 
701*5e7646d2SAndroid Build Coastguard Worker   for (w = (help_word_t *)cupsArrayFirst(n->words);
702*5e7646d2SAndroid Build Coastguard Worker        w;
703*5e7646d2SAndroid Build Coastguard Worker        w = (help_word_t *)cupsArrayNext(n->words))
704*5e7646d2SAndroid Build Coastguard Worker     help_delete_word(w);
705*5e7646d2SAndroid Build Coastguard Worker 
706*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(n->words);
707*5e7646d2SAndroid Build Coastguard Worker 
708*5e7646d2SAndroid Build Coastguard Worker   free(n);
709*5e7646d2SAndroid Build Coastguard Worker }
710*5e7646d2SAndroid Build Coastguard Worker 
711*5e7646d2SAndroid Build Coastguard Worker 
712*5e7646d2SAndroid Build Coastguard Worker /*
713*5e7646d2SAndroid Build Coastguard Worker  * 'help_delete_word()' - Free all memory used by a word.
714*5e7646d2SAndroid Build Coastguard Worker  */
715*5e7646d2SAndroid Build Coastguard Worker 
716*5e7646d2SAndroid Build Coastguard Worker static void
help_delete_word(help_word_t * w)717*5e7646d2SAndroid Build Coastguard Worker help_delete_word(help_word_t *w)	/* I - Word */
718*5e7646d2SAndroid Build Coastguard Worker {
719*5e7646d2SAndroid Build Coastguard Worker   if (!w)
720*5e7646d2SAndroid Build Coastguard Worker     return;
721*5e7646d2SAndroid Build Coastguard Worker 
722*5e7646d2SAndroid Build Coastguard Worker   if (w->text)
723*5e7646d2SAndroid Build Coastguard Worker     free(w->text);
724*5e7646d2SAndroid Build Coastguard Worker 
725*5e7646d2SAndroid Build Coastguard Worker   free(w);
726*5e7646d2SAndroid Build Coastguard Worker }
727*5e7646d2SAndroid Build Coastguard Worker 
728*5e7646d2SAndroid Build Coastguard Worker 
729*5e7646d2SAndroid Build Coastguard Worker /*
730*5e7646d2SAndroid Build Coastguard Worker  * 'help_load_directory()' - Load a directory of files into an index.
731*5e7646d2SAndroid Build Coastguard Worker  */
732*5e7646d2SAndroid Build Coastguard Worker 
733*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 0 = success, -1 = error, 1 = updated */
help_load_directory(help_index_t * hi,const char * directory,const char * relative)734*5e7646d2SAndroid Build Coastguard Worker help_load_directory(
735*5e7646d2SAndroid Build Coastguard Worker     help_index_t *hi,			/* I - Index */
736*5e7646d2SAndroid Build Coastguard Worker     const char   *directory,		/* I - Directory */
737*5e7646d2SAndroid Build Coastguard Worker     const char   *relative)		/* I - Relative path */
738*5e7646d2SAndroid Build Coastguard Worker {
739*5e7646d2SAndroid Build Coastguard Worker   cups_dir_t	*dir;			/* Directory file */
740*5e7646d2SAndroid Build Coastguard Worker   cups_dentry_t	*dent;			/* Directory entry */
741*5e7646d2SAndroid Build Coastguard Worker   char		*ext,			/* Pointer to extension */
742*5e7646d2SAndroid Build Coastguard Worker 		filename[1024],		/* Full filename */
743*5e7646d2SAndroid Build Coastguard Worker 		relname[1024];		/* Relative filename */
744*5e7646d2SAndroid Build Coastguard Worker   int		update;			/* Updated? */
745*5e7646d2SAndroid Build Coastguard Worker   help_node_t	*node;			/* Current node */
746*5e7646d2SAndroid Build Coastguard Worker 
747*5e7646d2SAndroid Build Coastguard Worker 
748*5e7646d2SAndroid Build Coastguard Worker  /*
749*5e7646d2SAndroid Build Coastguard Worker   * Open the directory and scan it...
750*5e7646d2SAndroid Build Coastguard Worker   */
751*5e7646d2SAndroid Build Coastguard Worker 
752*5e7646d2SAndroid Build Coastguard Worker   if ((dir = cupsDirOpen(directory)) == NULL)
753*5e7646d2SAndroid Build Coastguard Worker     return (0);
754*5e7646d2SAndroid Build Coastguard Worker 
755*5e7646d2SAndroid Build Coastguard Worker   update = 0;
756*5e7646d2SAndroid Build Coastguard Worker 
757*5e7646d2SAndroid Build Coastguard Worker   while ((dent = cupsDirRead(dir)) != NULL)
758*5e7646d2SAndroid Build Coastguard Worker   {
759*5e7646d2SAndroid Build Coastguard Worker    /*
760*5e7646d2SAndroid Build Coastguard Worker     * Skip "." files...
761*5e7646d2SAndroid Build Coastguard Worker     */
762*5e7646d2SAndroid Build Coastguard Worker 
763*5e7646d2SAndroid Build Coastguard Worker     if (dent->filename[0] == '.')
764*5e7646d2SAndroid Build Coastguard Worker       continue;
765*5e7646d2SAndroid Build Coastguard Worker 
766*5e7646d2SAndroid Build Coastguard Worker    /*
767*5e7646d2SAndroid Build Coastguard Worker     * Get absolute and relative filenames...
768*5e7646d2SAndroid Build Coastguard Worker     */
769*5e7646d2SAndroid Build Coastguard Worker 
770*5e7646d2SAndroid Build Coastguard Worker     snprintf(filename, sizeof(filename), "%s/%s", directory, dent->filename);
771*5e7646d2SAndroid Build Coastguard Worker     if (relative)
772*5e7646d2SAndroid Build Coastguard Worker       snprintf(relname, sizeof(relname), "%s/%s", relative, dent->filename);
773*5e7646d2SAndroid Build Coastguard Worker     else
774*5e7646d2SAndroid Build Coastguard Worker       strlcpy(relname, dent->filename, sizeof(relname));
775*5e7646d2SAndroid Build Coastguard Worker 
776*5e7646d2SAndroid Build Coastguard Worker    /*
777*5e7646d2SAndroid Build Coastguard Worker     * Check if we have a HTML file...
778*5e7646d2SAndroid Build Coastguard Worker     */
779*5e7646d2SAndroid Build Coastguard Worker 
780*5e7646d2SAndroid Build Coastguard Worker     if ((ext = strstr(dent->filename, ".html")) != NULL &&
781*5e7646d2SAndroid Build Coastguard Worker         (!ext[5] || !strcmp(ext + 5, ".gz")))
782*5e7646d2SAndroid Build Coastguard Worker     {
783*5e7646d2SAndroid Build Coastguard Worker      /*
784*5e7646d2SAndroid Build Coastguard Worker       * HTML file, see if we have already indexed the file...
785*5e7646d2SAndroid Build Coastguard Worker       */
786*5e7646d2SAndroid Build Coastguard Worker 
787*5e7646d2SAndroid Build Coastguard Worker       if ((node = helpFindNode(hi, relname, NULL)) != NULL)
788*5e7646d2SAndroid Build Coastguard Worker       {
789*5e7646d2SAndroid Build Coastguard Worker        /*
790*5e7646d2SAndroid Build Coastguard Worker         * File already indexed - check dates to confirm that the
791*5e7646d2SAndroid Build Coastguard Worker 	* index is up-to-date...
792*5e7646d2SAndroid Build Coastguard Worker 	*/
793*5e7646d2SAndroid Build Coastguard Worker 
794*5e7646d2SAndroid Build Coastguard Worker         if (node->mtime == dent->fileinfo.st_mtime)
795*5e7646d2SAndroid Build Coastguard Worker 	{
796*5e7646d2SAndroid Build Coastguard Worker 	 /*
797*5e7646d2SAndroid Build Coastguard Worker 	  * Same modification time, so mark all of the nodes
798*5e7646d2SAndroid Build Coastguard Worker 	  * for this file as up-to-date...
799*5e7646d2SAndroid Build Coastguard Worker 	  */
800*5e7646d2SAndroid Build Coastguard Worker 
801*5e7646d2SAndroid Build Coastguard Worker           for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
802*5e7646d2SAndroid Build Coastguard Worker 	    if (!strcmp(node->filename, relname))
803*5e7646d2SAndroid Build Coastguard Worker 	      node->score = 0;
804*5e7646d2SAndroid Build Coastguard Worker 	    else
805*5e7646d2SAndroid Build Coastguard Worker 	      break;
806*5e7646d2SAndroid Build Coastguard Worker 
807*5e7646d2SAndroid Build Coastguard Worker           continue;
808*5e7646d2SAndroid Build Coastguard Worker 	}
809*5e7646d2SAndroid Build Coastguard Worker       }
810*5e7646d2SAndroid Build Coastguard Worker 
811*5e7646d2SAndroid Build Coastguard Worker       update = 1;
812*5e7646d2SAndroid Build Coastguard Worker 
813*5e7646d2SAndroid Build Coastguard Worker       help_load_file(hi, filename, relname, dent->fileinfo.st_mtime);
814*5e7646d2SAndroid Build Coastguard Worker     }
815*5e7646d2SAndroid Build Coastguard Worker     else if (S_ISDIR(dent->fileinfo.st_mode))
816*5e7646d2SAndroid Build Coastguard Worker     {
817*5e7646d2SAndroid Build Coastguard Worker      /*
818*5e7646d2SAndroid Build Coastguard Worker       * Process sub-directory...
819*5e7646d2SAndroid Build Coastguard Worker       */
820*5e7646d2SAndroid Build Coastguard Worker 
821*5e7646d2SAndroid Build Coastguard Worker       if (help_load_directory(hi, filename, relname) == 1)
822*5e7646d2SAndroid Build Coastguard Worker         update = 1;
823*5e7646d2SAndroid Build Coastguard Worker     }
824*5e7646d2SAndroid Build Coastguard Worker   }
825*5e7646d2SAndroid Build Coastguard Worker 
826*5e7646d2SAndroid Build Coastguard Worker   cupsDirClose(dir);
827*5e7646d2SAndroid Build Coastguard Worker 
828*5e7646d2SAndroid Build Coastguard Worker   return (update);
829*5e7646d2SAndroid Build Coastguard Worker }
830*5e7646d2SAndroid Build Coastguard Worker 
831*5e7646d2SAndroid Build Coastguard Worker 
832*5e7646d2SAndroid Build Coastguard Worker /*
833*5e7646d2SAndroid Build Coastguard Worker  * 'help_load_file()' - Load a HTML files into an index.
834*5e7646d2SAndroid Build Coastguard Worker  */
835*5e7646d2SAndroid Build Coastguard Worker 
836*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 0 = success, -1 = error */
help_load_file(help_index_t * hi,const char * filename,const char * relative,time_t mtime)837*5e7646d2SAndroid Build Coastguard Worker help_load_file(
838*5e7646d2SAndroid Build Coastguard Worker     help_index_t *hi,			/* I - Index */
839*5e7646d2SAndroid Build Coastguard Worker     const char   *filename,		/* I - Filename */
840*5e7646d2SAndroid Build Coastguard Worker     const char   *relative,		/* I - Relative path */
841*5e7646d2SAndroid Build Coastguard Worker     time_t       mtime)			/* I - Modification time */
842*5e7646d2SAndroid Build Coastguard Worker {
843*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* HTML file */
844*5e7646d2SAndroid Build Coastguard Worker   help_node_t	*node;			/* Current node */
845*5e7646d2SAndroid Build Coastguard Worker   char		line[1024],		/* Line from file */
846*5e7646d2SAndroid Build Coastguard Worker 		temp[1024],		/* Temporary word */
847*5e7646d2SAndroid Build Coastguard Worker                 section[1024],		/* Section */
848*5e7646d2SAndroid Build Coastguard Worker 		*ptr,			/* Pointer into line */
849*5e7646d2SAndroid Build Coastguard Worker 		*anchor,		/* Anchor name */
850*5e7646d2SAndroid Build Coastguard Worker 		*text;			/* Text for anchor */
851*5e7646d2SAndroid Build Coastguard Worker   off_t		offset;			/* File offset */
852*5e7646d2SAndroid Build Coastguard Worker   char		quote;			/* Quote character */
853*5e7646d2SAndroid Build Coastguard Worker   help_word_t	*word;			/* Current word */
854*5e7646d2SAndroid Build Coastguard Worker   int		wordlen;		/* Length of word */
855*5e7646d2SAndroid Build Coastguard Worker 
856*5e7646d2SAndroid Build Coastguard Worker 
857*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(filename, "r")) == NULL)
858*5e7646d2SAndroid Build Coastguard Worker     return (-1);
859*5e7646d2SAndroid Build Coastguard Worker 
860*5e7646d2SAndroid Build Coastguard Worker   node   = NULL;
861*5e7646d2SAndroid Build Coastguard Worker   offset = 0;
862*5e7646d2SAndroid Build Coastguard Worker 
863*5e7646d2SAndroid Build Coastguard Worker   strlcpy(section, "Other", sizeof(section));
864*5e7646d2SAndroid Build Coastguard Worker 
865*5e7646d2SAndroid Build Coastguard Worker   while (cupsFileGets(fp, line, sizeof(line)))
866*5e7646d2SAndroid Build Coastguard Worker   {
867*5e7646d2SAndroid Build Coastguard Worker    /*
868*5e7646d2SAndroid Build Coastguard Worker     * Look for "<TITLE>", "<A NAME", or "<!-- SECTION:" prefix...
869*5e7646d2SAndroid Build Coastguard Worker     */
870*5e7646d2SAndroid Build Coastguard Worker 
871*5e7646d2SAndroid Build Coastguard Worker     if ((ptr = strstr(line, "<!-- SECTION:")) != NULL)
872*5e7646d2SAndroid Build Coastguard Worker     {
873*5e7646d2SAndroid Build Coastguard Worker      /*
874*5e7646d2SAndroid Build Coastguard Worker       * Got section line, copy it!
875*5e7646d2SAndroid Build Coastguard Worker       */
876*5e7646d2SAndroid Build Coastguard Worker 
877*5e7646d2SAndroid Build Coastguard Worker       for (ptr += 13; isspace(*ptr & 255); ptr ++);
878*5e7646d2SAndroid Build Coastguard Worker 
879*5e7646d2SAndroid Build Coastguard Worker       strlcpy(section, ptr, sizeof(section));
880*5e7646d2SAndroid Build Coastguard Worker       if ((ptr = strstr(section, "-->")) != NULL)
881*5e7646d2SAndroid Build Coastguard Worker       {
882*5e7646d2SAndroid Build Coastguard Worker        /*
883*5e7646d2SAndroid Build Coastguard Worker         * Strip comment stuff from end of line...
884*5e7646d2SAndroid Build Coastguard Worker 	*/
885*5e7646d2SAndroid Build Coastguard Worker 
886*5e7646d2SAndroid Build Coastguard Worker         for (*ptr-- = '\0'; ptr > line && isspace(*ptr & 255); *ptr-- = '\0');
887*5e7646d2SAndroid Build Coastguard Worker 
888*5e7646d2SAndroid Build Coastguard Worker 	if (isspace(*ptr & 255))
889*5e7646d2SAndroid Build Coastguard Worker 	  *ptr = '\0';
890*5e7646d2SAndroid Build Coastguard Worker       }
891*5e7646d2SAndroid Build Coastguard Worker       continue;
892*5e7646d2SAndroid Build Coastguard Worker     }
893*5e7646d2SAndroid Build Coastguard Worker 
894*5e7646d2SAndroid Build Coastguard Worker     for (ptr = line; (ptr = strchr(ptr, '<')) != NULL;)
895*5e7646d2SAndroid Build Coastguard Worker     {
896*5e7646d2SAndroid Build Coastguard Worker       ptr ++;
897*5e7646d2SAndroid Build Coastguard Worker 
898*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strncasecmp(ptr, "TITLE>", 6))
899*5e7646d2SAndroid Build Coastguard Worker       {
900*5e7646d2SAndroid Build Coastguard Worker        /*
901*5e7646d2SAndroid Build Coastguard Worker         * Found the title...
902*5e7646d2SAndroid Build Coastguard Worker 	*/
903*5e7646d2SAndroid Build Coastguard Worker 
904*5e7646d2SAndroid Build Coastguard Worker 	anchor = NULL;
905*5e7646d2SAndroid Build Coastguard Worker 	ptr += 6;
906*5e7646d2SAndroid Build Coastguard Worker       }
907*5e7646d2SAndroid Build Coastguard Worker       else
908*5e7646d2SAndroid Build Coastguard Worker       {
909*5e7646d2SAndroid Build Coastguard Worker         char *idptr;			/* Pointer to ID */
910*5e7646d2SAndroid Build Coastguard Worker 
911*5e7646d2SAndroid Build Coastguard Worker 	if (!_cups_strncasecmp(ptr, "A NAME=", 7))
912*5e7646d2SAndroid Build Coastguard Worker 	  ptr += 7;
913*5e7646d2SAndroid Build Coastguard Worker 	else if ((idptr = strstr(ptr, " ID=")) != NULL)
914*5e7646d2SAndroid Build Coastguard Worker 	  ptr = idptr + 4;
915*5e7646d2SAndroid Build Coastguard Worker 	else if ((idptr = strstr(ptr, " id=")) != NULL)
916*5e7646d2SAndroid Build Coastguard Worker 	  ptr = idptr + 4;
917*5e7646d2SAndroid Build Coastguard Worker 	else
918*5e7646d2SAndroid Build Coastguard Worker 	  continue;
919*5e7646d2SAndroid Build Coastguard Worker 
920*5e7646d2SAndroid Build Coastguard Worker        /*
921*5e7646d2SAndroid Build Coastguard Worker         * Found an anchor...
922*5e7646d2SAndroid Build Coastguard Worker 	*/
923*5e7646d2SAndroid Build Coastguard Worker 
924*5e7646d2SAndroid Build Coastguard Worker 	if (*ptr == '\"' || *ptr == '\'')
925*5e7646d2SAndroid Build Coastguard Worker 	{
926*5e7646d2SAndroid Build Coastguard Worker 	 /*
927*5e7646d2SAndroid Build Coastguard Worker 	  * Get quoted anchor...
928*5e7646d2SAndroid Build Coastguard Worker 	  */
929*5e7646d2SAndroid Build Coastguard Worker 
930*5e7646d2SAndroid Build Coastguard Worker 	  quote  = *ptr;
931*5e7646d2SAndroid Build Coastguard Worker           anchor = ptr + 1;
932*5e7646d2SAndroid Build Coastguard Worker 	  if ((ptr = strchr(anchor, quote)) != NULL)
933*5e7646d2SAndroid Build Coastguard Worker 	    *ptr++ = '\0';
934*5e7646d2SAndroid Build Coastguard Worker 	  else
935*5e7646d2SAndroid Build Coastguard Worker 	    break;
936*5e7646d2SAndroid Build Coastguard Worker 	}
937*5e7646d2SAndroid Build Coastguard Worker 	else
938*5e7646d2SAndroid Build Coastguard Worker 	{
939*5e7646d2SAndroid Build Coastguard Worker 	 /*
940*5e7646d2SAndroid Build Coastguard Worker 	  * Get unquoted anchor...
941*5e7646d2SAndroid Build Coastguard Worker 	  */
942*5e7646d2SAndroid Build Coastguard Worker 
943*5e7646d2SAndroid Build Coastguard Worker           anchor = ptr + 1;
944*5e7646d2SAndroid Build Coastguard Worker 
945*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr = anchor; *ptr && *ptr != '>' && !isspace(*ptr & 255); ptr ++);
946*5e7646d2SAndroid Build Coastguard Worker 
947*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr != '>')
948*5e7646d2SAndroid Build Coastguard Worker 	    *ptr++ = '\0';
949*5e7646d2SAndroid Build Coastguard Worker 	  else
950*5e7646d2SAndroid Build Coastguard Worker 	    break;
951*5e7646d2SAndroid Build Coastguard Worker 	}
952*5e7646d2SAndroid Build Coastguard Worker 
953*5e7646d2SAndroid Build Coastguard Worker        /*
954*5e7646d2SAndroid Build Coastguard Worker         * Got the anchor, now lets find the end...
955*5e7646d2SAndroid Build Coastguard Worker 	*/
956*5e7646d2SAndroid Build Coastguard Worker 
957*5e7646d2SAndroid Build Coastguard Worker         while (*ptr && *ptr != '>')
958*5e7646d2SAndroid Build Coastguard Worker 	  ptr ++;
959*5e7646d2SAndroid Build Coastguard Worker 
960*5e7646d2SAndroid Build Coastguard Worker         if (*ptr != '>')
961*5e7646d2SAndroid Build Coastguard Worker 	  break;
962*5e7646d2SAndroid Build Coastguard Worker 
963*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = '\0';
964*5e7646d2SAndroid Build Coastguard Worker       }
965*5e7646d2SAndroid Build Coastguard Worker 
966*5e7646d2SAndroid Build Coastguard Worker      /*
967*5e7646d2SAndroid Build Coastguard Worker       * Now collect text for the link...
968*5e7646d2SAndroid Build Coastguard Worker       */
969*5e7646d2SAndroid Build Coastguard Worker 
970*5e7646d2SAndroid Build Coastguard Worker       text = ptr;
971*5e7646d2SAndroid Build Coastguard Worker       while ((ptr = strchr(text, '<')) == NULL)
972*5e7646d2SAndroid Build Coastguard Worker       {
973*5e7646d2SAndroid Build Coastguard Worker 	ptr = text + strlen(text);
974*5e7646d2SAndroid Build Coastguard Worker 	if (ptr >= (line + sizeof(line) - 2))
975*5e7646d2SAndroid Build Coastguard Worker 	  break;
976*5e7646d2SAndroid Build Coastguard Worker 
977*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = ' ';
978*5e7646d2SAndroid Build Coastguard Worker 
979*5e7646d2SAndroid Build Coastguard Worker         if (!cupsFileGets(fp, ptr, sizeof(line) - (size_t)(ptr - line) - 1))
980*5e7646d2SAndroid Build Coastguard Worker 	  break;
981*5e7646d2SAndroid Build Coastguard Worker       }
982*5e7646d2SAndroid Build Coastguard Worker 
983*5e7646d2SAndroid Build Coastguard Worker       *ptr = '\0';
984*5e7646d2SAndroid Build Coastguard Worker 
985*5e7646d2SAndroid Build Coastguard Worker       if (node)
986*5e7646d2SAndroid Build Coastguard Worker 	node->length = (size_t)(offset - node->offset);
987*5e7646d2SAndroid Build Coastguard Worker 
988*5e7646d2SAndroid Build Coastguard Worker       if (!*text)
989*5e7646d2SAndroid Build Coastguard Worker       {
990*5e7646d2SAndroid Build Coastguard Worker         node = NULL;
991*5e7646d2SAndroid Build Coastguard Worker         break;
992*5e7646d2SAndroid Build Coastguard Worker       }
993*5e7646d2SAndroid Build Coastguard Worker 
994*5e7646d2SAndroid Build Coastguard Worker       if ((node = helpFindNode(hi, relative, anchor)) != NULL)
995*5e7646d2SAndroid Build Coastguard Worker       {
996*5e7646d2SAndroid Build Coastguard Worker        /*
997*5e7646d2SAndroid Build Coastguard Worker 	* Node already in the index, so replace the text and other
998*5e7646d2SAndroid Build Coastguard Worker 	* data...
999*5e7646d2SAndroid Build Coastguard Worker 	*/
1000*5e7646d2SAndroid Build Coastguard Worker 
1001*5e7646d2SAndroid Build Coastguard Worker         cupsArrayRemove(hi->nodes, node);
1002*5e7646d2SAndroid Build Coastguard Worker 
1003*5e7646d2SAndroid Build Coastguard Worker         if (node->section)
1004*5e7646d2SAndroid Build Coastguard Worker 	  free(node->section);
1005*5e7646d2SAndroid Build Coastguard Worker 
1006*5e7646d2SAndroid Build Coastguard Worker 	if (node->text)
1007*5e7646d2SAndroid Build Coastguard Worker 	  free(node->text);
1008*5e7646d2SAndroid Build Coastguard Worker 
1009*5e7646d2SAndroid Build Coastguard Worker         if (node->words)
1010*5e7646d2SAndroid Build Coastguard Worker 	{
1011*5e7646d2SAndroid Build Coastguard Worker 	  for (word = (help_word_t *)cupsArrayFirst(node->words);
1012*5e7646d2SAndroid Build Coastguard Worker 	       word;
1013*5e7646d2SAndroid Build Coastguard Worker 	       word = (help_word_t *)cupsArrayNext(node->words))
1014*5e7646d2SAndroid Build Coastguard Worker 	    help_delete_word(word);
1015*5e7646d2SAndroid Build Coastguard Worker 
1016*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayDelete(node->words);
1017*5e7646d2SAndroid Build Coastguard Worker 	  node->words = NULL;
1018*5e7646d2SAndroid Build Coastguard Worker 	}
1019*5e7646d2SAndroid Build Coastguard Worker 
1020*5e7646d2SAndroid Build Coastguard Worker 	node->section = section[0] ? strdup(section) : NULL;
1021*5e7646d2SAndroid Build Coastguard Worker 	node->text    = strdup(text);
1022*5e7646d2SAndroid Build Coastguard Worker 	node->mtime   = mtime;
1023*5e7646d2SAndroid Build Coastguard Worker 	node->offset  = offset;
1024*5e7646d2SAndroid Build Coastguard Worker 	node->score   = 0;
1025*5e7646d2SAndroid Build Coastguard Worker       }
1026*5e7646d2SAndroid Build Coastguard Worker       else
1027*5e7646d2SAndroid Build Coastguard Worker       {
1028*5e7646d2SAndroid Build Coastguard Worker        /*
1029*5e7646d2SAndroid Build Coastguard Worker 	* New node...
1030*5e7646d2SAndroid Build Coastguard Worker 	*/
1031*5e7646d2SAndroid Build Coastguard Worker 
1032*5e7646d2SAndroid Build Coastguard Worker         node = help_new_node(relative, anchor, section, text, mtime, offset, 0);
1033*5e7646d2SAndroid Build Coastguard Worker       }
1034*5e7646d2SAndroid Build Coastguard Worker 
1035*5e7646d2SAndroid Build Coastguard Worker      /*
1036*5e7646d2SAndroid Build Coastguard Worker       * Go through the text value and replace tabs and newlines with
1037*5e7646d2SAndroid Build Coastguard Worker       * whitespace and eliminate extra whitespace...
1038*5e7646d2SAndroid Build Coastguard Worker       */
1039*5e7646d2SAndroid Build Coastguard Worker 
1040*5e7646d2SAndroid Build Coastguard Worker       for (ptr = node->text, text = node->text; *ptr;)
1041*5e7646d2SAndroid Build Coastguard Worker 	if (isspace(*ptr & 255))
1042*5e7646d2SAndroid Build Coastguard Worker 	{
1043*5e7646d2SAndroid Build Coastguard Worker 	  while (isspace(*ptr & 255))
1044*5e7646d2SAndroid Build Coastguard Worker 	    ptr ++;
1045*5e7646d2SAndroid Build Coastguard Worker 
1046*5e7646d2SAndroid Build Coastguard Worker 	  *text++ = ' ';
1047*5e7646d2SAndroid Build Coastguard Worker         }
1048*5e7646d2SAndroid Build Coastguard Worker 	else if (text != ptr)
1049*5e7646d2SAndroid Build Coastguard Worker 	  *text++ = *ptr++;
1050*5e7646d2SAndroid Build Coastguard Worker 	else
1051*5e7646d2SAndroid Build Coastguard Worker 	{
1052*5e7646d2SAndroid Build Coastguard Worker 	  text ++;
1053*5e7646d2SAndroid Build Coastguard Worker 	  ptr ++;
1054*5e7646d2SAndroid Build Coastguard Worker 	}
1055*5e7646d2SAndroid Build Coastguard Worker 
1056*5e7646d2SAndroid Build Coastguard Worker       *text = '\0';
1057*5e7646d2SAndroid Build Coastguard Worker 
1058*5e7646d2SAndroid Build Coastguard Worker      /*
1059*5e7646d2SAndroid Build Coastguard Worker       * (Re)add the node to the array...
1060*5e7646d2SAndroid Build Coastguard Worker       */
1061*5e7646d2SAndroid Build Coastguard Worker 
1062*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(hi->nodes, node);
1063*5e7646d2SAndroid Build Coastguard Worker 
1064*5e7646d2SAndroid Build Coastguard Worker       if (!anchor)
1065*5e7646d2SAndroid Build Coastguard Worker         node = NULL;
1066*5e7646d2SAndroid Build Coastguard Worker       break;
1067*5e7646d2SAndroid Build Coastguard Worker     }
1068*5e7646d2SAndroid Build Coastguard Worker 
1069*5e7646d2SAndroid Build Coastguard Worker     if (node)
1070*5e7646d2SAndroid Build Coastguard Worker     {
1071*5e7646d2SAndroid Build Coastguard Worker      /*
1072*5e7646d2SAndroid Build Coastguard Worker       * Scan this line for words...
1073*5e7646d2SAndroid Build Coastguard Worker       */
1074*5e7646d2SAndroid Build Coastguard Worker 
1075*5e7646d2SAndroid Build Coastguard Worker       for (ptr = line; *ptr; ptr ++)
1076*5e7646d2SAndroid Build Coastguard Worker       {
1077*5e7646d2SAndroid Build Coastguard Worker        /*
1078*5e7646d2SAndroid Build Coastguard Worker 	* Skip HTML stuff...
1079*5e7646d2SAndroid Build Coastguard Worker 	*/
1080*5e7646d2SAndroid Build Coastguard Worker 
1081*5e7646d2SAndroid Build Coastguard Worker 	if (*ptr == '<')
1082*5e7646d2SAndroid Build Coastguard Worker 	{
1083*5e7646d2SAndroid Build Coastguard Worker           if (!strncmp(ptr, "<!--", 4))
1084*5e7646d2SAndroid Build Coastguard Worker 	  {
1085*5e7646d2SAndroid Build Coastguard Worker 	   /*
1086*5e7646d2SAndroid Build Coastguard Worker 	    * Skip HTML comment...
1087*5e7646d2SAndroid Build Coastguard Worker 	    */
1088*5e7646d2SAndroid Build Coastguard Worker 
1089*5e7646d2SAndroid Build Coastguard Worker             if ((text = strstr(ptr + 4, "-->")) == NULL)
1090*5e7646d2SAndroid Build Coastguard Worker 	      ptr += strlen(ptr) - 1;
1091*5e7646d2SAndroid Build Coastguard Worker 	    else
1092*5e7646d2SAndroid Build Coastguard Worker 	      ptr = text + 2;
1093*5e7646d2SAndroid Build Coastguard Worker 	  }
1094*5e7646d2SAndroid Build Coastguard Worker 	  else
1095*5e7646d2SAndroid Build Coastguard Worker 	  {
1096*5e7646d2SAndroid Build Coastguard Worker 	   /*
1097*5e7646d2SAndroid Build Coastguard Worker             * Skip HTML element...
1098*5e7646d2SAndroid Build Coastguard Worker 	    */
1099*5e7646d2SAndroid Build Coastguard Worker 
1100*5e7646d2SAndroid Build Coastguard Worker             for (ptr ++; *ptr && *ptr != '>'; ptr ++)
1101*5e7646d2SAndroid Build Coastguard Worker 	    {
1102*5e7646d2SAndroid Build Coastguard Worker 	      if (*ptr == '\"' || *ptr == '\'')
1103*5e7646d2SAndroid Build Coastguard Worker 	      {
1104*5e7646d2SAndroid Build Coastguard Worker 		for (quote = *ptr++; *ptr && *ptr != quote; ptr ++);
1105*5e7646d2SAndroid Build Coastguard Worker 
1106*5e7646d2SAndroid Build Coastguard Worker 		if (!*ptr)
1107*5e7646d2SAndroid Build Coastguard Worker 		  ptr --;
1108*5e7646d2SAndroid Build Coastguard Worker 	      }
1109*5e7646d2SAndroid Build Coastguard Worker 	    }
1110*5e7646d2SAndroid Build Coastguard Worker 
1111*5e7646d2SAndroid Build Coastguard Worker 	    if (!*ptr)
1112*5e7646d2SAndroid Build Coastguard Worker 	      ptr --;
1113*5e7646d2SAndroid Build Coastguard Worker           }
1114*5e7646d2SAndroid Build Coastguard Worker 
1115*5e7646d2SAndroid Build Coastguard Worker           continue;
1116*5e7646d2SAndroid Build Coastguard Worker 	}
1117*5e7646d2SAndroid Build Coastguard Worker 	else if (*ptr == '&')
1118*5e7646d2SAndroid Build Coastguard Worker 	{
1119*5e7646d2SAndroid Build Coastguard Worker 	 /*
1120*5e7646d2SAndroid Build Coastguard Worker 	  * Skip HTML entity...
1121*5e7646d2SAndroid Build Coastguard Worker 	  */
1122*5e7646d2SAndroid Build Coastguard Worker 
1123*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr ++; *ptr && *ptr != ';'; ptr ++);
1124*5e7646d2SAndroid Build Coastguard Worker 
1125*5e7646d2SAndroid Build Coastguard Worker 	  if (!*ptr)
1126*5e7646d2SAndroid Build Coastguard Worker 	    ptr --;
1127*5e7646d2SAndroid Build Coastguard Worker 
1128*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1129*5e7646d2SAndroid Build Coastguard Worker 	}
1130*5e7646d2SAndroid Build Coastguard Worker 	else if (!isalnum(*ptr & 255))
1131*5e7646d2SAndroid Build Coastguard Worker           continue;
1132*5e7646d2SAndroid Build Coastguard Worker 
1133*5e7646d2SAndroid Build Coastguard Worker        /*
1134*5e7646d2SAndroid Build Coastguard Worker 	* Found the start of a word, search until we find the end...
1135*5e7646d2SAndroid Build Coastguard Worker 	*/
1136*5e7646d2SAndroid Build Coastguard Worker 
1137*5e7646d2SAndroid Build Coastguard Worker 	for (text = ptr, ptr ++; *ptr && isalnum(*ptr & 255); ptr ++);
1138*5e7646d2SAndroid Build Coastguard Worker 
1139*5e7646d2SAndroid Build Coastguard Worker 	wordlen = (int)(ptr - text);
1140*5e7646d2SAndroid Build Coastguard Worker 
1141*5e7646d2SAndroid Build Coastguard Worker         memcpy(temp, text, (size_t)wordlen);
1142*5e7646d2SAndroid Build Coastguard Worker 	temp[wordlen] = '\0';
1143*5e7646d2SAndroid Build Coastguard Worker 
1144*5e7646d2SAndroid Build Coastguard Worker         ptr --;
1145*5e7646d2SAndroid Build Coastguard Worker 
1146*5e7646d2SAndroid Build Coastguard Worker 	if (wordlen > 1 && !bsearch(temp, help_common_words,
1147*5e7646d2SAndroid Build Coastguard Worker 	                            (sizeof(help_common_words) /
1148*5e7646d2SAndroid Build Coastguard Worker 				     sizeof(help_common_words[0])),
1149*5e7646d2SAndroid Build Coastguard Worker 				    sizeof(help_common_words[0]),
1150*5e7646d2SAndroid Build Coastguard Worker 				    (int (*)(const void *, const void *))
1151*5e7646d2SAndroid Build Coastguard Worker 				        _cups_strcasecmp))
1152*5e7646d2SAndroid Build Coastguard Worker           help_add_word(node, temp);
1153*5e7646d2SAndroid Build Coastguard Worker       }
1154*5e7646d2SAndroid Build Coastguard Worker     }
1155*5e7646d2SAndroid Build Coastguard Worker 
1156*5e7646d2SAndroid Build Coastguard Worker    /*
1157*5e7646d2SAndroid Build Coastguard Worker     * Get the offset of the next line...
1158*5e7646d2SAndroid Build Coastguard Worker     */
1159*5e7646d2SAndroid Build Coastguard Worker 
1160*5e7646d2SAndroid Build Coastguard Worker     offset = cupsFileTell(fp);
1161*5e7646d2SAndroid Build Coastguard Worker   }
1162*5e7646d2SAndroid Build Coastguard Worker 
1163*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(fp);
1164*5e7646d2SAndroid Build Coastguard Worker 
1165*5e7646d2SAndroid Build Coastguard Worker   if (node)
1166*5e7646d2SAndroid Build Coastguard Worker     node->length = (size_t)(offset - node->offset);
1167*5e7646d2SAndroid Build Coastguard Worker 
1168*5e7646d2SAndroid Build Coastguard Worker   return (0);
1169*5e7646d2SAndroid Build Coastguard Worker }
1170*5e7646d2SAndroid Build Coastguard Worker 
1171*5e7646d2SAndroid Build Coastguard Worker 
1172*5e7646d2SAndroid Build Coastguard Worker /*
1173*5e7646d2SAndroid Build Coastguard Worker  * 'help_new_node()' - Create a new node and add it to an index.
1174*5e7646d2SAndroid Build Coastguard Worker  */
1175*5e7646d2SAndroid Build Coastguard Worker 
1176*5e7646d2SAndroid Build Coastguard Worker static help_node_t *			/* O - Node pointer or NULL on error */
help_new_node(const char * filename,const char * anchor,const char * section,const char * text,time_t mtime,off_t offset,size_t length)1177*5e7646d2SAndroid Build Coastguard Worker help_new_node(const char   *filename,	/* I - Filename */
1178*5e7646d2SAndroid Build Coastguard Worker               const char   *anchor,	/* I - Anchor */
1179*5e7646d2SAndroid Build Coastguard Worker 	      const char   *section,	/* I - Section */
1180*5e7646d2SAndroid Build Coastguard Worker 	      const char   *text,	/* I - Text */
1181*5e7646d2SAndroid Build Coastguard Worker 	      time_t       mtime,	/* I - Modification time */
1182*5e7646d2SAndroid Build Coastguard Worker               off_t        offset,	/* I - Offset in file */
1183*5e7646d2SAndroid Build Coastguard Worker 	      size_t       length)	/* I - Length in bytes */
1184*5e7646d2SAndroid Build Coastguard Worker {
1185*5e7646d2SAndroid Build Coastguard Worker   help_node_t	*n;			/* Node */
1186*5e7646d2SAndroid Build Coastguard Worker 
1187*5e7646d2SAndroid Build Coastguard Worker 
1188*5e7646d2SAndroid Build Coastguard Worker   n = (help_node_t *)calloc(1, sizeof(help_node_t));
1189*5e7646d2SAndroid Build Coastguard Worker   if (!n)
1190*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1191*5e7646d2SAndroid Build Coastguard Worker 
1192*5e7646d2SAndroid Build Coastguard Worker   n->filename = strdup(filename);
1193*5e7646d2SAndroid Build Coastguard Worker   n->anchor   = anchor ? strdup(anchor) : NULL;
1194*5e7646d2SAndroid Build Coastguard Worker   n->section  = (section && *section) ? strdup(section) : NULL;
1195*5e7646d2SAndroid Build Coastguard Worker   n->text     = strdup(text);
1196*5e7646d2SAndroid Build Coastguard Worker   n->mtime    = mtime;
1197*5e7646d2SAndroid Build Coastguard Worker   n->offset   = offset;
1198*5e7646d2SAndroid Build Coastguard Worker   n->length   = length;
1199*5e7646d2SAndroid Build Coastguard Worker 
1200*5e7646d2SAndroid Build Coastguard Worker   return (n);
1201*5e7646d2SAndroid Build Coastguard Worker }
1202*5e7646d2SAndroid Build Coastguard Worker 
1203*5e7646d2SAndroid Build Coastguard Worker 
1204*5e7646d2SAndroid Build Coastguard Worker /*
1205*5e7646d2SAndroid Build Coastguard Worker  * 'help_sort_nodes_by_name()' - Sort nodes by section, filename, and anchor.
1206*5e7646d2SAndroid Build Coastguard Worker  */
1207*5e7646d2SAndroid Build Coastguard Worker 
1208*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Difference */
help_sort_by_name(help_node_t * n1,help_node_t * n2)1209*5e7646d2SAndroid Build Coastguard Worker help_sort_by_name(help_node_t *n1,	/* I - First node */
1210*5e7646d2SAndroid Build Coastguard Worker                   help_node_t *n2)	/* I - Second node */
1211*5e7646d2SAndroid Build Coastguard Worker {
1212*5e7646d2SAndroid Build Coastguard Worker   int		diff;			/* Difference */
1213*5e7646d2SAndroid Build Coastguard Worker 
1214*5e7646d2SAndroid Build Coastguard Worker 
1215*5e7646d2SAndroid Build Coastguard Worker   if ((diff = strcmp(n1->filename, n2->filename)) != 0)
1216*5e7646d2SAndroid Build Coastguard Worker     return (diff);
1217*5e7646d2SAndroid Build Coastguard Worker 
1218*5e7646d2SAndroid Build Coastguard Worker   if (!n1->anchor && !n2->anchor)
1219*5e7646d2SAndroid Build Coastguard Worker     return (0);
1220*5e7646d2SAndroid Build Coastguard Worker   else if (!n1->anchor)
1221*5e7646d2SAndroid Build Coastguard Worker     return (-1);
1222*5e7646d2SAndroid Build Coastguard Worker   else if (!n2->anchor)
1223*5e7646d2SAndroid Build Coastguard Worker     return (1);
1224*5e7646d2SAndroid Build Coastguard Worker   else
1225*5e7646d2SAndroid Build Coastguard Worker     return (strcmp(n1->anchor, n2->anchor));
1226*5e7646d2SAndroid Build Coastguard Worker }
1227*5e7646d2SAndroid Build Coastguard Worker 
1228*5e7646d2SAndroid Build Coastguard Worker 
1229*5e7646d2SAndroid Build Coastguard Worker /*
1230*5e7646d2SAndroid Build Coastguard Worker  * 'help_sort_nodes_by_score()' - Sort nodes by score and text.
1231*5e7646d2SAndroid Build Coastguard Worker  */
1232*5e7646d2SAndroid Build Coastguard Worker 
1233*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Difference */
help_sort_by_score(help_node_t * n1,help_node_t * n2)1234*5e7646d2SAndroid Build Coastguard Worker help_sort_by_score(help_node_t *n1,	/* I - First node */
1235*5e7646d2SAndroid Build Coastguard Worker                    help_node_t *n2)	/* I - Second node */
1236*5e7646d2SAndroid Build Coastguard Worker {
1237*5e7646d2SAndroid Build Coastguard Worker   int		diff;			/* Difference */
1238*5e7646d2SAndroid Build Coastguard Worker 
1239*5e7646d2SAndroid Build Coastguard Worker 
1240*5e7646d2SAndroid Build Coastguard Worker   if (n1->score != n2->score)
1241*5e7646d2SAndroid Build Coastguard Worker     return (n2->score - n1->score);
1242*5e7646d2SAndroid Build Coastguard Worker 
1243*5e7646d2SAndroid Build Coastguard Worker   if (n1->section && !n2->section)
1244*5e7646d2SAndroid Build Coastguard Worker     return (1);
1245*5e7646d2SAndroid Build Coastguard Worker   else if (!n1->section && n2->section)
1246*5e7646d2SAndroid Build Coastguard Worker     return (-1);
1247*5e7646d2SAndroid Build Coastguard Worker   else if (n1->section && n2->section &&
1248*5e7646d2SAndroid Build Coastguard Worker            (diff = strcmp(n1->section, n2->section)) != 0)
1249*5e7646d2SAndroid Build Coastguard Worker     return (diff);
1250*5e7646d2SAndroid Build Coastguard Worker 
1251*5e7646d2SAndroid Build Coastguard Worker   return (_cups_strcasecmp(n1->text, n2->text));
1252*5e7646d2SAndroid Build Coastguard Worker }
1253*5e7646d2SAndroid Build Coastguard Worker 
1254*5e7646d2SAndroid Build Coastguard Worker 
1255*5e7646d2SAndroid Build Coastguard Worker /*
1256*5e7646d2SAndroid Build Coastguard Worker  * 'help_sort_words()' - Sort words alphabetically.
1257*5e7646d2SAndroid Build Coastguard Worker  */
1258*5e7646d2SAndroid Build Coastguard Worker 
1259*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Difference */
help_sort_words(help_word_t * w1,help_word_t * w2)1260*5e7646d2SAndroid Build Coastguard Worker help_sort_words(help_word_t *w1,	/* I - Second word */
1261*5e7646d2SAndroid Build Coastguard Worker                 help_word_t *w2)	/* I - Second word */
1262*5e7646d2SAndroid Build Coastguard Worker {
1263*5e7646d2SAndroid Build Coastguard Worker   return (_cups_strcasecmp(w1->text, w2->text));
1264*5e7646d2SAndroid Build Coastguard Worker }
1265