/*
- * "$Id: help-index.c 4863 2005-12-03 04:28:10Z mike $"
+ * "$Id: help-index.c 7615 2008-05-25 07:17:07Z mike $"
*
- * On-line help index routines for the Common UNIX Printing System (CUPS).
+ * Online help index routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 1997-2005 by Easy Software Products.
+ * Copyright 2007-2008 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* Contents:
*
* helpLoadIndex() - Load a help index from disk.
* helpSaveIndex() - Save a help index to disk.
* helpSearchIndex() - Search an index.
+ * help_add_word() - Add a word to a node.
* help_compile_search() - Convert a search string into a regular expression.
- * help_create_sorted() - Create the sorted node array.
* help_delete_node() - Free all memory used by a node.
- * help_insert_node() - Insert a node in an index.
+ * help_delete_word() - Free all memory used by a word.
* help_load_directory() - Load a directory of files into an index.
* help_load_file() - Load a HTML files into an index.
* help_new_node() - Create a new node and add it to an index.
* help_sort_nodes_by_name() - Sort nodes by section, filename, and anchor.
* help_sort_nodes_by_score() - Sort nodes by score and text.
+ * help_sort_words() - Sort words alphabetically.
*/
/*
#include <cups/dir.h>
+/*
+ * List of common English words that should not be indexed...
+ */
+
+static char help_common_words[][6] =
+ {
+ "about",
+ "all",
+ "an",
+ "and",
+ "are",
+ "as",
+ "at",
+ "be",
+ "been",
+ "but",
+ "by",
+ "call",
+ "can",
+ "come",
+ "could",
+ "day",
+ "did",
+ "do",
+ "down",
+ "each",
+ "find",
+ "first",
+ "for",
+ "from",
+ "go",
+ "had",
+ "has",
+ "have",
+ "he",
+ "her",
+ "him",
+ "his",
+ "hot",
+ "how",
+ "if",
+ "in",
+ "is",
+ "it",
+ "know",
+ "like",
+ "long",
+ "look",
+ "make",
+ "many",
+ "may",
+ "more",
+ "most",
+ "my",
+ "no",
+ "now",
+ "of",
+ "on",
+ "one",
+ "or",
+ "other",
+ "out",
+ "over",
+ "said",
+ "see",
+ "she",
+ "side",
+ "so",
+ "some",
+ "sound",
+ "than",
+ "that",
+ "the",
+ "their",
+ "them",
+ "then",
+ "there",
+ "these",
+ "they",
+ "thing",
+ "this",
+ "time",
+ "to",
+ "two",
+ "up",
+ "use",
+ "was",
+ "water",
+ "way",
+ "we",
+ "were",
+ "what",
+ "when",
+ "which",
+ "who",
+ "will",
+ "with",
+ "word",
+ "would",
+ "write",
+ "you",
+ "your"
+ };
+
+
/*
* Local functions...
*/
-static void help_create_sorted(help_index_t *hi);
+static help_word_t *help_add_word(help_node_t *n, const char *text);
static void help_delete_node(help_node_t *n);
-static void help_insert_node(help_index_t *hi, help_node_t *n);
+static void help_delete_word(help_word_t *w);
static int help_load_directory(help_index_t *hi,
const char *directory,
const char *relative);
const char *section, const char *text,
time_t mtime, off_t offset,
size_t length);
-static int help_sort_by_name(const void *p1, const void *p2);
-static int help_sort_by_score(const void *p1, const void *p2);
+static int help_sort_by_name(help_node_t *p1, help_node_t *p2);
+static int help_sort_by_score(help_node_t *p1, help_node_t *p2);
+static int help_sort_words(help_word_t *w1, help_word_t *w2);
/*
*/
void
-helpDeleteIndex(help_index_t *hi)
+helpDeleteIndex(help_index_t *hi) /* I - Help index */
{
- int i; /* Looping var */
+ help_node_t *node; /* Current node */
DEBUG_printf(("helpDeleteIndex(hi=%p)\n", hi));
if (!hi)
return;
- if (!hi->search)
+ for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
+ node;
+ node = (help_node_t *)cupsArrayNext(hi->nodes))
{
- for (i = 0; i < hi->num_nodes; i ++)
- help_delete_node(hi->nodes[i]);
+ if (!hi->search)
+ help_delete_node(node);
}
- free(hi->nodes);
-
- if (hi->sorted)
- free(hi->sorted);
+ cupsArrayDelete(hi->nodes);
+ cupsArrayDelete(hi->sorted);
free(hi);
}
* 'helpFindNode()' - Find a node in an index.
*/
-help_node_t ** /* O - Node pointer or NULL */
+help_node_t * /* O - Node pointer or NULL */
helpFindNode(help_index_t *hi, /* I - Index */
const char *filename, /* I - Filename */
const char *anchor) /* I - Anchor */
{
- help_node_t key, /* Search key */
- *ptr; /* Pointer to key */
+ help_node_t key; /* Search key */
DEBUG_printf(("helpFindNode(hi=%p, filename=\"%s\", anchor=\"%s\")\n",
key.filename = (char *)filename;
key.anchor = (char *)anchor;
- ptr = &key;
/*
* Return any match...
*/
- return ((help_node_t **)bsearch(&ptr, hi->nodes, hi->num_nodes,
- sizeof(help_node_t *), help_sort_by_name));
+ return ((help_node_t *)cupsArrayFind(hi->nodes, &key));
}
off_t offset; /* Offset into file */
size_t length; /* Length in bytes */
int update; /* Update? */
- int i; /* Looping var */
help_node_t *node; /* Current node */
+ help_word_t *word; /* Current word */
DEBUG_printf(("helpLoadIndex(hifile=\"%s\", directory=\"%s\")\n",
* Create a new, empty index.
*/
- hi = (help_index_t *)calloc(1, sizeof(help_index_t));
+ if ((hi = (help_index_t *)calloc(1, sizeof(help_index_t))) == NULL)
+ return (NULL);
+
+ hi->nodes = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
+ hi->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
+
+ if (!hi->nodes || !hi->sorted)
+ {
+ cupsArrayDelete(hi->nodes);
+ cupsArrayDelete(hi->sorted);
+ free(hi);
+ return (NULL);
+ }
/*
* Try loading the existing index file...
cupsFileLock(fp, 1);
- if (cupsFileGets(fp, line, sizeof(line)) && !strcmp(line, "HELPV1"))
+ if (cupsFileGets(fp, line, sizeof(line)) && !strcmp(line, "HELPV2"))
{
/*
* Got a valid header line, now read the data lines...
*/
+ node = NULL;
+
while (cupsFileGets(fp, line, sizeof(line)))
{
/*
*
* filename mtime offset length "section" "text"
* filename#anchor offset length "text"
+ * SP count word
*/
- filename = line;
-
- if ((ptr = strchr(line, ' ')) == NULL)
- break;
-
- while (isspace(*ptr & 255))
- *ptr++ = '\0';
-
- if ((anchor = strrchr(filename, '#')) != NULL)
+ if (line[0] == ' ')
{
- *anchor++ = '\0';
- mtime = 0;
- }
- else
- mtime = strtol(ptr, &ptr, 10);
-
- offset = strtoll(ptr, &ptr, 10);
- length = strtoll(ptr, &ptr, 10);
+ /*
+ * Read a word in the current node...
+ */
- while (isspace(*ptr & 255))
- ptr ++;
+ if (!node || (ptr = strrchr(line, ' ')) == NULL)
+ continue;
- if (!anchor)
+ if ((word = help_add_word(node, ptr + 1)) != NULL)
+ word->count = atoi(line + 1);
+ }
+ else
{
/*
- * Get section...
+ * Add a node...
*/
- if (*ptr != '\"')
- break;
-
- ptr ++;
- sectptr = ptr;
+ filename = line;
- while (*ptr && *ptr != '\"')
- ptr ++;
+ if ((ptr = strchr(line, ' ')) == NULL)
+ break;
- if (*ptr != '\"')
- break;
+ while (isspace(*ptr & 255))
+ *ptr++ = '\0';
- *ptr++ = '\0';
+ if ((anchor = strrchr(filename, '#')) != NULL)
+ {
+ *anchor++ = '\0';
+ mtime = 0;
+ }
+ else
+ mtime = strtol(ptr, &ptr, 10);
- strlcpy(section, sectptr, sizeof(section));
+ offset = strtoll(ptr, &ptr, 10);
+ length = strtoll(ptr, &ptr, 10);
while (isspace(*ptr & 255))
ptr ++;
- }
- if (*ptr != '\"')
- break;
+ if (!anchor)
+ {
+ /*
+ * Get section...
+ */
- ptr ++;
- text = ptr;
+ if (*ptr != '\"')
+ break;
- while (*ptr && *ptr != '\"')
- ptr ++;
+ ptr ++;
+ sectptr = ptr;
- if (*ptr != '\"')
- break;
+ while (*ptr && *ptr != '\"')
+ ptr ++;
+
+ if (*ptr != '\"')
+ break;
+
+ *ptr++ = '\0';
+
+ strlcpy(section, sectptr, sizeof(section));
+
+ while (isspace(*ptr & 255))
+ ptr ++;
+ }
+
+ if (*ptr != '\"')
+ break;
+
+ ptr ++;
+ text = ptr;
+
+ while (*ptr && *ptr != '\"')
+ ptr ++;
+
+ if (*ptr != '\"')
+ break;
- *ptr++ = '\0';
+ *ptr++ = '\0';
- if ((node = help_new_node(filename, anchor, section, text,
- mtime, offset, length)) == NULL)
- break;
+ if ((node = help_new_node(filename, anchor, section, text,
+ mtime, offset, length)) == NULL)
+ break;
- help_insert_node(hi, node);
+ node->score = -1;
- node->score = -1;
+ cupsArrayAdd(hi->nodes, node);
+ }
}
}
* Remove any files that are no longer installed...
*/
- for (i = 0; i < hi->num_nodes;)
- {
- if (hi->nodes[i]->score < 0)
+ for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
+ node;
+ node = (help_node_t *)cupsArrayNext(hi->nodes))
+ if (node->score < 0)
{
/*
* Delete this node...
*/
- help_delete_node(hi->nodes[i]);
-
- hi->num_nodes --;
- if (i < hi->num_nodes)
- memmove(hi->nodes + i, hi->nodes + i + 1,
- (hi->num_nodes - i) * sizeof(help_node_t *));
-
- update = 1;
+ cupsArrayRemove(hi->nodes, node);
+ help_delete_node(node);
}
- else
- {
- /*
- * Keep this node...
- */
-
- i ++;
- }
- }
/*
- * Save the index if we updated it...
+ * Add nodes to the sorted array...
*/
- if (update)
- helpSaveIndex(hi, hifile);
+ for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
+ node;
+ node = (help_node_t *)cupsArrayNext(hi->nodes))
+ cupsArrayAdd(hi->sorted, node);
/*
- * Create the sorted array...
+ * Save the index if we updated it...
*/
- help_create_sorted(hi);
+ if (update)
+ helpSaveIndex(hi, hifile);
/*
* Return the index...
const char *hifile) /* I - Index filename */
{
cups_file_t *fp; /* Index file */
- int i; /* Looping var */
help_node_t *node; /* Current node */
+ help_word_t *word; /* Current word */
DEBUG_printf(("helpSaveIndex(hi=%p, hifile=\"%s\")\n", hi, hifile));
cupsFileLock(fp, 1);
- cupsFilePuts(fp, "HELPV1\n");
+ cupsFilePuts(fp, "HELPV2\n");
- for (i = 0; i < hi->num_nodes; i ++)
+ for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
+ node;
+ node = (help_node_t *)cupsArrayNext(hi->nodes))
{
/*
* Write the current node with/without the anchor...
*/
- node = hi->nodes[i];
-
if (node->anchor)
{
if (cupsFilePrintf(fp, "%s#%s " CUPS_LLFMT " " CUPS_LLFMT " \"%s\"\n",
else
{
if (cupsFilePrintf(fp, "%s %d " CUPS_LLFMT " " CUPS_LLFMT " \"%s\" \"%s\"\n",
- node->filename, node->mtime,
+ node->filename, (int)node->mtime,
CUPS_LLCAST node->offset, CUPS_LLCAST node->length,
node->section ? node->section : "", node->text) < 0)
break;
}
+
+ /*
+ * Then write the words associated with the node...
+ */
+
+ for (word = (help_word_t *)cupsArrayFirst(node->words);
+ word;
+ word = (help_word_t *)cupsArrayNext(node->words))
+ if (cupsFilePrintf(fp, " %d %s\n", word->count, word->text) < 0)
+ break;
}
+ cupsFileFlush(fp);
+
if (cupsFileClose(fp) < 0)
return (-1);
- else if (i < hi->num_nodes)
+ else if (node)
return (-1);
else
return (0);
const char *section, /* I - Limit search to this section */
const char *filename) /* I - Limit search to this file */
{
- int i; /* Looping var */
help_index_t *search; /* Search index */
- help_node_t **n; /* Current node */
+ help_node_t *node; /* Current node */
+ help_word_t *word; /* Current word */
void *sc; /* Search context */
int matches; /* Number of matches */
if (!hi || !query)
return (NULL);
- for (i = 0, n = hi->nodes; i < hi->num_nodes; i ++, n ++)
- n[0]->score = 0;
+ /*
+ * Reset the scores of all nodes to 0...
+ */
+
+ for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
+ node;
+ node = (help_node_t *)cupsArrayNext(hi->nodes))
+ node->score = 0;
+
+ /*
+ * Find the first node to search in...
+ */
if (filename)
{
- n = helpFindNode(hi, filename, NULL);
- if (!n)
+ node = helpFindNode(hi, filename, NULL);
+ if (!node)
return (NULL);
}
else
- n = hi->nodes;
+ node = (help_node_t *)cupsArrayFirst(hi->nodes);
/*
* Convert the query into a regular expression...
return (NULL);
}
+ search->nodes = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
+ search->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
+
+ if (!search->nodes || !search->sorted)
+ {
+ cupsArrayDelete(search->nodes);
+ cupsArrayDelete(search->sorted);
+ free(search);
+ cgiFreeSearch(sc);
+ return (NULL);
+ }
+
search->search = 1;
/*
* search index...
*/
- for (i = n - hi->nodes; i < hi->num_nodes; i ++, n ++)
- if (section && strcmp(n[0]->section, section))
+ for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
+ if (section && strcmp(node->section, section))
continue;
- else if (filename && strcmp(n[0]->filename, filename))
+ else if (filename && strcmp(node->filename, filename))
continue;
- else if ((matches = cgiDoSearch(sc, n[0]->text)) > 0)
+ else
{
- /*
- * Found a match, add the node to the search index...
- */
+ matches = cgiDoSearch(sc, node->text);
- help_insert_node(search, *n);
+ for (word = (help_word_t *)cupsArrayFirst(node->words);
+ word;
+ word = (help_word_t *)cupsArrayNext(node->words))
+ if (cgiDoSearch(sc, word->text) > 0)
+ matches += word->count;
- n[0]->score = matches;
+ if (matches > 0)
+ {
+ /*
+ * Found a match, add the node to the search index...
+ */
+
+ node->score = matches;
+
+ cupsArrayAdd(search->nodes, node);
+ cupsArrayAdd(search->sorted, node);
+ }
}
/*
cgiFreeSearch(sc);
- /*
- * Sort the results...
- */
-
- help_create_sorted(search);
-
/*
* Return the results...
*/
/*
- * 'help_create_sorted()' - Create the sorted node array.
+ * 'help_add_word()' - Add a word to a node.
*/
-static void
-help_create_sorted(help_index_t *hi) /* I - Index */
+static help_word_t * /* O - New word */
+help_add_word(help_node_t *n, /* I - Node */
+ const char *text) /* I - Word text */
{
- DEBUG_printf(("help_create_sorted(hi=%p)\n", hi));
+ help_word_t *w, /* New word */
+ key; /* Search key */
+
+
+ DEBUG_printf(("help_add_word(n=%p, text=\"%s\")\n", n, text));
/*
- * Free any existing sorted array...
+ * Create the words array as needed...
*/
- if (hi->sorted)
- free(hi->sorted);
+ if (!n->words)
+ n->words = cupsArrayNew((cups_array_func_t)help_sort_words, NULL);
/*
- * Create a new sorted array...
+ * See if the word is already added...
*/
- hi->sorted = calloc(hi->num_nodes, sizeof(help_node_t *));
+ key.text = (char *)text;
- if (!hi->sorted)
- return;
+ if ((w = (help_word_t *)cupsArrayFind(n->words, &key)) == NULL)
+ {
+ /*
+ * Create a new word...
+ */
- /*
- * Copy the nodes to the new array...
- */
+ if ((w = calloc(1, sizeof(help_word_t))) == NULL)
+ return (NULL);
- memcpy(hi->sorted, hi->nodes, hi->num_nodes * sizeof(help_node_t *));
+ if ((w->text = strdup(text)) == NULL)
+ {
+ free(w);
+ return (NULL);
+ }
+
+ cupsArrayAdd(n->words, w);
+ }
/*
- * Sort the new array by score and text.
+ * Bump the counter for this word and return it...
*/
- if (hi->num_nodes > 1)
- qsort(hi->sorted, hi->num_nodes, sizeof(help_node_t *),
- help_sort_by_score);
+ w->count ++;
+
+ return (w);
}
static void
help_delete_node(help_node_t *n) /* I - Node */
{
+ help_word_t *w; /* Current word */
+
+
DEBUG_printf(("help_delete_node(n=%p)\n", n));
if (!n)
if (n->text)
free(n->text);
+ for (w = (help_word_t *)cupsArrayFirst(n->words);
+ w;
+ w = (help_word_t *)cupsArrayNext(n->words))
+ help_delete_word(w);
+
+ cupsArrayDelete(n->words);
+
free(n);
}
/*
- * 'help_insert_node()' - Insert a node in an index.
+ * 'help_delete_word()' - Free all memory used by a word.
*/
static void
-help_insert_node(help_index_t *hi, /* I - Index */
- help_node_t *n) /* I - Node */
+help_delete_word(help_word_t *w) /* I - Word */
{
- int current, /* Current node */
- left, /* Left side */
- right, /* Right side */
- diff; /* Difference between nodes */
- help_node_t **temp; /* Temporary node pointer */
-
-
- DEBUG_printf(("help_insert_node(hi=%p, n=%p)\n", hi, n));
-
- /*
- * Allocate memory as needed...
- */
-
- if (hi->num_nodes >= hi->alloc_nodes)
- {
- /*
- * Expand the array in 128 node increments...
- */
-
- hi->alloc_nodes += 128;
- if (hi->alloc_nodes == 128)
- temp = (help_node_t **)malloc(hi->alloc_nodes * sizeof(help_node_t *));
- else
- temp = (help_node_t **)realloc(hi->nodes,
- hi->alloc_nodes * sizeof(help_node_t *));
-
- if (!temp)
- return;
+ DEBUG_printf(("help_delete_word(w=%p)\n", w));
- hi->nodes = temp;
- }
-
- /*
- * Find the insertion point...
- */
-
- if (hi->num_nodes == 0 ||
- help_sort_by_name(&n, hi->nodes + hi->num_nodes - 1) > 0)
- {
- /*
- * Last node...
- */
-
- hi->nodes[hi->num_nodes] = n;
- hi->num_nodes ++;
+ if (!w)
return;
- }
- else if (help_sort_by_name(&n, hi->nodes) < 0)
- {
- /*
- * First node...
- */
- memmove(hi->nodes + 1, hi->nodes, hi->num_nodes * sizeof(help_node_t *));
- hi->nodes[0] = n;
- hi->num_nodes ++;
- return;
- }
+ if (w->text)
+ free(w->text);
- /*
- * Otherwise, do a binary insertion...
- */
-
- left = 0;
- right = hi->num_nodes - 1;
-
- do
- {
- current = (left + right) / 2;
- diff = help_sort_by_name(&n, hi->nodes + current);
-
- if (!diff)
- break;
- else if (diff < 0)
- right = current;
- else
- left = current;
- }
- while ((right - left) > 1);
-
- if (diff > 0)
- current ++;
-
- memmove(hi->nodes + current + 1, hi->nodes + current,
- (hi->num_nodes - current) * sizeof(help_node_t *));
- hi->nodes[current] = n;
- hi->num_nodes ++;
+ free(w);
}
const char *directory, /* I - Directory */
const char *relative) /* I - Relative path */
{
- int i; /* Looping var */
cups_dir_t *dir; /* Directory file */
cups_dentry_t *dent; /* Directory entry */
char *ext, /* Pointer to extension */
filename[1024], /* Full filename */
relname[1024]; /* Relative filename */
int update; /* Updated? */
- help_node_t **node; /* Current node */
+ help_node_t *node; /* Current node */
DEBUG_printf(("help_load_directory(hi=%p, directory=\"%s\", relative=\"%s\")\n",
while ((dent = cupsDirRead(dir)) != NULL)
{
+ /*
+ * Skip "." files...
+ */
+
+ if (dent->filename[0] == '.')
+ continue;
+
/*
* Get absolute and relative filenames...
*/
* index is up-to-date...
*/
- if (node[0]->mtime == dent->fileinfo.st_mtime)
+ if (node->mtime == dent->fileinfo.st_mtime)
{
/*
* Same modification time, so mark all of the nodes
* for this file as up-to-date...
*/
- for (i = node - hi->nodes; i < hi->num_nodes; i ++, node ++)
- if (!strcmp(node[0]->filename, relname))
- node[0]->score = 0;
+ for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
+ if (!strcmp(node->filename, relname))
+ node->score = 0;
else
break;
time_t mtime) /* I - Modification time */
{
cups_file_t *fp; /* HTML file */
- help_node_t *node, /* Current node */
- **n; /* Node pointer */
+ help_node_t *node; /* Current node */
char line[1024], /* Line from file */
+ temp[1024], /* Temporary word */
section[1024], /* Section */
*ptr, /* Pointer into line */
*anchor, /* Anchor name */
*text; /* Text for anchor */
off_t offset; /* File offset */
char quote; /* Quote character */
+ help_word_t *word; /* Current word */
+ int wordlen; /* Length of word */
DEBUG_printf(("help_load_file(hi=%p, filename=\"%s\", relative=\"%s\", mtime=%ld)\n",
break;
}
- if ((n = helpFindNode(hi, relative, anchor)) != NULL)
+ if ((node = helpFindNode(hi, relative, anchor)) != NULL)
{
/*
* Node already in the index, so replace the text and other
* data...
*/
- node = n[0];
+ cupsArrayRemove(hi->nodes, node);
if (node->section)
free(node->section);
if (node->text)
free(node->text);
+ if (node->words)
+ {
+ for (word = (help_word_t *)cupsArrayFirst(node->words);
+ word;
+ word = (help_word_t *)cupsArrayNext(node->words))
+ help_delete_word(word);
+
+ cupsArrayDelete(node->words);
+ node->words = NULL;
+ }
+
node->section = section[0] ? strdup(section) : NULL;
node->text = strdup(text);
node->mtime = mtime;
*/
node = help_new_node(relative, anchor, section, text, mtime, offset, 0);
- help_insert_node(hi, node);
}
/*
if (isspace(*ptr & 255))
{
while (isspace(*ptr & 255))
- *ptr ++;
+ ptr ++;
*text++ = ' ';
}
*text = '\0';
+ /*
+ * (Re)add the node to the array...
+ */
+
+ cupsArrayAdd(hi->nodes, node);
+
+ if (!anchor)
+ node = NULL;
break;
}
+ if (node)
+ {
+ /*
+ * Scan this line for words...
+ */
+
+ for (ptr = line; *ptr; ptr ++)
+ {
+ /*
+ * Skip HTML stuff...
+ */
+
+ if (*ptr == '<')
+ {
+ if (!strncmp(ptr, "<!--", 4))
+ {
+ /*
+ * Skip HTML comment...
+ */
+
+ if ((text = strstr(ptr + 4, "-->")) == NULL)
+ ptr += strlen(ptr) - 1;
+ else
+ ptr = text + 2;
+ }
+ else
+ {
+ /*
+ * Skip HTML element...
+ */
+
+ for (ptr ++; *ptr && *ptr != '>'; ptr ++)
+ {
+ if (*ptr == '\"' || *ptr == '\'')
+ {
+ for (quote = *ptr++; *ptr && *ptr != quote; ptr ++);
+
+ if (!*ptr)
+ ptr --;
+ }
+ }
+
+ if (!*ptr)
+ ptr --;
+ }
+
+ continue;
+ }
+ else if (*ptr == '&')
+ {
+ /*
+ * Skip HTML entity...
+ */
+
+ for (ptr ++; *ptr && *ptr != ';'; ptr ++);
+
+ if (!*ptr)
+ ptr --;
+
+ continue;
+ }
+ else if (!isalnum(*ptr & 255))
+ continue;
+
+ /*
+ * Found the start of a word, search until we find the end...
+ */
+
+ for (text = ptr, ptr ++; *ptr && isalnum(*ptr & 255); ptr ++);
+
+ wordlen = ptr - text;
+
+ memcpy(temp, text, wordlen);
+ temp[wordlen] = '\0';
+
+ ptr --;
+
+ if (wordlen > 1 && !bsearch(temp, help_common_words,
+ (sizeof(help_common_words) /
+ sizeof(help_common_words[0])),
+ sizeof(help_common_words[0]),
+ (int (*)(const void *, const void *))
+ strcasecmp))
+ help_add_word(node, temp);
+ }
+ }
+
/*
* Get the offset of the next line...
*/
help_node_t *n; /* Node */
- DEBUG_printf(("help_new_node(filename=\"%s\", anchor=\"%s\", text=\"%s\", mtime=%ld, offset=%ld, length=%ld)\n",
+ DEBUG_printf(("help_new_node(filename=\"%s\", anchor=\"%s\", text=\"%s\", "
+ "mtime=%ld, offset=%ld, length=%ld)\n",
filename ? filename : "(nil)", anchor ? anchor : "(nil)",
- text ? text : "(nil)", mtime, offset, length));
+ text ? text : "(nil)", (long)mtime, (long)offset,
+ (long)length));
n = (help_node_t *)calloc(1, sizeof(help_node_t));
if (!n)
*/
static int /* O - Difference */
-help_sort_by_name(const void *p1, /* I - First node */
- const void *p2) /* I - Second node */
+help_sort_by_name(help_node_t *n1, /* I - First node */
+ help_node_t *n2) /* I - Second node */
{
- help_node_t **n1, /* First node */
- **n2; /* Second node */
int diff; /* Difference */
- DEBUG_printf(("help_sort_by_name(p1=%p, p2=%p)\n", p1, p2));
-
- n1 = (help_node_t **)p1;
- n2 = (help_node_t **)p2;
+ DEBUG_printf(("help_sort_by_name(n1=%p(%s#%s), n2=%p(%s#%s)\n",
+ n1, n1->filename, n1->anchor ? n1->anchor : "",
+ n2, n2->filename, n2->anchor ? n2->anchor : ""));
- if ((diff = strcmp(n1[0]->filename, n2[0]->filename)) != 0)
+ if ((diff = strcmp(n1->filename, n2->filename)) != 0)
return (diff);
- if (!n1[0]->anchor && !n2[0]->anchor)
+ if (!n1->anchor && !n2->anchor)
return (0);
- else if (!n1[0]->anchor)
+ else if (!n1->anchor)
return (-1);
- else if (!n2[0]->anchor)
+ else if (!n2->anchor)
return (1);
else
- return (strcmp(n1[0]->anchor, n2[0]->anchor));
+ return (strcmp(n1->anchor, n2->anchor));
}
*/
static int /* O - Difference */
-help_sort_by_score(const void *p1, /* I - First node */
- const void *p2) /* I - Second node */
+help_sort_by_score(help_node_t *n1, /* I - First node */
+ help_node_t *n2) /* I - Second node */
{
- help_node_t **n1, /* First node */
- **n2; /* Second node */
int diff; /* Difference */
- DEBUG_printf(("help_sort_by_score(p1=%p, p2=%p)\n", p1, p2));
+ DEBUG_printf(("help_sort_by_score(n1=%p(%d \"%s\" \"%s\"), "
+ "n2=%p(%d \"%s\" \"%s\")\n",
+ n1, n1->score, n1->section ? n1->section : "", n1->text,
+ n2, n2->score, n2->section ? n2->section : "", n2->text));
- n1 = (help_node_t **)p1;
- n2 = (help_node_t **)p2;
+ if (n1->score != n2->score)
+ return (n2->score - n1->score);
- if (n1[0]->score != n2[0]->score)
- return (n1[0]->score - n2[0]->score);
-
- if (n1[0]->section && !n2[0]->section)
+ if (n1->section && !n2->section)
return (1);
- else if (!n1[0]->section && n2[0]->section)
+ else if (!n1->section && n2->section)
return (-1);
- else if (n1[0]->section && n2[0]->section &&
- (diff = strcmp(n1[0]->section, n2[0]->section)) != 0)
+ else if (n1->section && n2->section &&
+ (diff = strcmp(n1->section, n2->section)) != 0)
return (diff);
- return (strcasecmp(n1[0]->text, n2[0]->text));
+ return (strcasecmp(n1->text, n2->text));
+}
+
+
+/*
+ * 'help_sort_words()' - Sort words alphabetically.
+ */
+
+static int /* O - Difference */
+help_sort_words(help_word_t *w1, /* I - Second word */
+ help_word_t *w2) /* I - Second word */
+{
+ DEBUG_printf(("help_sort_words(w1=%p(\"%s\"), w2=%p(\"%s\"))\n",
+ w1, w1->text, w2, w2->text));
+
+ return (strcasecmp(w1->text, w2->text));
}
/*
- * End of "$Id: help-index.c 4863 2005-12-03 04:28:10Z mike $".
+ * End of "$Id: help-index.c 7615 2008-05-25 07:17:07Z mike $".
*/