]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cgi-bin/help-index.c
Merge changes from CUPS 1.7svn-r10629.
[thirdparty/cups.git] / cgi-bin / help-index.c
index 8f148c471e4f54e473ea6e9078da8bd025085c28..08586a0b16d013298beaa9efa85f4ce034f01283 100644 (file)
@@ -1,25 +1,16 @@
 /*
- * "$Id$"
+ * "$Id: help-index.c 7717 2008-07-04 02:35:33Z mike $"
  *
- *   On-line help index routines for the Common UNIX Printing System (CUPS).
+ *   Online help index routines for CUPS.
  *
- *   Copyright 1997-2006 by Easy Software Products.
+ *   Copyright 2007-2012 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_delete_node()         - Free all memory used by a node.
+ *   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 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_delete_word(help_word_t *w);
 static int             help_load_directory(help_index_t *hi,
                                            const char *directory,
                                            const char *relative);
@@ -60,9 +161,11 @@ static int          help_load_file(help_index_t *hi,
 static help_node_t     *help_new_node(const char *filename, const char *anchor,
                                       const char *section, const char *text,
                                       time_t mtime, off_t offset,
-                                      size_t length);
+                                      size_t length)
+                                      __attribute__((nonnull(1,3,4)));
 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);
 
 
 /*
@@ -75,7 +178,7 @@ helpDeleteIndex(help_index_t *hi)    /* I - Help index */
   help_node_t  *node;                  /* Current node */
 
 
-  DEBUG_printf(("helpDeleteIndex(hi=%p)\n", hi));
+  DEBUG_printf(("helpDeleteIndex(hi=%p)", hi));
 
   if (!hi)
     return;
@@ -84,9 +187,6 @@ helpDeleteIndex(help_index_t *hi)    /* I - Help index */
        node;
        node = (help_node_t *)cupsArrayNext(hi->nodes))
   {
-    cupsArrayRemove(hi->nodes, node);
-    cupsArrayRemove(hi->sorted, node);
-
     if (!hi->search)
       help_delete_node(node);
   }
@@ -110,8 +210,8 @@ helpFindNode(help_index_t *hi,              /* I - Index */
   help_node_t  key;                    /* Search key */
 
 
-  DEBUG_printf(("helpFindNode(hi=%p, filename=\"%s\", anchor=\"%s\")\n",
-                hi, filename ? filename : "(nil)", anchor ? anchor : "(nil)"));
+  DEBUG_printf(("helpFindNode(hi=%p, filename=\"%s\", anchor=\"%s\")",
+                hi, filename, anchor));
 
  /*
   * Range check input...
@@ -157,9 +257,10 @@ helpLoadIndex(const char *hifile,  /* I - Index filename */
   size_t       length;                 /* Length in bytes */
   int          update;                 /* Update? */
   help_node_t  *node;                  /* Current node */
+  help_word_t  *word;                  /* Current word */
 
 
-  DEBUG_printf(("helpLoadIndex(hifile=\"%s\", directory=\"%s\")\n",
+  DEBUG_printf(("helpLoadIndex(hifile=\"%s\", directory=\"%s\")",
                 hifile, directory));
 
  /*
@@ -192,12 +293,14 @@ helpLoadIndex(const char *hifile, /* I - Index filename */
 
     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)))
       {
        /*
@@ -205,77 +308,97 @@ helpLoadIndex(const char *hifile, /* I - Index filename */
        *
        *     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));
 
-        *ptr++ = '\0';
+           while (isspace(*ptr & 255))
+              ptr ++;
+          }
 
-       if ((node = help_new_node(filename, anchor, section, text,
-                                 mtime, offset, length)) == NULL)
-          break;
+          if (*ptr != '\"')
+           break;
+
+          ptr ++;
+         text = ptr;
+
+          while (*ptr && *ptr != '\"')
+           ptr ++;
+
+          if (*ptr != '\"')
+           break;
+
+          *ptr++ = '\0';
+
+         if ((node = help_new_node(filename, anchor, section, text,
+                                   mtime, offset, length)) == NULL)
+            break;
 
-       node->score = -1;
+         node->score = -1;
 
-       cupsArrayAdd(hi->nodes, node);
+         cupsArrayAdd(hi->nodes, node);
+        }
       }
     }
 
