home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / CSSRC / HELP.C < prev    next >
C/C++ Source or Header  |  1990-11-01  |  9KB  |  400 lines

  1. /*
  2.     help.c
  3.  
  4.     % help_Init etc.
  5.  
  6.     Routines for the C-scape help system.
  7.  
  8.     C-scape 3.2
  9.     Copyright (c) 1986, 1987, by Oakland Group, Inc.
  10.     ALL RIGHTS RESERVED.
  11.  
  12.     Revision History:
  13.     -----------------
  14.     12/11/87 jmd    Changed \r\n translation scheme in LookUp for UNIX compat.
  15.      3/08/88 jmd     Added STRATUS decl.
  16.      4/07/88 jmd     Fixed index[0] bug in help_Close
  17.      6/07/88 jmd     Fixed missing message bug in help_LookUp
  18.      6/23/88 jmd    removed errno.h
  19.      6/23/88 jmd    converted generic pointers to VOID*
  20.      6/24/88 jmd    converted to new xarray/iarray calls
  21.      8/16/88 jmd    added calls to omalloc, oak_Errno
  22.  
  23.      4/16/89 jmd    adjusted for jarray
  24.  
  25.     10/25/89 jdc    added trailing '\n' strip in help_LookUp
  26.     11/07/89 jdc    again
  27.      3/08/90 jmd    improved index array scheme
  28.      3/28/90 jmd    ansi-fied
  29.     11/01/90 ted    put (void) in arg list of help_Close.
  30. */
  31.  
  32. #include <stdio.h>
  33. #include <string.h>
  34.  
  35.  
  36. #include "cscape.h"
  37. #include "ostdlib.h"        /* for atoi() */
  38.  
  39. #include "cserror.h"
  40.  
  41. #include "oakalloc.h"
  42. #include "oaktag.h"
  43.  
  44. #include "helpdecl.h"
  45.  
  46. static    help_type help = NULL;
  47. static  char     buffer[HELPLINE + 1];
  48.  
  49. /* -------------------------------------------------------------------------- */
  50. /* index macros */
  51.  
  52. #define help_GetIndex(h, chap, par) \
  53.     *(((h)->index + ((chap) * (h)->par_count)) + (par))
  54.  
  55. #define help_SetIndex(h, chap, par, msg) \
  56.     *(((h)->index + ((chap) * (h)->par_count)) + (par)) = (msg)
  57.  
  58. /* -------------------------------------------------------------------------- */
  59.  
  60. int help_Init(FILE *fp, help_fptr disp, unsigned int size, VOID *data)
  61. /*
  62.     Initialize the help system using fp as the help file
  63.     and disp as the disp function.
  64.  
  65.     size is the size of the help buffer.
  66.  
  67.     data is placed in the help data pointer.
  68.  
  69.     Returns HELP_OK if successful, else
  70.     a help error message.
  71. */
  72. {
  73.     int        chap, par;
  74.     int        msg, msg_count, chap_count, par_count;
  75.     long    start, temp;
  76.  
  77.     if (fp == NULL || disp == FNULL || help != NULL) {
  78.         return(HELP_BADARG);
  79.     }
  80.  
  81.     /* make the help stucture */
  82.     if ((help = (help_type) omalloc(CSA_HELP, sizeof(struct help_struct))) == NULL) {
  83.         return(HELP_NOMEM);
  84.     }
  85.  
  86.     help->fp = fp;
  87.     help->disp = disp;
  88.     help->high_msg = 0;
  89.  
  90.     help->msg = 0;
  91.     help->chap = 0;
  92.     help->par = 0;
  93.  
  94.     help->data = data;
  95.  
  96.     help->size = size;
  97.  
  98.     /* set up the help index */
  99.     rewind(fp);
  100.  
  101.     /* skip the header */
  102.     while(1) {
  103.         if (fgets(buffer, HELPLINE, fp) == NULL) {
  104.             help = NULL;
  105.             return(HELP_BADFILE);
  106.         }
  107.  
  108.         if (buffer[0] == '%' && buffer[1] == '%') {
  109.             break;
  110.         }
  111.     }
  112.  
  113.     /* remember where we are */
  114.     start = ftell(fp);
  115.  
  116.     /* compute the size of the index */
  117.     chap_count = par_count = msg_count = 0;
  118.  
  119.     /* read the index */
  120.     while(1) {
  121.         if (fgets(buffer, HELPLINE, fp) == NULL) {
  122.             help = NULL;
  123.             return(HELP_BADFILE);
  124.         }
  125.  
  126.         if (buffer[0] == '%' && buffer[1] == '%') {
  127.             break;
  128.         }
  129.         else if (buffer[0] != '!') {    /* skip comments */
  130.             chap = par = msg = 0;
  131.             if (sscanf(buffer, "%d,%d:%d", &chap, &par, &msg) == 3) {
  132.                 chap_count = (chap_count > chap) ? chap_count : chap;
  133.                 par_count = (par_count > par) ? par_count : par;
  134.                 msg_count = (msg_count > msg) ? msg_count : msg;
  135.             }
  136.         }
  137.     }
  138.  
  139.     help->chap_count = chap_count;
  140.     help->par_count = par_count + 1;    /* add one for default (0) paragraph */
  141.  
  142.     /* allocate the message buffer */
  143.     help->text = (char *) omalloc(CSA_HELPTEXT, help->size + 10);
  144.  
  145.     /* allocate the index */
  146.     help->index = (int *) ocalloc(CSA_HELPINDEX, help->chap_count * help->par_count, sizeof(int));
  147.  
  148.      if (help->index == NULL || help->text == NULL) {
  149.         help = NULL;
  150.         return(HELP_NOMEM);
  151.     }
  152.  
  153.     /* read the index */
  154.     fseek(fp, start, SEEK_SET);
  155.  
  156.     while(1) {
  157.         if (fgets(buffer, HELPLINE, fp) == NULL) {
  158.             help = NULL;
  159.             return(HELP_BADFILE);
  160.         }
  161.  
  162.         if (buffer[0] == '%' && buffer[1] == '%') {
  163.             break;
  164.         }
  165.         else if (buffer[0] != '!') {    /* skip comments */
  166.             chap = par = msg = 0;
  167.             if (sscanf(buffer, "%d,%d:%d", &chap, &par, &msg) == 3) {
  168.  
  169.                 if (chap > 0 && chap <= help->chap_count && 
  170.                     par >= 0 && par < help->par_count) {
  171.  
  172.                     /* note chap 1 is element 0 in the index array */
  173.                     help_SetIndex(help, chap - 1, par, msg);
  174.                 }
  175.             }
  176.         }
  177.     }
  178.  
  179.     /* set up the offset array */
  180.     help->offset = la_Open(msg_count + 1);
  181.  
  182.      if (help->offset == NULL) {
  183.         help = NULL;
  184.         return(HELP_NOMEM);
  185.     }
  186.  
  187.     /* find first msg, put into the offset array */
  188.     while(fgets(buffer, HELPLINE, fp) != NULL) {
  189.         if (buffer[0] == '.' && buffer[1] != '!') {
  190.             msg = atoi(buffer + 1);
  191.             if (msg > 0 && msg <= msg_count) {
  192.                 temp = ftell(fp);
  193.                 if (!la_Put(help->offset, msg, temp)) {
  194.                     help = NULL;
  195.                     return(HELP_NOMEM);
  196.                 }
  197.                 help->high_msg = msg;
  198.                 break;
  199.             }
  200.         }
  201.     }
  202.  
  203.     /* set up the help_Show function */
  204.     _help_InitShow(_help_Show);
  205.  
  206.     return(HELP_OK);
  207. }
  208.  
  209. int _help_Show(int chap, int par)
  210. /*
  211.     Searches for the appropriate message.
  212.     Displays the message via the display function.
  213.  
  214.     If no there is no message for the paragraph, try and give
  215.     the message for the chapter.  If unable to display a message
  216.     return(0) else return(1).
  217. */
  218. /*
  219.     note: this function is called indirectly by help_Show
  220. */
  221. {
  222.     int msg;
  223.  
  224.     /* look up the message number */
  225.     if ((msg = help_Index(chap,par)) == -1) {
  226.         return(0);
  227.     }
  228.  
  229.     /* find the message */
  230.     if (!help_LookUp(msg)) {
  231.         return(0);
  232.     }
  233.  
  234.     (*(help->disp))(help);
  235.  
  236.     return(1);
  237. }
  238.  
  239. int help_Index(int chap, int par)
  240. /*
  241.     Look up the message number associated with the chapter
  242.     and paragraph.
  243.  
  244.     Adjusts the help's chapter and paragraph parameters.
  245.  
  246.     Returns (-1) if no message found.
  247. */
  248. {
  249.     int msg;
  250.  
  251.     /* adjust the chapter number */
  252.     chap--;
  253.  
  254.     if (help == NULL || chap < 0 || chap >= help->chap_count) {
  255.         return(-1);
  256.     }
  257.  
  258.     /* check if par exists */
  259.     if (par <= 0 || par >= help->par_count || help_GetIndex(help, chap, par) <= 0) {
  260.         par = 0;
  261.     }
  262.  
  263.     /* lookup the message number */
  264.     if ((msg = help_GetIndex(help, chap, par)) <= 0) {
  265.         return(-1);
  266.     }
  267.  
  268.     help->chap = chap;
  269.     help->par = par;
  270.  
  271.     return(msg);
  272. }
  273.  
  274. boolean help_LookUp(int msg)
  275. /*
  276.     Looks up the message in the help file.
  277.  
  278.     Adjusts help parameters for the new message.
  279.  
  280.     Returns TRUE if successful.
  281. */
  282. {
  283.     int     m;
  284.     unsigned int size, len;
  285.     char   *found;
  286.     long     offset, temp;
  287.  
  288.     /* is it the same message as last time? */
  289.     if (msg != help->msg) {
  290.         /*     have we found this msg yet?
  291.             if not, look it up.
  292.             get offsets of all the other msgs along the way
  293.         */
  294.  
  295.         if (msg > help->high_msg) {
  296.             fseek(help->fp, la_Get(help->offset, help->high_msg), SEEK_SET);
  297.  
  298.             while((found = fgets(buffer, HELPLINE, help->fp)) != NULL) {
  299.                 if (buffer[0] == '.' && buffer[1] != '!') {
  300.                     m = atoi(buffer + 1);
  301.                     if (m > 0) {
  302.                         temp = ftell(help->fp);
  303.                         if (!la_Put(help->offset, m, temp)) {
  304.                             return(FALSE);
  305.                         }
  306.  
  307.                         help->high_msg = m;
  308.                         if (m == msg) {
  309.                             break;
  310.                         }
  311.                     }
  312.                 }
  313.             }
  314.             if (found == NULL) {
  315.                 return(FALSE);
  316.             }
  317.         }
  318.         else {
  319.             /* get the message, if it is missing do nothing */
  320.             offset = la_Get(help->offset, msg);
  321.             if (offset > 0L) {
  322.                 fseek(help->fp, offset, SEEK_SET);
  323.             }
  324.             else {
  325.                 return(FALSE);
  326.             }
  327.         }
  328.  
  329.         /* get the message */
  330.         /* get the title (skip commented lines) */
  331.         do {
  332.             if (fgets(buffer, HELPLINE, help->fp) == NULL) {
  333.                 break;
  334.             }
  335.  
  336.         } while(buffer[0] == '.' && buffer[1] == '!');
  337.  
  338.         if ((len = strlen(buffer)) > 1 && (buffer[len - 2] == '\r')) {
  339.             /* translate '\r' '\n' to '\0' (if needed) */
  340.             buffer[len - 2] = '\0';
  341.         }
  342.         else if ((len = strlen(buffer)) > 0 && (buffer[len - 1] == '\n')) {
  343.             /* translate '\n' to '\0' (if needed) */
  344.             buffer[len - 1] = '\0';
  345.         }
  346.         strcpy(help->title, buffer);
  347.  
  348.         /* get the text */
  349.         size = 0;
  350.         strcpy(help->text, "");
  351.         while(1) {
  352.             if (fgets(buffer, HELPLINE, help->fp) == NULL) {
  353.                 break;
  354.             }
  355.             if (buffer[0] == '.') {
  356.                 if (buffer[1] == '!') {
  357.                     /* comment: ignore line */
  358.                     continue;
  359.                 }
  360.                 else {
  361.                     /* end of message */
  362.                     break;
  363.                 }
  364.             }
  365.  
  366.             if ((len = strlen(buffer)) > 1 && buffer[len - 2] == '\r') {
  367.                 /* translate '\r' '\n' to '\n' '\0' (if needed) */
  368.                 buffer[len - 2] = '\n';
  369.                 buffer[len - 1] = '\0';
  370.             }
  371.             size += len;
  372.             if (size >= help->size) {
  373.                 break;
  374.             }
  375.             strcat(help->text, buffer);
  376.         }
  377.     }
  378.  
  379.     help->msg = msg;
  380.  
  381.     return(TRUE);
  382. }
  383.  
  384.  
  385. void help_Close(void)
  386. /*
  387.     Destroy and deallocate storage from the help system.
  388. */
  389. {
  390.     if (help != NULL) {
  391.  
  392.         la_Close(help->offset);
  393.         ofree(CSA_HELPINDEX, (VOID *) help->index);
  394.         ofree(CSA_HELPTEXT, (VOID *) help->text);
  395.         ofree(CSA_HELP, (VOID *) help);
  396.  
  397.         help = NULL;
  398.     }
  399. }
  400.