]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/help-index.c
2 * "$Id: help-index.c 6258 2007-02-11 01:16:31Z mike $"
4 * On-line help index routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2007 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * helpDeleteIndex() - Delete an index, freeing all memory used.
27 * helpFindNode() - Find a node in an index.
28 * helpLoadIndex() - Load a help index from disk.
29 * helpSaveIndex() - Save a help index to disk.
30 * helpSearchIndex() - Search an index.
31 * help_add_word() - Add a word to a node.
32 * help_compile_search() - Convert a search string into a regular expression.
33 * help_delete_node() - Free all memory used by a node.
34 * help_delete_word() - Free all memory used by a word.
35 * help_load_directory() - Load a directory of files into an index.
36 * help_load_file() - Load a HTML files into an index.
37 * help_new_node() - Create a new node and add it to an index.
38 * help_sort_nodes_by_name() - Sort nodes by section, filename, and anchor.
39 * help_sort_nodes_by_score() - Sort nodes by score and text.
40 * help_sort_words() - Sort words alphabetically.
44 * Include necessary headers...
47 #include "cgi-private.h"
52 * List of common English words that should not be indexed...
55 static char help_common_words
[][6] =
160 static help_word_t
*help_add_word(help_node_t
*n
, const char *text
);
161 static void help_delete_node(help_node_t
*n
);
162 static void help_delete_word(help_word_t
*w
);
163 static int help_load_directory(help_index_t
*hi
,
164 const char *directory
,
165 const char *relative
);
166 static int help_load_file(help_index_t
*hi
,
167 const char *filename
,
168 const char *relative
,
170 static help_node_t
*help_new_node(const char *filename
, const char *anchor
,
171 const char *section
, const char *text
,
172 time_t mtime
, off_t offset
,
174 static int help_sort_by_name(help_node_t
*p1
, help_node_t
*p2
);
175 static int help_sort_by_score(help_node_t
*p1
, help_node_t
*p2
);
176 static int help_sort_words(help_word_t
*w1
, help_word_t
*w2
);
180 * 'helpDeleteIndex()' - Delete an index, freeing all memory used.
184 helpDeleteIndex(help_index_t
*hi
) /* I - Help index */
186 help_node_t
*node
; /* Current node */
189 DEBUG_printf(("helpDeleteIndex(hi=%p)\n", hi
));
194 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
196 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
199 help_delete_node(node
);
202 cupsArrayDelete(hi
->nodes
);
203 cupsArrayDelete(hi
->sorted
);
210 * 'helpFindNode()' - Find a node in an index.
213 help_node_t
* /* O - Node pointer or NULL */
214 helpFindNode(help_index_t
*hi
, /* I - Index */
215 const char *filename
, /* I - Filename */
216 const char *anchor
) /* I - Anchor */
218 help_node_t key
; /* Search key */
221 DEBUG_printf(("helpFindNode(hi=%p, filename=\"%s\", anchor=\"%s\")\n",
222 hi
, filename
? filename
: "(nil)", anchor
? anchor
: "(nil)"));
225 * Range check input...
228 if (!hi
|| !filename
)
232 * Initialize the search key...
235 key
.filename
= (char *)filename
;
236 key
.anchor
= (char *)anchor
;
239 * Return any match...
242 return ((help_node_t
*)cupsArrayFind(hi
->nodes
, &key
));
247 * 'helpLoadIndex()' - Load a help index from disk.
250 help_index_t
* /* O - Index pointer or NULL */
251 helpLoadIndex(const char *hifile
, /* I - Index filename */
252 const char *directory
) /* I - Directory that is indexed */
254 help_index_t
*hi
; /* Help index */
255 cups_file_t
*fp
; /* Current file */
256 char line
[2048], /* Line from file */
257 *ptr
, /* Pointer into line */
258 *filename
, /* Filename in line */
259 *anchor
, /* Anchor in line */
260 *sectptr
, /* Section pointer in line */
261 section
[1024], /* Section name */
262 *text
; /* Text in line */
263 time_t mtime
; /* Modification time */
264 off_t offset
; /* Offset into file */
265 size_t length
; /* Length in bytes */
266 int update
; /* Update? */
267 help_node_t
*node
; /* Current node */
268 help_word_t
*word
; /* Current word */
271 DEBUG_printf(("helpLoadIndex(hifile=\"%s\", directory=\"%s\")\n",
275 * Create a new, empty index.
278 if ((hi
= (help_index_t
*)calloc(1, sizeof(help_index_t
))) == NULL
)
281 hi
->nodes
= cupsArrayNew((cups_array_func_t
)help_sort_by_name
, NULL
);
282 hi
->sorted
= cupsArrayNew((cups_array_func_t
)help_sort_by_score
, NULL
);
284 if (!hi
->nodes
|| !hi
->sorted
)
286 cupsArrayDelete(hi
->nodes
);
287 cupsArrayDelete(hi
->sorted
);
293 * Try loading the existing index file...
296 if ((fp
= cupsFileOpen(hifile
, "r")) != NULL
)
299 * Lock the file and then read the first line...
304 if (cupsFileGets(fp
, line
, sizeof(line
)) && !strcmp(line
, "HELPV2"))
307 * Got a valid header line, now read the data lines...
312 while (cupsFileGets(fp
, line
, sizeof(line
)))
315 * Each line looks like one of the following:
317 * filename mtime offset length "section" "text"
318 * filename#anchor offset length "text"
325 * Read a word in the current node...
328 if (!node
|| (ptr
= strrchr(line
, ' ')) == NULL
)
331 if ((word
= help_add_word(node
, ptr
+ 1)) != NULL
)
332 word
->count
= atoi(line
+ 1);
342 if ((ptr
= strchr(line
, ' ')) == NULL
)
345 while (isspace(*ptr
& 255))
348 if ((anchor
= strrchr(filename
, '#')) != NULL
)
354 mtime
= strtol(ptr
, &ptr
, 10);
356 offset
= strtoll(ptr
, &ptr
, 10);
357 length
= strtoll(ptr
, &ptr
, 10);
359 while (isspace(*ptr
& 255))
374 while (*ptr
&& *ptr
!= '\"')
382 strlcpy(section
, sectptr
, sizeof(section
));
384 while (isspace(*ptr
& 255))
394 while (*ptr
&& *ptr
!= '\"')
402 if ((node
= help_new_node(filename
, anchor
, section
, text
,
403 mtime
, offset
, length
)) == NULL
)
408 cupsArrayAdd(hi
->nodes
, node
);
417 * Scan for new/updated files...
420 update
= help_load_directory(hi
, directory
, NULL
);
423 * Remove any files that are no longer installed...
426 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
428 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
432 * Delete this node...
435 cupsArrayRemove(hi
->nodes
, node
);
436 help_delete_node(node
);
440 * Add nodes to the sorted array...
443 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
445 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
446 cupsArrayAdd(hi
->sorted
, node
);
449 * Save the index if we updated it...
453 helpSaveIndex(hi
, hifile
);
456 * Return the index...
464 * 'helpSaveIndex()' - Save a help index to disk.
467 int /* O - 0 on success, -1 on error */
468 helpSaveIndex(help_index_t
*hi
, /* I - Index */
469 const char *hifile
) /* I - Index filename */
471 cups_file_t
*fp
; /* Index file */
472 help_node_t
*node
; /* Current node */
473 help_word_t
*word
; /* Current word */
476 DEBUG_printf(("helpSaveIndex(hi=%p, hifile=\"%s\")\n", hi
, hifile
));
479 * Try creating a new index file...
482 if ((fp
= cupsFileOpen(hifile
, "w9")) == NULL
)
486 * Lock the file while we write it...
491 cupsFilePuts(fp
, "HELPV2\n");
493 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
495 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
498 * Write the current node with/without the anchor...
503 if (cupsFilePrintf(fp
, "%s#%s " CUPS_LLFMT
" " CUPS_LLFMT
" \"%s\"\n",
504 node
->filename
, node
->anchor
,
505 CUPS_LLCAST node
->offset
, CUPS_LLCAST node
->length
,
511 if (cupsFilePrintf(fp
, "%s %d " CUPS_LLFMT
" " CUPS_LLFMT
" \"%s\" \"%s\"\n",
512 node
->filename
, node
->mtime
,
513 CUPS_LLCAST node
->offset
, CUPS_LLCAST node
->length
,
514 node
->section
? node
->section
: "", node
->text
) < 0)
519 * Then write the words associated with the node...
522 for (word
= (help_word_t
*)cupsArrayFirst(node
->words
);
524 word
= (help_word_t
*)cupsArrayNext(node
->words
))
525 if (cupsFilePrintf(fp
, " %d %s\n", word
->count
, word
->text
) < 0)
531 if (cupsFileClose(fp
) < 0)
541 * 'helpSearchIndex()' - Search an index.
544 help_index_t
* /* O - Search index */
545 helpSearchIndex(help_index_t
*hi
, /* I - Index */
546 const char *query
, /* I - Query string */
547 const char *section
, /* I - Limit search to this section */
548 const char *filename
) /* I - Limit search to this file */
550 help_index_t
*search
; /* Search index */
551 help_node_t
*node
; /* Current node */
552 help_word_t
*word
; /* Current word */
553 void *sc
; /* Search context */
554 int matches
; /* Number of matches */
557 DEBUG_printf(("helpSearchIndex(hi=%p, query=\"%s\", filename=\"%s\")\n",
558 hi
, query
? query
: "(nil)",
559 filename
? filename
: "(nil)"));
569 * Reset the scores of all nodes to 0...
572 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
574 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
578 * Find the first node to search in...
583 node
= helpFindNode(hi
, filename
, NULL
);
588 node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
591 * Convert the query into a regular expression...
594 sc
= cgiCompileSearch(query
);
599 * Allocate a search index...
602 search
= calloc(1, sizeof(help_index_t
));
609 search
->nodes
= cupsArrayNew((cups_array_func_t
)help_sort_by_name
, NULL
);
610 search
->sorted
= cupsArrayNew((cups_array_func_t
)help_sort_by_score
, NULL
);
612 if (!search
->nodes
|| !search
->sorted
)
614 cupsArrayDelete(search
->nodes
);
615 cupsArrayDelete(search
->sorted
);
624 * Check each node in the index, adding matching nodes to the
628 for (; node
; node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
629 if (section
&& strcmp(node
->section
, section
))
631 else if (filename
&& strcmp(node
->filename
, filename
))
635 matches
= cgiDoSearch(sc
, node
->text
);
637 for (word
= (help_word_t
*)cupsArrayFirst(node
->words
);
639 word
= (help_word_t
*)cupsArrayNext(node
->words
))
640 if (cgiDoSearch(sc
, word
->text
) > 0)
641 matches
+= word
->count
;
646 * Found a match, add the node to the search index...
649 node
->score
= matches
;
651 cupsArrayAdd(search
->nodes
, node
);
652 cupsArrayAdd(search
->sorted
, node
);
657 * Free the search context...
663 * Return the results...
671 * 'help_add_word()' - Add a word to a node.
674 static help_word_t
* /* O - New word */
675 help_add_word(help_node_t
*n
, /* I - Node */
676 const char *text
) /* I - Word text */
678 help_word_t
*w
, /* New word */
679 key
; /* Search key */
682 DEBUG_printf(("help_add_word(n=%p, text=\"%s\")\n", n
, text
));
685 * Create the words array as needed...
689 n
->words
= cupsArrayNew((cups_array_func_t
)help_sort_words
, NULL
);
692 * See if the word is already added...
695 key
.text
= (char *)text
;
697 if ((w
= (help_word_t
*)cupsArrayFind(n
->words
, &key
)) == NULL
)
700 * Create a new word...
703 if ((w
= calloc(1, sizeof(help_word_t
))) == NULL
)
706 if ((w
->text
= strdup(text
)) == NULL
)
712 cupsArrayAdd(n
->words
, w
);
716 * Bump the counter for this word and return it...
726 * 'help_delete_node()' - Free all memory used by a node.
730 help_delete_node(help_node_t
*n
) /* I - Node */
732 help_word_t
*w
; /* Current word */
735 DEBUG_printf(("help_delete_node(n=%p)\n", n
));
752 for (w
= (help_word_t
*)cupsArrayFirst(n
->words
);
754 w
= (help_word_t
*)cupsArrayNext(n
->words
))
757 cupsArrayDelete(n
->words
);
764 * 'help_delete_word()' - Free all memory used by a word.
768 help_delete_word(help_word_t
*w
) /* I - Word */
770 DEBUG_printf(("help_delete_word(w=%p)\n", w
));
783 * 'help_load_directory()' - Load a directory of files into an index.
786 static int /* O - 0 = success, -1 = error, 1 = updated */
788 help_index_t
*hi
, /* I - Index */
789 const char *directory
, /* I - Directory */
790 const char *relative
) /* I - Relative path */
792 cups_dir_t
*dir
; /* Directory file */
793 cups_dentry_t
*dent
; /* Directory entry */
794 char *ext
, /* Pointer to extension */
795 filename
[1024], /* Full filename */
796 relname
[1024]; /* Relative filename */
797 int update
; /* Updated? */
798 help_node_t
*node
; /* Current node */
801 DEBUG_printf(("help_load_directory(hi=%p, directory=\"%s\", relative=\"%s\")\n",
802 hi
, directory
? directory
: "(nil)", relative
? relative
: "(nil)"));
805 * Open the directory and scan it...
808 if ((dir
= cupsDirOpen(directory
)) == NULL
)
813 while ((dent
= cupsDirRead(dir
)) != NULL
)
819 if (dent
->filename
[0] == '.')
823 * Get absolute and relative filenames...
826 snprintf(filename
, sizeof(filename
), "%s/%s", directory
, dent
->filename
);
828 snprintf(relname
, sizeof(relname
), "%s/%s", relative
, dent
->filename
);
830 strlcpy(relname
, dent
->filename
, sizeof(relname
));
833 * Check if we have a HTML file...
836 if ((ext
= strstr(dent
->filename
, ".html")) != NULL
&&
837 (!ext
[5] || !strcmp(ext
+ 5, ".gz")))
840 * HTML file, see if we have already indexed the file...
843 if ((node
= helpFindNode(hi
, relname
, NULL
)) != NULL
)
846 * File already indexed - check dates to confirm that the
847 * index is up-to-date...
850 if (node
->mtime
== dent
->fileinfo
.st_mtime
)
853 * Same modification time, so mark all of the nodes
854 * for this file as up-to-date...
857 for (; node
; node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
858 if (!strcmp(node
->filename
, relname
))
869 help_load_file(hi
, filename
, relname
, dent
->fileinfo
.st_mtime
);
871 else if (S_ISDIR(dent
->fileinfo
.st_mode
))
874 * Process sub-directory...
877 if (help_load_directory(hi
, filename
, relname
) == 1)
889 * 'help_load_file()' - Load a HTML files into an index.
892 static int /* O - 0 = success, -1 = error */
894 help_index_t
*hi
, /* I - Index */
895 const char *filename
, /* I - Filename */
896 const char *relative
, /* I - Relative path */
897 time_t mtime
) /* I - Modification time */
899 cups_file_t
*fp
; /* HTML file */
900 help_node_t
*node
; /* Current node */
901 char line
[1024], /* Line from file */
902 section
[1024], /* Section */
903 *ptr
, /* Pointer into line */
904 *anchor
, /* Anchor name */
905 *text
; /* Text for anchor */
906 off_t offset
; /* File offset */
907 char quote
; /* Quote character */
908 help_word_t
*word
; /* Current word */
909 int wordlen
; /* Length of word */
912 DEBUG_printf(("help_load_file(hi=%p, filename=\"%s\", relative=\"%s\", mtime=%ld)\n",
913 hi
, filename
? filename
: "(nil)",
914 relative
? relative
: "(nil)", mtime
));
916 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
922 strcpy(section
, "Other");
924 while (cupsFileGets(fp
, line
, sizeof(line
)))
927 * Look for "<TITLE>", "<A NAME", or "<!-- SECTION:" prefix...
930 if (!strncasecmp(line
, "<!-- SECTION:", 13))
933 * Got section line, copy it!
936 for (ptr
= line
+ 13; isspace(*ptr
& 255); ptr
++);
938 strlcpy(section
, ptr
, sizeof(section
));
939 if ((ptr
= strstr(section
, "-->")) != NULL
)
942 * Strip comment stuff from end of line...
945 for (*ptr
-- = '\0'; ptr
> line
&& isspace(*ptr
& 255); *ptr
-- = '\0');
947 if (isspace(*ptr
& 255))
953 for (ptr
= line
; (ptr
= strchr(ptr
, '<')) != NULL
;)
957 if (!strncasecmp(ptr
, "TITLE>", 6))
966 else if (!strncasecmp(ptr
, "A NAME=", 7))
974 if (*ptr
== '\"' || *ptr
== '\'')
977 * Get quoted anchor...
982 if ((ptr
= strchr(anchor
, quote
)) != NULL
)
990 * Get unquoted anchor...
995 for (ptr
= anchor
; *ptr
&& *ptr
!= '>' && !isspace(*ptr
& 255); ptr
++);
1004 * Got the anchor, now lets find the end...
1007 while (*ptr
&& *ptr
!= '>')
1019 * Now collect text for the link...
1023 while ((ptr
= strchr(text
, '<')) == NULL
)
1025 ptr
= text
+ strlen(text
);
1026 if (ptr
>= (line
+ sizeof(line
) - 2))
1031 if (!cupsFileGets(fp
, ptr
, sizeof(line
) - (ptr
- line
) - 1))
1038 node
->length
= offset
- node
->offset
;
1046 if ((node
= helpFindNode(hi
, relative
, anchor
)) != NULL
)
1049 * Node already in the index, so replace the text and other
1053 cupsArrayRemove(hi
->nodes
, node
);
1056 free(node
->section
);
1063 for (word
= (help_word_t
*)cupsArrayFirst(node
->words
);
1065 word
= (help_word_t
*)cupsArrayNext(node
->words
))
1066 help_delete_word(word
);
1068 cupsArrayDelete(node
->words
);
1072 node
->section
= section
[0] ? strdup(section
) : NULL
;
1073 node
->text
= strdup(text
);
1074 node
->mtime
= mtime
;
1075 node
->offset
= offset
;
1084 node
= help_new_node(relative
, anchor
, section
, text
, mtime
, offset
, 0);
1088 * Go through the text value and replace tabs and newlines with
1089 * whitespace and eliminate extra whitespace...
1092 for (ptr
= node
->text
, text
= node
->text
; *ptr
;)
1093 if (isspace(*ptr
& 255))
1095 while (isspace(*ptr
& 255))
1100 else if (text
!= ptr
)
1111 * (Re)add the node to the array...
1114 cupsArrayAdd(hi
->nodes
, node
);
1124 * Scan this line for words...
1127 for (ptr
= line
; *ptr
; ptr
++)
1130 * Skip HTML stuff...
1135 if (!strncmp(ptr
, "<!--", 4))
1138 * Skip HTML comment...
1141 if ((text
= strstr(ptr
+ 4, "-->")) == NULL
)
1142 ptr
+= strlen(ptr
) - 1;
1149 * Skip HTML element...
1152 for (ptr
++; *ptr
&& *ptr
!= '>'; ptr
++)
1153 if (*ptr
== '\"' || *ptr
== '\'')
1155 for (quote
= *ptr
++; *ptr
&& *ptr
!= quote
; ptr
++);
1167 else if (*ptr
== '&')
1170 * Skip HTML entity...
1173 for (ptr
++; *ptr
&& *ptr
!= ';'; ptr
++);
1180 else if (!isalnum(*ptr
& 255))
1184 * Found the start of a word, search until we find the end...
1187 for (text
= ptr
, ptr
++; *ptr
&& isalnum(*ptr
& 255); ptr
++);
1189 wordlen
= ptr
- text
;
1196 if (wordlen
> 1 && !bsearch(text
, help_common_words
,
1197 (sizeof(help_common_words
) /
1198 sizeof(help_common_words
[0])),
1199 sizeof(help_common_words
[0]),
1200 (int (*)(const void *, const void *))
1202 help_add_word(node
, text
);
1207 * Get the offset of the next line...
1210 offset
= cupsFileTell(fp
);
1216 node
->length
= offset
- node
->offset
;
1223 * 'help_new_node()' - Create a new node and add it to an index.
1226 static help_node_t
* /* O - Node pointer or NULL on error */
1227 help_new_node(const char *filename
, /* I - Filename */
1228 const char *anchor
, /* I - Anchor */
1229 const char *section
, /* I - Section */
1230 const char *text
, /* I - Text */
1231 time_t mtime
, /* I - Modification time */
1232 off_t offset
, /* I - Offset in file */
1233 size_t length
) /* I - Length in bytes */
1235 help_node_t
*n
; /* Node */
1238 DEBUG_printf(("help_new_node(filename=\"%s\", anchor=\"%s\", text=\"%s\", "
1239 "mtime=%ld, offset=%ld, length=%ld)\n",
1240 filename
? filename
: "(nil)", anchor
? anchor
: "(nil)",
1241 text
? text
: "(nil)", (long)mtime
, (long)offset
,
1244 n
= (help_node_t
*)calloc(1, sizeof(help_node_t
));
1248 n
->filename
= strdup(filename
);
1249 n
->anchor
= anchor
? strdup(anchor
) : NULL
;
1250 n
->section
= (section
&& *section
) ? strdup(section
) : NULL
;
1251 n
->text
= strdup(text
);
1261 * 'help_sort_nodes_by_name()' - Sort nodes by section, filename, and anchor.
1264 static int /* O - Difference */
1265 help_sort_by_name(help_node_t
*n1
, /* I - First node */
1266 help_node_t
*n2
) /* I - Second node */
1268 int diff
; /* Difference */
1271 DEBUG_printf(("help_sort_by_name(n1=%p(%s#%s), n2=%p(%s#%s)\n",
1272 n1
, n1
->filename
, n1
->anchor
? n1
->anchor
: "",
1273 n2
, n2
->filename
, n2
->anchor
? n2
->anchor
: ""));
1275 if ((diff
= strcmp(n1
->filename
, n2
->filename
)) != 0)
1278 if (!n1
->anchor
&& !n2
->anchor
)
1280 else if (!n1
->anchor
)
1282 else if (!n2
->anchor
)
1285 return (strcmp(n1
->anchor
, n2
->anchor
));
1290 * 'help_sort_nodes_by_score()' - Sort nodes by score and text.
1293 static int /* O - Difference */
1294 help_sort_by_score(help_node_t
*n1
, /* I - First node */
1295 help_node_t
*n2
) /* I - Second node */
1297 int diff
; /* Difference */
1300 DEBUG_printf(("help_sort_by_score(n1=%p(%d \"%s\" \"%s\"), "
1301 "n2=%p(%d \"%s\" \"%s\")\n",
1302 n1
, n1
->score
, n1
->section
? n1
->section
: "", n1
->text
,
1303 n2
, n2
->score
, n2
->section
? n2
->section
: "", n2
->text
));
1305 if (n1
->score
!= n2
->score
)
1306 return (n1
->score
- n2
->score
);
1308 if (n1
->section
&& !n2
->section
)
1310 else if (!n1
->section
&& n2
->section
)
1312 else if (n1
->section
&& n2
->section
&&
1313 (diff
= strcmp(n1
->section
, n2
->section
)) != 0)
1316 return (strcasecmp(n1
->text
, n2
->text
));
1321 * 'help_sort_words()' - Sort words alphabetically.
1324 static int /* O - Difference */
1325 help_sort_words(help_word_t
*w1
, /* I - Second word */
1326 help_word_t
*w2
) /* I - Second word */
1328 DEBUG_printf(("help_sort_words(w1=%p(\"%s\"), w2=%p(\"%s\"))\n",
1329 w1
, w1
->text
, w2
, w2
->text
));
1331 return (strcasecmp(w1
->text
, w2
->text
));
1336 * End of "$Id: help-index.c 6258 2007-02-11 01:16:31Z mike $".