@@ -339,9 +462,10 @@ helpSaveIndex(help_index_t *hi,            /* I - Index */
 {
   cups_file_t  *fp;                    /* Index file */
   help_node_t  *node;                  /* Current node */
+  help_word_t  *word;                  /* Current word */
 
 
-  DEBUG_printf(("helpSaveIndex(hi=%p, hifile=\"%s\")\n", hi, hifile));
+  DEBUG_printf(("helpSaveIndex(hi=%p, hifile=\"%s\")", hi, hifile));
 
  /*
   * Try creating a new index file...
@@ -356,7 +480,7 @@ helpSaveIndex(help_index_t *hi,             /* I - Index */
 
   cupsFileLock(fp, 1);
 
-  cupsFilePuts(fp, "HELPV1\n");
+  cupsFilePuts(fp, "HELPV2\n");
 
   for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
        node;
@@ -377,11 +501,21 @@ helpSaveIndex(help_index_t *hi,           /* I - Index */
     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);
@@ -407,13 +541,13 @@ helpSearchIndex(help_index_t *hi, /* I - Index */
 {
   help_index_t *search;                /* Search index */
   help_node_t  *node;                  /* Current node */
+  help_word_t  *word;                  /* Current word */
   void         *sc;                    /* Search context */
   int          matches;                /* Number of matches */
 
 
-  DEBUG_printf(("helpSearchIndex(hi=%p, query=\"%s\", filename=\"%s\")\n",
-                hi, query ? query : "(nil)",
-               filename ? filename : "(nil)"));
+  DEBUG_printf(("helpSearchIndex(hi=%p, query=\"%s\", filename=\"%s\")",
+                hi, query, filename));
 
  /*
   * Range check...
@@ -465,7 +599,7 @@ helpSearchIndex(help_index_t *hi,   /* I - Index */
 
   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);
@@ -487,16 +621,27 @@ helpSearchIndex(help_index_t *hi, /* I - Index */
       continue;
     else if (filename && strcmp(node->filename, filename))
       continue;
-    else if ((matches = cgiDoSearch(sc, node->text)) > 0)
+    else
     {
-     /*
-      * Found a match, add the node to the search index...
-      */
+      matches = cgiDoSearch(sc, node->text);
+
+      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;
+
+      if (matches > 0)
+      {
+       /*
+       * Found a match, add the node to the search index...
+       */
 
-      node->score = matches;
+       node->score = matches;
 
-      cupsArrayAdd(search->nodes, node);      
-      cupsArrayAdd(search->sorted, node);      
+       cupsArrayAdd(search->nodes, node);
+       cupsArrayAdd(search->sorted, node);
+      }
     }
 
  /*
@@ -513,6 +658,61 @@ helpSearchIndex(help_index_t *hi,  /* I - Index */
 }
 
 
+/*
+ * 'help_add_word()' - Add a word to a node.
+ */
+
+static help_word_t *                   /* O - New word */
+help_add_word(help_node_t *n,          /* I - Node */
+              const char  *text)       /* I - Word text */
+{
+  help_word_t  *w,                     /* New word */
+               key;                    /* Search key */
+
+
+  DEBUG_printf(("2help_add_word(n=%p, text=\"%s\")", n, text));
+
+ /*
+  * Create the words array as needed...
+  */
+
+  if (!n->words)
+    n->words = cupsArrayNew((cups_array_func_t)help_sort_words, NULL);
+
+ /*
+  * See if the word is already added...
+  */
+
+  key.text = (char *)text;
+
+  if ((w = (help_word_t *)cupsArrayFind(n->words, &key)) == NULL)
+  {
+   /*
+    * Create a new word...
+    */
+
+    if ((w = calloc(1, sizeof(help_word_t))) == NULL)
+      return (NULL);
+
+    if ((w->text = strdup(text)) == NULL)
+    {
+      free(w);
+      return (NULL);
+    }
+
+    cupsArrayAdd(n->words, w);
+  }
+
+ /*
+  * Bump the counter for this word and return it...
+  */
+
+  w->count ++;
+
+  return (w);
+}
+
+
 /*
  * 'help_delete_node()' - Free all memory used by a node.
  */
@@ -520,7 +720,10 @@ helpSearchIndex(help_index_t *hi,  /* I - Index */
 static void
 help_delete_node(help_node_t *n)       /* I - Node */
 {
-  DEBUG_printf(("help_delete_node(n=%p)\n", n));
+  help_word_t  *w;                     /* Current word */
+
+
+  DEBUG_printf(("2help_delete_node(n=%p)", n));
 
   if (!n)
     return;
@@ -537,10 +740,36 @@ help_delete_node(help_node_t *n)  /* I - Node */
   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_delete_word()' - Free all memory used by a word.
+ */
+
+static void
+help_delete_word(help_word_t *w)       /* I - Word */
+{
+  DEBUG_printf(("2help_delete_word(w=%p)", w));
+
+  if (!w)
+    return;
+
+  if (w->text)
+    free(w->text);
+
+  free(w);
+}
+
+
 /*
  * 'help_load_directory()' - Load a directory of files into an index.
  */
@@ -560,8 +789,8 @@ help_load_directory(
   help_node_t  *node;                  /* Current node */
 
 
-  DEBUG_printf(("help_load_directory(hi=%p, directory=\"%s\", relative=\"%s\")\n",
-                hi, directory ? directory : "(nil)", relative ? relative : "(nil)"));
+  DEBUG_printf(("2help_load_directory(hi=%p, directory=\"%s\", relative=\"%s\")",
+                hi, directory, relative));
 
  /*
   * Open the directory and scan it...
@@ -661,17 +890,19 @@ help_load_file(
   cups_file_t  *fp;                    /* HTML file */
   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",
-                hi, filename ? filename : "(nil)",
-               relative ? relative : "(nil)", mtime));
+  DEBUG_printf(("2help_load_file(hi=%p, filename=\"%s\", relative=\"%s\", "
+                "mtime=%ld)", hi, filename, relative, mtime));
 
   if ((fp = cupsFileOpen(filename, "r")) == NULL)
     return (-1);
@@ -679,7 +910,7 @@ help_load_file(
   node   = NULL;
   offset = 0;
 
-  strcpy(section, "Other");
+  strlcpy(section, "Other", sizeof(section));
 
   while (cupsFileGets(fp, line, sizeof(line)))
   {
@@ -687,7 +918,7 @@ help_load_file(
     * Look for "<TITLE>", "<A NAME", or "<!-- SECTION:" prefix...
     */
 
-    if (!strncasecmp(line, "<!-- SECTION:", 13))
+    if (!_cups_strncasecmp(line, "<!-- SECTION:", 13))
     {
      /*
       * Got section line, copy it!
@@ -714,7 +945,7 @@ help_load_file(
     {
       ptr ++;
 
-      if (!strncasecmp(ptr, "TITLE>", 6))
+      if (!_cups_strncasecmp(ptr, "TITLE>", 6))
       {
        /*
         * Found the title...
@@ -723,7 +954,7 @@ help_load_file(
        anchor = NULL;
        ptr += 6;
       }
-      else if (!strncasecmp(ptr, "A NAME=", 7))
+      else if (!_cups_strncasecmp(ptr, "A NAME=", 7))
       {
        /*
         * Found an anchor...
@@ -818,6 +1049,17 @@ help_load_file(
        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;
@@ -842,7 +1084,7 @@ help_load_file(
        if (isspace(*ptr & 255))
        {
          while (isspace(*ptr & 255))
-           *ptr ++;
+           ptr ++;
 
          *text++ = ' ';
         }
@@ -861,9 +1103,99 @@ help_load_file(
       */
 
       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 *))
+                                       _cups_strcasecmp))
+          help_add_word(node, temp);
+      }
+    }
+
    /*
     * Get the offset of the next line...
     */
@@ -896,11 +1228,9 @@ help_new_node(const char   *filename,     /* I - Filename */
   help_node_t  *n;                     /* Node */
 
 
-  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)", (long)mtime, (long)offset,
-               (long)length));
+  DEBUG_printf(("2help_new_node(filename=\"%s\", anchor=\"%s\", text=\"%s\", "
+                "mtime=%ld, offset=%ld, length=%ld)", filename, anchor, text,
+                (long)mtime, (long)offset, (long)length));
 
   n = (help_node_t *)calloc(1, sizeof(help_node_t));
   if (!n)
