|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Online help index routines for CUPS.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* Copyright 2007-2015 by Apple Inc.
|
|
Packit |
2fc92b |
* Copyright 1997-2007 by Easy Software Products.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* These coded instructions, statements, and computer programs are the
|
|
Packit |
2fc92b |
* property of Apple Inc. and are protected by Federal copyright
|
|
Packit |
2fc92b |
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
|
|
Packit |
2fc92b |
* which should have been included with this file. If this file is
|
|
Packit |
2fc92b |
* missing or damaged, see the license at "http://www.cups.org/".
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Include necessary headers...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
#include "cgi-private.h"
|
|
Packit |
2fc92b |
#include <cups/dir.h>
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* List of common English words that should not be indexed...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static char help_common_words[][6] =
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
"about",
|
|
Packit |
2fc92b |
"all",
|
|
Packit |
2fc92b |
"an",
|
|
Packit |
2fc92b |
"and",
|
|
Packit |
2fc92b |
"are",
|
|
Packit |
2fc92b |
"as",
|
|
Packit |
2fc92b |
"at",
|
|
Packit |
2fc92b |
"be",
|
|
Packit |
2fc92b |
"been",
|
|
Packit |
2fc92b |
"but",
|
|
Packit |
2fc92b |
"by",
|
|
Packit |
2fc92b |
"call",
|
|
Packit |
2fc92b |
"can",
|
|
Packit |
2fc92b |
"come",
|
|
Packit |
2fc92b |
"could",
|
|
Packit |
2fc92b |
"day",
|
|
Packit |
2fc92b |
"did",
|
|
Packit |
2fc92b |
"do",
|
|
Packit |
2fc92b |
"down",
|
|
Packit |
2fc92b |
"each",
|
|
Packit |
2fc92b |
"find",
|
|
Packit |
2fc92b |
"first",
|
|
Packit |
2fc92b |
"for",
|
|
Packit |
2fc92b |
"from",
|
|
Packit |
2fc92b |
"go",
|
|
Packit |
2fc92b |
"had",
|
|
Packit |
2fc92b |
"has",
|
|
Packit |
2fc92b |
"have",
|
|
Packit |
2fc92b |
"he",
|
|
Packit |
2fc92b |
"her",
|
|
Packit |
2fc92b |
"him",
|
|
Packit |
2fc92b |
"his",
|
|
Packit |
2fc92b |
"hot",
|
|
Packit |
2fc92b |
"how",
|
|
Packit |
2fc92b |
"if",
|
|
Packit |
2fc92b |
"in",
|
|
Packit |
2fc92b |
"is",
|
|
Packit |
2fc92b |
"it",
|
|
Packit |
2fc92b |
"know",
|
|
Packit |
2fc92b |
"like",
|
|
Packit |
2fc92b |
"long",
|
|
Packit |
2fc92b |
"look",
|
|
Packit |
2fc92b |
"make",
|
|
Packit |
2fc92b |
"many",
|
|
Packit |
2fc92b |
"may",
|
|
Packit |
2fc92b |
"more",
|
|
Packit |
2fc92b |
"most",
|
|
Packit |
2fc92b |
"my",
|
|
Packit |
2fc92b |
"no",
|
|
Packit |
2fc92b |
"now",
|
|
Packit |
2fc92b |
"of",
|
|
Packit |
2fc92b |
"on",
|
|
Packit |
2fc92b |
"one",
|
|
Packit |
2fc92b |
"or",
|
|
Packit |
2fc92b |
"other",
|
|
Packit |
2fc92b |
"out",
|
|
Packit |
2fc92b |
"over",
|
|
Packit |
2fc92b |
"said",
|
|
Packit |
2fc92b |
"see",
|
|
Packit |
2fc92b |
"she",
|
|
Packit |
2fc92b |
"side",
|
|
Packit |
2fc92b |
"so",
|
|
Packit |
2fc92b |
"some",
|
|
Packit |
2fc92b |
"sound",
|
|
Packit |
2fc92b |
"than",
|
|
Packit |
2fc92b |
"that",
|
|
Packit |
2fc92b |
"the",
|
|
Packit |
2fc92b |
"their",
|
|
Packit |
2fc92b |
"them",
|
|
Packit |
2fc92b |
"then",
|
|
Packit |
2fc92b |
"there",
|
|
Packit |
2fc92b |
"these",
|
|
Packit |
2fc92b |
"they",
|
|
Packit |
2fc92b |
"thing",
|
|
Packit |
2fc92b |
"this",
|
|
Packit |
2fc92b |
"time",
|
|
Packit |
2fc92b |
"to",
|
|
Packit |
2fc92b |
"two",
|
|
Packit |
2fc92b |
"up",
|
|
Packit |
2fc92b |
"use",
|
|
Packit |
2fc92b |
"was",
|
|
Packit |
2fc92b |
"water",
|
|
Packit |
2fc92b |
"way",
|
|
Packit |
2fc92b |
"we",
|
|
Packit |
2fc92b |
"were",
|
|
Packit |
2fc92b |
"what",
|
|
Packit |
2fc92b |
"when",
|
|
Packit |
2fc92b |
"which",
|
|
Packit |
2fc92b |
"who",
|
|
Packit |
2fc92b |
"will",
|
|
Packit |
2fc92b |
"with",
|
|
Packit |
2fc92b |
"word",
|
|
Packit |
2fc92b |
"would",
|
|
Packit |
2fc92b |
"write",
|
|
Packit |
2fc92b |
"you",
|
|
Packit |
2fc92b |
"your"
|
|
Packit |
2fc92b |
};
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Local functions...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static help_word_t *help_add_word(help_node_t *n, const char *text);
|
|
Packit |
2fc92b |
static void help_delete_node(help_node_t *n);
|
|
Packit |
2fc92b |
static void help_delete_word(help_word_t *w);
|
|
Packit |
2fc92b |
static int help_load_directory(help_index_t *hi,
|
|
Packit |
2fc92b |
const char *directory,
|
|
Packit |
2fc92b |
const char *relative);
|
|
Packit |
2fc92b |
static int help_load_file(help_index_t *hi,
|
|
Packit |
2fc92b |
const char *filename,
|
|
Packit |
2fc92b |
const char *relative,
|
|
Packit |
2fc92b |
time_t mtime);
|
|
Packit |
2fc92b |
static help_node_t *help_new_node(const char *filename, const char *anchor,
|
|
Packit |
2fc92b |
const char *section, const char *text,
|
|
Packit |
2fc92b |
time_t mtime, off_t offset,
|
|
Packit |
2fc92b |
size_t length)
|
|
Packit |
2fc92b |
__attribute__((nonnull(1,3,4)));
|
|
Packit |
2fc92b |
static int help_sort_by_name(help_node_t *p1, help_node_t *p2);
|
|
Packit |
2fc92b |
static int help_sort_by_score(help_node_t *p1, help_node_t *p2);
|
|
Packit |
2fc92b |
static int help_sort_words(help_word_t *w1, help_word_t *w2);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'helpDeleteIndex()' - Delete an index, freeing all memory used.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
void
|
|
Packit |
2fc92b |
helpDeleteIndex(help_index_t *hi) /* I - Help index */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
help_node_t *node; /* Current node */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("helpDeleteIndex(hi=%p)", hi));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!hi)
|
|
Packit |
2fc92b |
return;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
|
|
Packit |
2fc92b |
node;
|
|
Packit |
2fc92b |
node = (help_node_t *)cupsArrayNext(hi->nodes))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (!hi->search)
|
|
Packit |
2fc92b |
help_delete_node(node);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayDelete(hi->nodes);
|
|
Packit |
2fc92b |
cupsArrayDelete(hi->sorted);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
free(hi);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'helpFindNode()' - Find a node in an index.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
help_node_t * /* O - Node pointer or NULL */
|
|
Packit |
2fc92b |
helpFindNode(help_index_t *hi, /* I - Index */
|
|
Packit |
2fc92b |
const char *filename, /* I - Filename */
|
|
Packit |
2fc92b |
const char *anchor) /* I - Anchor */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
help_node_t key; /* Search key */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("helpFindNode(hi=%p, filename=\"%s\", anchor=\"%s\")",
|
|
Packit |
2fc92b |
hi, filename, anchor));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Range check input...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!hi || !filename)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Initialize the search key...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
key.filename = (char *)filename;
|
|
Packit |
2fc92b |
key.anchor = (char *)anchor;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Return any match...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return ((help_node_t *)cupsArrayFind(hi->nodes, &key));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'helpLoadIndex()' - Load a help index from disk.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
help_index_t * /* O - Index pointer or NULL */
|
|
Packit |
2fc92b |
helpLoadIndex(const char *hifile, /* I - Index filename */
|
|
Packit |
2fc92b |
const char *directory) /* I - Directory that is indexed */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
help_index_t *hi; /* Help index */
|
|
Packit |
2fc92b |
cups_file_t *fp; /* Current file */
|
|
Packit |
2fc92b |
char line[2048], /* Line from file */
|
|
Packit |
2fc92b |
*ptr, /* Pointer into line */
|
|
Packit |
2fc92b |
*filename, /* Filename in line */
|
|
Packit |
2fc92b |
*anchor, /* Anchor in line */
|
|
Packit |
2fc92b |
*sectptr, /* Section pointer in line */
|
|
Packit |
2fc92b |
section[1024], /* Section name */
|
|
Packit |
2fc92b |
*text; /* Text in line */
|
|
Packit |
2fc92b |
time_t mtime; /* Modification time */
|
|
Packit |
2fc92b |
off_t offset; /* Offset into file */
|
|
Packit |
2fc92b |
size_t length; /* Length in bytes */
|
|
Packit |
2fc92b |
int update; /* Update? */
|
|
Packit |
2fc92b |
help_node_t *node; /* Current node */
|
|
Packit |
2fc92b |
help_word_t *word; /* Current word */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("helpLoadIndex(hifile=\"%s\", directory=\"%s\")",
|
|
Packit |
2fc92b |
hifile, directory));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Create a new, empty index.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((hi = (help_index_t *)calloc(1, sizeof(help_index_t))) == NULL)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
hi->nodes = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
|
|
Packit |
2fc92b |
hi->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!hi->nodes || !hi->sorted)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsArrayDelete(hi->nodes);
|
|
Packit |
2fc92b |
cupsArrayDelete(hi->sorted);
|
|
Packit |
2fc92b |
free(hi);
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Try loading the existing index file...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((fp = cupsFileOpen(hifile, "r")) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Lock the file and then read the first line...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsFileLock(fp, 1);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (cupsFileGets(fp, line, sizeof(line)) && !strcmp(line, "HELPV2"))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Got a valid header line, now read the data lines...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
node = NULL;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (cupsFileGets(fp, line, sizeof(line)))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Each line looks like one of the following:
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* filename mtime offset length "section" "text"
|
|
Packit |
2fc92b |
* filename#anchor offset length "text"
|
|
Packit |
2fc92b |
* SP count word
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (line[0] == ' ')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Read a word in the current node...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!node || (ptr = strrchr(line, ' ')) == NULL)
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((word = help_add_word(node, ptr + 1)) != NULL)
|
|
Packit |
2fc92b |
word->count = atoi(line + 1);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Add a node...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
filename = line;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((ptr = strchr(line, ' ')) == NULL)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (isspace(*ptr & 255))
|
|
Packit |
2fc92b |
*ptr++ = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((anchor = strrchr(filename, '#')) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
*anchor++ = '\0';
|
|
Packit |
2fc92b |
mtime = 0;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
mtime = strtol(ptr, &ptr, 10);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
offset = strtoll(ptr, &ptr, 10);
|
|
Packit |
2fc92b |
length = (size_t)strtoll(ptr, &ptr, 10);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (isspace(*ptr & 255))
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!anchor)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Get section...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr != '\"')
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
sectptr = ptr;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (*ptr && *ptr != '\"')
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr != '\"')
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*ptr++ = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
strlcpy(section, sectptr, sizeof(section));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (isspace(*ptr & 255))
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr != '\"')
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
text = ptr;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (*ptr && *ptr != '\"')
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr != '\"')
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*ptr++ = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((node = help_new_node(filename, anchor, section, text,
|
|
Packit |
2fc92b |
mtime, offset, length)) == NULL)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
node->score = -1;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayAdd(hi->nodes, node);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsFileClose(fp);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Scan for new/updated files...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
update = help_load_directory(hi, directory, NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Remove any files that are no longer installed...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
|
|
Packit |
2fc92b |
node;
|
|
Packit |
2fc92b |
node = (help_node_t *)cupsArrayNext(hi->nodes))
|
|
Packit |
2fc92b |
if (node->score < 0)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Delete this node...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayRemove(hi->nodes, node);
|
|
Packit |
2fc92b |
help_delete_node(node);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Add nodes to the sorted array...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
|
|
Packit |
2fc92b |
node;
|
|
Packit |
2fc92b |
node = (help_node_t *)cupsArrayNext(hi->nodes))
|
|
Packit |
2fc92b |
cupsArrayAdd(hi->sorted, node);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Save the index if we updated it...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (update)
|
|
Packit |
2fc92b |
helpSaveIndex(hi, hifile);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Return the index...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (hi);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'helpSaveIndex()' - Save a help index to disk.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
int /* O - 0 on success, -1 on error */
|
|
Packit |
2fc92b |
helpSaveIndex(help_index_t *hi, /* I - Index */
|
|
Packit |
2fc92b |
const char *hifile) /* I - Index filename */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cups_file_t *fp; /* Index file */
|
|
Packit |
2fc92b |
help_node_t *node; /* Current node */
|
|
Packit |
2fc92b |
help_word_t *word; /* Current word */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("helpSaveIndex(hi=%p, hifile=\"%s\")", hi, hifile));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Try creating a new index file...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((fp = cupsFileOpen(hifile, "w9")) == NULL)
|
|
Packit |
2fc92b |
return (-1);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Lock the file while we write it...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsFileLock(fp, 1);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsFilePuts(fp, "HELPV2\n");
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
|
|
Packit |
2fc92b |
node;
|
|
Packit |
2fc92b |
node = (help_node_t *)cupsArrayNext(hi->nodes))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Write the current node with/without the anchor...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node->anchor)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (cupsFilePrintf(fp, "%s#%s " CUPS_LLFMT " " CUPS_LLFMT " \"%s\"\n",
|
|
Packit |
2fc92b |
node->filename, node->anchor,
|
|
Packit |
2fc92b |
CUPS_LLCAST node->offset, CUPS_LLCAST node->length,
|
|
Packit |
2fc92b |
node->text) < 0)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (cupsFilePrintf(fp, "%s %d " CUPS_LLFMT " " CUPS_LLFMT " \"%s\" \"%s\"\n",
|
|
Packit |
2fc92b |
node->filename, (int)node->mtime,
|
|
Packit |
2fc92b |
CUPS_LLCAST node->offset, CUPS_LLCAST node->length,
|
|
Packit |
2fc92b |
node->section ? node->section : "", node->text) < 0)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Then write the words associated with the node...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (word = (help_word_t *)cupsArrayFirst(node->words);
|
|
Packit |
2fc92b |
word;
|
|
Packit |
2fc92b |
word = (help_word_t *)cupsArrayNext(node->words))
|
|
Packit |
2fc92b |
if (cupsFilePrintf(fp, " %d %s\n", word->count, word->text) < 0)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsFileFlush(fp);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (cupsFileClose(fp) < 0)
|
|
Packit |
2fc92b |
return (-1);
|
|
Packit |
2fc92b |
else if (node)
|
|
Packit |
2fc92b |
return (-1);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
return (0);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'helpSearchIndex()' - Search an index.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
help_index_t * /* O - Search index */
|
|
Packit |
2fc92b |
helpSearchIndex(help_index_t *hi, /* I - Index */
|
|
Packit |
2fc92b |
const char *query, /* I - Query string */
|
|
Packit |
2fc92b |
const char *section, /* I - Limit search to this section */
|
|
Packit |
2fc92b |
const char *filename) /* I - Limit search to this file */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
help_index_t *search; /* Search index */
|
|
Packit |
2fc92b |
help_node_t *node; /* Current node */
|
|
Packit |
2fc92b |
help_word_t *word; /* Current word */
|
|
Packit |
2fc92b |
void *sc; /* Search context */
|
|
Packit |
2fc92b |
int matches; /* Number of matches */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("helpSearchIndex(hi=%p, query=\"%s\", filename=\"%s\")",
|
|
Packit |
2fc92b |
hi, query, filename));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Range check...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!hi || !query)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Reset the scores of all nodes to 0...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
|
|
Packit |
2fc92b |
node;
|
|
Packit |
2fc92b |
node = (help_node_t *)cupsArrayNext(hi->nodes))
|
|
Packit |
2fc92b |
node->score = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Find the first node to search in...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (filename)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
node = helpFindNode(hi, filename, NULL);
|
|
Packit |
2fc92b |
if (!node)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
node = (help_node_t *)cupsArrayFirst(hi->nodes);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Convert the query into a regular expression...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
sc = cgiCompileSearch(query);
|
|
Packit |
2fc92b |
if (!sc)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Allocate a search index...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
search = calloc(1, sizeof(help_index_t));
|
|
Packit |
2fc92b |
if (!search)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cgiFreeSearch(sc);
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
search->nodes = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
|
|
Packit |
2fc92b |
search->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!search->nodes || !search->sorted)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cupsArrayDelete(search->nodes);
|
|
Packit |
2fc92b |
cupsArrayDelete(search->sorted);
|
|
Packit |
2fc92b |
free(search);
|
|
Packit |
2fc92b |
cgiFreeSearch(sc);
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
search->search = 1;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Check each node in the index, adding matching nodes to the
|
|
Packit |
2fc92b |
* search index...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
|
|
Packit |
2fc92b |
if (section && strcmp(node->section, section))
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
else if (filename && strcmp(node->filename, filename))
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
matches = cgiDoSearch(sc, node->text);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (word = (help_word_t *)cupsArrayFirst(node->words);
|
|
Packit |
2fc92b |
word;
|
|
Packit |
2fc92b |
word = (help_word_t *)cupsArrayNext(node->words))
|
|
Packit |
2fc92b |
if (cgiDoSearch(sc, word->text) > 0)
|
|
Packit |
2fc92b |
matches += word->count;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (matches > 0)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Found a match, add the node to the search index...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
node->score = matches;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayAdd(search->nodes, node);
|
|
Packit |
2fc92b |
cupsArrayAdd(search->sorted, node);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Free the search context...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cgiFreeSearch(sc);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Return the results...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (search);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_add_word()' - Add a word to a node.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static help_word_t * /* O - New word */
|
|
Packit |
2fc92b |
help_add_word(help_node_t *n, /* I - Node */
|
|
Packit |
2fc92b |
const char *text) /* I - Word text */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
help_word_t *w, /* New word */
|
|
Packit |
2fc92b |
key; /* Search key */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_add_word(n=%p, text=\"%s\")", n, text));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Create the words array as needed...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!n->words)
|
|
Packit |
2fc92b |
n->words = cupsArrayNew((cups_array_func_t)help_sort_words, NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* See if the word is already added...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
key.text = (char *)text;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((w = (help_word_t *)cupsArrayFind(n->words, &key)) == NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Create a new word...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((w = calloc(1, sizeof(help_word_t))) == NULL)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((w->text = strdup(text)) == NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
free(w);
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayAdd(n->words, w);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Bump the counter for this word and return it...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
w->count ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (w);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_delete_node()' - Free all memory used by a node.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
help_delete_node(help_node_t *n) /* I - Node */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
help_word_t *w; /* Current word */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_delete_node(n=%p)", n));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!n)
|
|
Packit |
2fc92b |
return;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (n->filename)
|
|
Packit |
2fc92b |
free(n->filename);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (n->anchor)
|
|
Packit |
2fc92b |
free(n->anchor);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (n->section)
|
|
Packit |
2fc92b |
free(n->section);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (n->text)
|
|
Packit |
2fc92b |
free(n->text);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (w = (help_word_t *)cupsArrayFirst(n->words);
|
|
Packit |
2fc92b |
w;
|
|
Packit |
2fc92b |
w = (help_word_t *)cupsArrayNext(n->words))
|
|
Packit |
2fc92b |
help_delete_word(w);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayDelete(n->words);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
free(n);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_delete_word()' - Free all memory used by a word.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
help_delete_word(help_word_t *w) /* I - Word */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_delete_word(w=%p)", w));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!w)
|
|
Packit |
2fc92b |
return;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (w->text)
|
|
Packit |
2fc92b |
free(w->text);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
free(w);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_load_directory()' - Load a directory of files into an index.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static int /* O - 0 = success, -1 = error, 1 = updated */
|
|
Packit |
2fc92b |
help_load_directory(
|
|
Packit |
2fc92b |
help_index_t *hi, /* I - Index */
|
|
Packit |
2fc92b |
const char *directory, /* I - Directory */
|
|
Packit |
2fc92b |
const char *relative) /* I - Relative path */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cups_dir_t *dir; /* Directory file */
|
|
Packit |
2fc92b |
cups_dentry_t *dent; /* Directory entry */
|
|
Packit |
2fc92b |
char *ext, /* Pointer to extension */
|
|
Packit |
2fc92b |
filename[1024], /* Full filename */
|
|
Packit |
2fc92b |
relname[1024]; /* Relative filename */
|
|
Packit |
2fc92b |
int update; /* Updated? */
|
|
Packit |
2fc92b |
help_node_t *node; /* Current node */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_load_directory(hi=%p, directory=\"%s\", relative=\"%s\")",
|
|
Packit |
2fc92b |
hi, directory, relative));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Open the directory and scan it...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((dir = cupsDirOpen(directory)) == NULL)
|
|
Packit |
2fc92b |
return (0);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
update = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while ((dent = cupsDirRead(dir)) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Skip "." files...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (dent->filename[0] == '.')
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Get absolute and relative filenames...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
snprintf(filename, sizeof(filename), "%s/%s", directory, dent->filename);
|
|
Packit |
2fc92b |
if (relative)
|
|
Packit |
2fc92b |
snprintf(relname, sizeof(relname), "%s/%s", relative, dent->filename);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
strlcpy(relname, dent->filename, sizeof(relname));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Check if we have a HTML file...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((ext = strstr(dent->filename, ".html")) != NULL &&
|
|
Packit |
2fc92b |
(!ext[5] || !strcmp(ext + 5, ".gz")))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* HTML file, see if we have already indexed the file...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((node = helpFindNode(hi, relname, NULL)) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* File already indexed - check dates to confirm that the
|
|
Packit |
2fc92b |
* index is up-to-date...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node->mtime == dent->fileinfo.st_mtime)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Same modification time, so mark all of the nodes
|
|
Packit |
2fc92b |
* for this file as up-to-date...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
|
|
Packit |
2fc92b |
if (!strcmp(node->filename, relname))
|
|
Packit |
2fc92b |
node->score = 0;
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
update = 1;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
help_load_file(hi, filename, relname, dent->fileinfo.st_mtime);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (S_ISDIR(dent->fileinfo.st_mode))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Process sub-directory...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (help_load_directory(hi, filename, relname) == 1)
|
|
Packit |
2fc92b |
update = 1;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsDirClose(dir);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (update);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_load_file()' - Load a HTML files into an index.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static int /* O - 0 = success, -1 = error */
|
|
Packit |
2fc92b |
help_load_file(
|
|
Packit |
2fc92b |
help_index_t *hi, /* I - Index */
|
|
Packit |
2fc92b |
const char *filename, /* I - Filename */
|
|
Packit |
2fc92b |
const char *relative, /* I - Relative path */
|
|
Packit |
2fc92b |
time_t mtime) /* I - Modification time */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cups_file_t *fp; /* HTML file */
|
|
Packit |
2fc92b |
help_node_t *node; /* Current node */
|
|
Packit |
2fc92b |
char line[1024], /* Line from file */
|
|
Packit |
2fc92b |
temp[1024], /* Temporary word */
|
|
Packit |
2fc92b |
section[1024], /* Section */
|
|
Packit |
2fc92b |
*ptr, /* Pointer into line */
|
|
Packit |
2fc92b |
*anchor, /* Anchor name */
|
|
Packit |
2fc92b |
*text; /* Text for anchor */
|
|
Packit |
2fc92b |
off_t offset; /* File offset */
|
|
Packit |
2fc92b |
char quote; /* Quote character */
|
|
Packit |
2fc92b |
help_word_t *word; /* Current word */
|
|
Packit |
2fc92b |
int wordlen; /* Length of word */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_load_file(hi=%p, filename=\"%s\", relative=\"%s\", "
|
|
Packit |
2fc92b |
"mtime=%ld)", hi, filename, relative, (long)mtime));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((fp = cupsFileOpen(filename, "r")) == NULL)
|
|
Packit |
2fc92b |
return (-1);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
node = NULL;
|
|
Packit |
2fc92b |
offset = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
strlcpy(section, "Other", sizeof(section));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (cupsFileGets(fp, line, sizeof(line)))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Look for "<TITLE>", "
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!_cups_strncasecmp(line, "
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Got section line, copy it!
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (ptr = line + 13; isspace(*ptr & 255); ptr ++);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
strlcpy(section, ptr, sizeof(section));
|
|
Packit |
2fc92b |
if ((ptr = strstr(section, "-->")) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Strip comment stuff from end of line...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (*ptr-- = '\0'; ptr > line && isspace(*ptr & 255); *ptr-- = '\0');
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (isspace(*ptr & 255))
|
|
Packit |
2fc92b |
*ptr = '\0';
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (ptr = line; (ptr = strchr(ptr, '<')) != NULL;)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!_cups_strncasecmp(ptr, "TITLE>", 6))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Found the title...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
anchor = NULL;
|
|
Packit |
2fc92b |
ptr += 6;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (!_cups_strncasecmp(ptr, "A NAME=", 7))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Found an anchor...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
ptr += 7;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr == '\"' || *ptr == '\'')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Get quoted anchor...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
quote = *ptr;
|
|
Packit |
2fc92b |
anchor = ptr + 1;
|
|
Packit |
2fc92b |
if ((ptr = strchr(anchor, quote)) != NULL)
|
|
Packit |
2fc92b |
*ptr++ = '\0';
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Get unquoted anchor...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
anchor = ptr + 1;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (ptr = anchor; *ptr && *ptr != '>' && !isspace(*ptr & 255); ptr ++);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr)
|
|
Packit |
2fc92b |
*ptr++ = '\0';
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Got the anchor, now lets find the end...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (*ptr && *ptr != '>')
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr != '>')
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Now collect text for the link...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
text = ptr;
|
|
Packit |
2fc92b |
while ((ptr = strchr(text, '<')) == NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
ptr = text + strlen(text);
|
|
Packit |
2fc92b |
if (ptr >= (line + sizeof(line) - 2))
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*ptr++ = ' ';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!cupsFileGets(fp, ptr, sizeof(line) - (size_t)(ptr - line) - 1))
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*ptr = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node)
|
|
Packit |
2fc92b |
node->length = (size_t)(offset - node->offset);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!*text)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
node = NULL;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((node = helpFindNode(hi, relative, anchor)) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Node already in the index, so replace the text and other
|
|
Packit |
2fc92b |
* data...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayRemove(hi->nodes, node);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node->section)
|
|
Packit |
2fc92b |
free(node->section);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node->text)
|
|
Packit |
2fc92b |
free(node->text);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node->words)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
for (word = (help_word_t *)cupsArrayFirst(node->words);
|
|
Packit |
2fc92b |
word;
|
|
Packit |
2fc92b |
word = (help_word_t *)cupsArrayNext(node->words))
|
|
Packit |
2fc92b |
help_delete_word(word);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayDelete(node->words);
|
|
Packit |
2fc92b |
node->words = NULL;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
node->section = section[0] ? strdup(section) : NULL;
|
|
Packit |
2fc92b |
node->text = strdup(text);
|
|
Packit |
2fc92b |
node->mtime = mtime;
|
|
Packit |
2fc92b |
node->offset = offset;
|
|
Packit |
2fc92b |
node->score = 0;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* New node...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
node = help_new_node(relative, anchor, section, text, mtime, offset, 0);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Go through the text value and replace tabs and newlines with
|
|
Packit |
2fc92b |
* whitespace and eliminate extra whitespace...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (ptr = node->text, text = node->text; *ptr;)
|
|
Packit |
2fc92b |
if (isspace(*ptr & 255))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
while (isspace(*ptr & 255))
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*text++ = ' ';
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (text != ptr)
|
|
Packit |
2fc92b |
*text++ = *ptr++;
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
text ++;
|
|
Packit |
2fc92b |
ptr ++;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*text = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* (Re)add the node to the array...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayAdd(hi->nodes, node);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!anchor)
|
|
Packit |
2fc92b |
node = NULL;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Scan this line for words...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (ptr = line; *ptr; ptr ++)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Skip HTML stuff...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*ptr == '<')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (!strncmp(ptr, "
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Skip HTML comment...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((text = strstr(ptr + 4, "-->")) == NULL)
|
|
Packit |
2fc92b |
ptr += strlen(ptr) - 1;
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
ptr = text + 2;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Skip HTML element...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (ptr ++; *ptr && *ptr != '>'; ptr ++)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (*ptr == '\"' || *ptr == '\'')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
for (quote = *ptr++; *ptr && *ptr != quote; ptr ++);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!*ptr)
|
|
Packit |
2fc92b |
ptr --;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!*ptr)
|
|
Packit |
2fc92b |
ptr --;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (*ptr == '&')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Skip HTML entity...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (ptr ++; *ptr && *ptr != ';'; ptr ++);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!*ptr)
|
|
Packit |
2fc92b |
ptr --;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (!isalnum(*ptr & 255))
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Found the start of a word, search until we find the end...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (text = ptr, ptr ++; *ptr && isalnum(*ptr & 255); ptr ++);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
wordlen = (int)(ptr - text);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
memcpy(temp, text, (size_t)wordlen);
|
|
Packit |
2fc92b |
temp[wordlen] = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
ptr --;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (wordlen > 1 && !bsearch(temp, help_common_words,
|
|
Packit |
2fc92b |
(sizeof(help_common_words) /
|
|
Packit |
2fc92b |
sizeof(help_common_words[0])),
|
|
Packit |
2fc92b |
sizeof(help_common_words[0]),
|
|
Packit |
2fc92b |
(int (*)(const void *, const void *))
|
|
Packit |
2fc92b |
_cups_strcasecmp))
|
|
Packit |
2fc92b |
help_add_word(node, temp);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Get the offset of the next line...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
offset = cupsFileTell(fp);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsFileClose(fp);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (node)
|
|
Packit |
2fc92b |
node->length = (size_t)(offset - node->offset);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (0);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_new_node()' - Create a new node and add it to an index.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static help_node_t * /* O - Node pointer or NULL on error */
|
|
Packit |
2fc92b |
help_new_node(const char *filename, /* I - Filename */
|
|
Packit |
2fc92b |
const char *anchor, /* I - Anchor */
|
|
Packit |
2fc92b |
const char *section, /* I - Section */
|
|
Packit |
2fc92b |
const char *text, /* I - Text */
|
|
Packit |
2fc92b |
time_t mtime, /* I - Modification time */
|
|
Packit |
2fc92b |
off_t offset, /* I - Offset in file */
|
|
Packit |
2fc92b |
size_t length) /* I - Length in bytes */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
help_node_t *n; /* Node */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_new_node(filename=\"%s\", anchor=\"%s\", text=\"%s\", "
|
|
Packit |
2fc92b |
"mtime=%ld, offset=%ld, length=%ld)", filename, anchor, text,
|
|
Packit |
2fc92b |
(long)mtime, (long)offset, (long)length));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
n = (help_node_t *)calloc(1, sizeof(help_node_t));
|
|
Packit |
2fc92b |
if (!n)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
n->filename = strdup(filename);
|
|
Packit |
2fc92b |
n->anchor = anchor ? strdup(anchor) : NULL;
|
|
Packit |
2fc92b |
n->section = *section ? strdup(section) : NULL;
|
|
Packit |
2fc92b |
n->text = strdup(text);
|
|
Packit |
2fc92b |
n->mtime = mtime;
|
|
Packit |
2fc92b |
n->offset = offset;
|
|
Packit |
2fc92b |
n->length = length;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (n);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_sort_nodes_by_name()' - Sort nodes by section, filename, and anchor.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static int /* O - Difference */
|
|
Packit |
2fc92b |
help_sort_by_name(help_node_t *n1, /* I - First node */
|
|
Packit |
2fc92b |
help_node_t *n2) /* I - Second node */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
int diff; /* Difference */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_sort_by_name(n1=%p(%s#%s), n2=%p(%s#%s)",
|
|
Packit |
2fc92b |
n1, n1->filename, n1->anchor,
|
|
Packit |
2fc92b |
n2, n2->filename, n2->anchor));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((diff = strcmp(n1->filename, n2->filename)) != 0)
|
|
Packit |
2fc92b |
return (diff);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!n1->anchor && !n2->anchor)
|
|
Packit |
2fc92b |
return (0);
|
|
Packit |
2fc92b |
else if (!n1->anchor)
|
|
Packit |
2fc92b |
return (-1);
|
|
Packit |
2fc92b |
else if (!n2->anchor)
|
|
Packit |
2fc92b |
return (1);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
return (strcmp(n1->anchor, n2->anchor));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_sort_nodes_by_score()' - Sort nodes by score and text.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static int /* O - Difference */
|
|
Packit |
2fc92b |
help_sort_by_score(help_node_t *n1, /* I - First node */
|
|
Packit |
2fc92b |
help_node_t *n2) /* I - Second node */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
int diff; /* Difference */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_sort_by_score(n1=%p(%d \"%s\" \"%s\"), "
|
|
Packit |
2fc92b |
"n2=%p(%d \"%s\" \"%s\")",
|
|
Packit |
2fc92b |
n1, n1->score, n1->section, n1->text,
|
|
Packit |
2fc92b |
n2, n2->score, n2->section, n2->text));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (n1->score != n2->score)
|
|
Packit |
2fc92b |
return (n2->score - n1->score);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (n1->section && !n2->section)
|
|
Packit |
2fc92b |
return (1);
|
|
Packit |
2fc92b |
else if (!n1->section && n2->section)
|
|
Packit |
2fc92b |
return (-1);
|
|
Packit |
2fc92b |
else if (n1->section && n2->section &&
|
|
Packit |
2fc92b |
(diff = strcmp(n1->section, n2->section)) != 0)
|
|
Packit |
2fc92b |
return (diff);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (_cups_strcasecmp(n1->text, n2->text));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'help_sort_words()' - Sort words alphabetically.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static int /* O - Difference */
|
|
Packit |
2fc92b |
help_sort_words(help_word_t *w1, /* I - Second word */
|
|
Packit |
2fc92b |
help_word_t *w2) /* I - Second word */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
DEBUG_printf(("2help_sort_words(w1=%p(\"%s\"), w2=%p(\"%s\"))",
|
|
Packit |
2fc92b |
w1, w1->text, w2, w2->text));
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (_cups_strcasecmp(w1->text, w2->text));
|
|
Packit |
2fc92b |
}
|