home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 4.ddi / TOOLS.4 / TCTSRC1.EXE / HLLOOKUP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-31  |  9.6 KB  |  339 lines

  1. /**
  2. *
  3. * Name        HLLOOKUP -- Look up and read the help record for a given
  4. *                ID string from the specified help database.
  5. *
  6. * Synopsis    result = hllookup(pdatabase_path, pid_string, offset,
  7. *                  phelp_win, pptext, ptext_length,
  8. *                  option);
  9. *
  10. *        int result         Error code indicating success or
  11. *                     failure of the operation.
  12. *        const char         The name of the help database to
  13. *            *pdatabase_path  search.
  14. *        const char         The help ID string to search for.
  15. *            *pid_string
  16. *        unsigned long offset If pid_string is NIL or points to
  17. *                     the NUL string ('\0'), this is the
  18. *                     absolute offset of the help record
  19. *                     in the help database.
  20. *        HL_WINDOW *phelp_win Pointer to a help window structure
  21. *                     to be filled in from the database.
  22. *        char **pptext         Pointer to the returned pointer to
  23. *                     the buffer which is allocated for
  24. *                     the help window's text (read from
  25. *                     the database).
  26. *        int *ptext_length    Pointer to the returned length of
  27. *                     the text contained in **pptext.
  28. *        int option         The format that the window's text
  29. *                     is to be returned in.  One of the
  30. *                     following values:
  31. *                     HL_CHARS_ONLY: Return the text as
  32. *                       characters only.
  33. *                     HL_CHAR_ATTR: Return the text as
  34. *                       character attribute pairs.
  35. *                     HL_COMPRESSED: Return text in
  36. *                       comressed format.
  37. *
  38. * Description    This function will construct the specified database's
  39. *        index in memory (if it is not already built), search for
  40. *        the specified string, and read in the data associated
  41. *        with the given ID string, if it can be found.  If
  42. *        pid_string is NIL or points to the NUL string ('\0'),
  43. *        then offset contains the absolute file offset of the
  44. *        help record within the specified database. The
  45. *        characteristics of the help record's window will be
  46. *        copied into *phelp_win, which must be preallocated. The
  47. *        memory for the window's text will be allocated (a
  48. *        pointer to which is returned in *pptext), and the size
  49. *        of the allocated space is returned in *ptext_length.
  50. *
  51. *        If b_phelp_index already points to a database index,
  52. *        the entire index is freed before the new index is built.
  53. *
  54. *        An error occurs if the given pathname does not exist, if
  55. *        there are not enough file handles to open the database,
  56. *        if the path does not point to a valid help database, or
  57. *        if there is not enough memory for the index or the help
  58. *        text.
  59. *
  60. * Returns    result        Error code. Possible values are:
  61. *                HL_NO_ERROR    Operation successful.
  62. *                HL_NO_PATH    Pathname does not exist.
  63. *                HL_NO_HANDLES    Not enough file handles.
  64. *                HL_BAD_DATABASE Specified file is not
  65. *                        a valid help file.
  66. *                HL_NO_MEMORY    Insufficient memory.
  67. *                HL_NOT_FOUND    Id is not in database.
  68. *                HL_VER_MISMATCH Database version is
  69. *                        incorrect.
  70. *                HL_SYSTEM    Internal error.
  71. *
  72. *        b_phelp_index    Pointer to help index (possibly newly
  73. *                constructed), or NIL if unable to
  74. *                construct index.
  75. *
  76. *        b_help_path    Pathname of database whose index is
  77. *                currently constructed.
  78. *
  79. *
  80. * Version    6.00 (C)Copyright Blaise Computing Inc.  1989
  81. *
  82. **/
  83. #include <stdlib.h>
  84. #include <fcntl.h>
  85. #include <sys\types.h>
  86. #include <sys\stat.h>
  87. #include <io.h>
  88. #include <errno.h>
  89. #include <bhelp.h>
  90. #include <bstrings.h>
  91. #include <bfiles.h>
  92.  
  93.  
  94. #define close_error(error) {close(help_fd); hlerror(error);}
  95.  
  96.  
  97. static HL_INDEX_NODE *search_index(HL_INDEX_NODE *, char *);
  98.  
  99.  
  100. int hllookup(pdatabase_path, pid_string, offset, phelp_win, pptext,
  101.          ptext_length, option)
  102. const char     *pdatabase_path;
  103. const char     *pid_string;
  104. unsigned long    offset;
  105. HL_WINDOW      *phelp_win;
  106. char          **pptext;
  107. int           *ptext_length;
  108. int        option;
  109. {
  110.     int         error;
  111.     HL_INDEX_NODE  *pindex_node;
  112.     HL_RECORD_DATA  record_data;
  113.     extern int        errno;
  114.     int         help_fd;
  115.     int         buffer_index;
  116.     const char       *ppath;
  117.     char       *puncompressed_text;
  118.     char       *pchars_only_text;
  119.     int         uncompressed_size;
  120.     int         chars_only_size;
  121.     char        uppercase_id[HL_ID_SIZE];
  122.     char        normalized_path[MAX_FLEN];
  123.     int         name_index;
  124.     unsigned long   search_offset;
  125.     int         id_specified = 0;
  126.  
  127.     errno = 0;
  128.  
  129.     if (flnorm(pdatabase_path, normalized_path, &name_index) != 0)
  130.     ppath = pdatabase_path;
  131.     else
  132.     ppath = normalized_path;
  133.  
  134.         /* First check to see if we need to build the index.*/
  135.     if (strcmp(ppath, b_help_path) != 0)
  136.     {
  137.     hlclose();
  138.     error = hlopen(ppath);
  139.     if (error != HL_NO_ERROR)
  140.         return(error);
  141.     }
  142.  
  143.         /* Now search the index if necessary.            */
  144.     if ((pid_string != NIL) && (*pid_string != '\0'))
  145.     {
  146.     id_specified = 1;
  147.  
  148.     strncpy(uppercase_id, pid_string, HL_ID_SIZE - 1);
  149.     uppercase_id[HL_ID_SIZE - 1] = '\0';
  150.     stpcvt(uppercase_id, RLWHITE | RTWHITE | TOUP);
  151.  
  152.     pindex_node = search_index(b_phelp_index, uppercase_id);
  153.     if (pindex_node == NIL)
  154.         hlerror(HL_NOT_FOUND);
  155.  
  156.     search_offset = pindex_node->index_data.help_record;
  157.     }
  158.     else
  159.     search_offset = offset;
  160.  
  161.         /* The index has been found, so open the file and   */
  162.         /* read the data.                    */
  163.     help_fd = open(ppath, O_RDONLY | O_BINARY);
  164.     if (help_fd == -1)
  165.     switch (errno)
  166.     {
  167.     case EACCES:
  168.         hlerror(HL_BAD_DATABASE);
  169.  
  170.     case EMFILE:
  171.         hlerror(HL_NO_HANDLES);
  172.  
  173.     case ENOENT:
  174.         hlerror(HL_NO_PATH);
  175.  
  176.     default:
  177.         hlerror(HL_SYSTEM);
  178.     }
  179.  
  180.     if (lseek(help_fd, search_offset, SEEK_SET) != search_offset)
  181.     close_error(HL_BAD_DATABASE);
  182.  
  183.         /* First, read the record header and window data.   */
  184.     if ((read(help_fd, &record_data, sizeof(HL_RECORD_DATA)) !=
  185.           sizeof(HL_RECORD_DATA))                 ||
  186.     (record_data.record_sign.type    != HL_WINDOW_RECORD) ||
  187.     (record_data.record_sign.length != sizeof(HL_RECORD_DATA)))
  188.     {
  189.     close_error(HL_BAD_DATABASE);
  190.     }
  191.  
  192.     hlpas2c(record_data.id_string, record_data.id_string,
  193.         sizeof(record_data.id_string));
  194.  
  195.     if (id_specified &&
  196.     (strcmp(record_data.id_string, uppercase_id) != 0))
  197.     {
  198.     close_error(HL_BAD_DATABASE);
  199.     }
  200.  
  201.         /* Convert the help record from disk format to        */
  202.         /* memory format.                    */
  203.     *phelp_win = *((HL_WINDOW *) &record_data.view_top);
  204.     phelp_win->view_top--;
  205.     phelp_win->view_left--;
  206.     phelp_win->view_bottom--;
  207.     phelp_win->view_right--;
  208.     phelp_win->origin_row--;
  209.     phelp_win->origin_col--;
  210.  
  211.             /* Now read in the help window's text.          */
  212.     *pptext = malloc(record_data.image_length);
  213.     if (*pptext == NIL)
  214.     close_error(HL_NO_MEMORY);
  215.  
  216.     if (read(help_fd, *pptext, record_data.image_length) !=
  217.     record_data.image_length)
  218.     {
  219.     close_error(HL_BAD_DATABASE);
  220.     }
  221.  
  222.         /* Now check to see if the window has a title.        */
  223.     if (record_data.title_length != 0)
  224.     {
  225.     phelp_win->pwindow_title = malloc(record_data.title_length + 1);
  226.     if (phelp_win->pwindow_title == NIL)
  227.         close_error(HL_NO_MEMORY);
  228.  
  229.     if (read(help_fd, phelp_win->pwindow_title,
  230.          record_data.title_length) != record_data.title_length)
  231.         close_error(HL_BAD_DATABASE);
  232.  
  233.     phelp_win->pwindow_title[record_data.title_length] = '\0';
  234.     }
  235.     else
  236.     phelp_win->pwindow_title = NIL;
  237.  
  238.         /* Now check to see how the text should be returned.*/
  239.     switch(option)
  240.     {
  241.     case HL_COMPRESSED:
  242.     *ptext_length = record_data.image_length;
  243.     break;
  244.  
  245.     case HL_CHAR_ATTR:
  246.     case HL_CHARS_ONLY:
  247.     uncompressed_size = *((int *) ((*pptext) + 2));
  248.     puncompressed_text = malloc(uncompressed_size);
  249.     if (puncompressed_text == NIL)
  250.         close_error(HL_NO_MEMORY);
  251.     if (utunsqz(*pptext, puncompressed_text,
  252.             record_data.image_length, uncompressed_size) !=
  253.         uncompressed_size)
  254.     {
  255.         free(puncompressed_text);
  256.         close_error(HL_BAD_DATABASE);
  257.     }
  258.  
  259.     if (option == HL_CHAR_ATTR)
  260.     {
  261.         free(*pptext);
  262.         *pptext = puncompressed_text;
  263.         *ptext_length = uncompressed_size;
  264.     }
  265.     else
  266.     {
  267.         chars_only_size = uncompressed_size / 2;
  268.         pchars_only_text = malloc(chars_only_size);
  269.         if (pchars_only_text == NIL)
  270.         {
  271.         free(puncompressed_text);
  272.         close_error(HL_NO_MEMORY);
  273.         }
  274.         for (buffer_index = 0; buffer_index < chars_only_size;
  275.          buffer_index++)
  276.         {
  277.         pchars_only_text[buffer_index] =
  278.             puncompressed_text[buffer_index * 2];
  279.         }
  280.         free(*pptext);
  281.         *pptext = pchars_only_text;
  282.         free(puncompressed_text);
  283.         *ptext_length = chars_only_size;
  284.     }
  285.     break;
  286.  
  287.     default:
  288.     return(HL_SYSTEM);
  289.     }
  290.  
  291.     return(HL_NO_ERROR);
  292. }
  293.  
  294.  
  295. /**
  296. *
  297. * Name        SEARCH_INDEX -- Recursively search a help index tree for
  298. *                a specified ID string.
  299. *
  300. * Synopsis    pindex_node = search_index(pindex_root, pid_string);
  301. *
  302. *        HL_INDEX_NODE *pindex_node  Pointer to found index node,
  303. *                        or NIL if ID is not in the
  304. *                        index.
  305. *        HL_INDEX_NODE *pindex_root  Pointer to root of subtree
  306. *                        to search.
  307. *        char *pid_string        The help ID string to search
  308. *                        for.
  309. *
  310. * Description    This function will recursively search the specified
  311. *        help index subtree for the given id string.  The return
  312. *        value is a pointer to the help index node for the ID,
  313. *        or NIL if the ID cannot be found in the subtree.
  314. *
  315. * Returns    pindex_node    Found index node or NIL if ID does not
  316. *                exist.
  317. *
  318. **/
  319.  
  320. HL_INDEX_NODE *search_index(pindex_root, pid_string)
  321. HL_INDEX_NODE *pindex_root;
  322. char *pid_string;
  323. {
  324.     int result;
  325.  
  326.     if (pindex_root == NIL)
  327.     return(NIL);
  328.  
  329.     result = strcmp(pid_string, pindex_root->index_data.id_string);
  330.  
  331.     if (result == 0)
  332.     return(pindex_root);
  333.  
  334.     if (result < 0)
  335.     return(search_index(pindex_root->pleft, pid_string));
  336.  
  337.     return(search_index(pindex_root->pright, pid_string));
  338. }
  339.