@@ -929,9 +1259,9 @@ help_sort_by_name(help_node_t *n1, /* I - First node */
   int          diff;                   /* Difference */
 
 
-  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 : ""));
+  DEBUG_printf(("2help_sort_by_name(n1=%p(%s#%s), n2=%p(%s#%s)",
+                n1, n1->filename, n1->anchor,
+               n2, n2->filename, n2->anchor));
 
   if ((diff = strcmp(n1->filename, n2->filename)) != 0)
     return (diff);
@@ -958,13 +1288,13 @@ help_sort_by_score(help_node_t *n1,      /* I - First node */
   int          diff;                   /* Difference */
 
 
-  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));
+  DEBUG_printf(("2help_sort_by_score(n1=%p(%d \"%s\" \"%s\"), "
+                "n2=%p(%d \"%s\" \"%s\")",
+                n1, n1->score, n1->section, n1->text,
+                n2, n2->score, n2->section, n2->text));
 
   if (n1->score != n2->score)
-    return (n1->score - n2->score);
+    return (n2->score - n1->score);
 
   if (n1->section && !n2->section)
     return (1);
@@ -974,10 +1304,25 @@ help_sort_by_score(help_node_t *n1,      /* I - First node */
            (diff = strcmp(n1->section, n2->section)) != 0)
     return (diff);
 
-  return (strcasecmp(n1->text, n2->text));
+  return (_cups_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(("2help_sort_words(w1=%p(\"%s\"), w2=%p(\"%s\"))",
+                w1, w1->text, w2, w2->text));
+
+  return (_cups_strcasecmp(w1->text, w2->text));
 }
 
 
 /*
- * End of "$Id$".
+ * End of "$Id: help-index.c 7717 2008-07-04 02:35:33Z mike $".
  */