home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cHelp.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  20KB  |  777 lines

  1. /*
  2.  *  CELLS       An Implementation of the WireWorld cellular automata
  3.  *              as described in Scientific American, Jan 1990.
  4.  *
  5.  *              Copyright 1990 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  *  See the CELLS.HELP file for complete information on distribution conditions.
  8.  */
  9.  
  10. /*
  11.  *  File:  cHelp.c                  Handles the HELP file system
  12.  */
  13.  
  14.  
  15. #include "cGadget.h"
  16. #include "cRequest.h"
  17. #include "cHelp.h"
  18. #include "cReqHelp.h"
  19. #include <stdio.h>
  20.  
  21. #define MAXERROR    8
  22.  
  23. #define ABTTEXT     ABTRequest.er_Request.ReqText
  24. #define HLPGADGET   HLPRequest.er_Request.ReqGadget
  25.  
  26. extern int HelpActive;
  27.  
  28. static FILE *HelpFile;                          /* the HELP file handle */
  29. static char HelpName[] = "HELP:Cells.Help";     /* the name of the file */
  30. #define HELPNAME    &(HelpName[5])              /* HelpName without 'HELP:' */
  31. static long LineCount;                          /* number of lines read */
  32. static char Line[MAXBUFFER];                    /* the current line of text */
  33. static int noError;                             /* TRUE if no errors so far */
  34. static int EndOfFile;                           /* TRUE if at end of file */
  35. static int CurrentLevel;                        /* help topic level */
  36. static HELPITEM *CurrentNode;                   /* current help topic node */
  37. static int TextNotReported;                     /* TRUE if no error for text */
  38. static int EndHelpSeen;                         /* TRUE if ENDHELP exists */
  39. static int ErrorCount;                          /* number of errors found */
  40.  
  41.  
  42. /*
  43.  *  Main help topic tree
  44.  */
  45.  
  46. HELPITEM HelpRoot =
  47.    {NULL,NULL, NULL,0, HLP_STATIC, NULL, 0, NULL,NULL,NULL, 0};
  48.  
  49.  
  50. /*
  51.  *  HelpError()
  52.  *
  53.  *  Set up the message string, and do the error requester
  54.  *  Count the error, and if enough have already been reported,
  55.  *    ask if the user wants to keep looking at the file
  56.  *  Inform him that we are still loading the file
  57.  */
  58.  
  59. static void HelpError(s,x1,x2,x3,x4)
  60. char *s,*x1,*x2,*x3,*x4;
  61. {
  62.    char Message[80];
  63.  
  64.    sprintf(Message,s,x1,x2,x3,x4);
  65.    sprintf(&Message[strlen(Message)]," at line %d",LineCount);
  66.    DoError(Message);
  67.    ErrorCount++;
  68.    if (ErrorCount == MAXERROR)
  69.    {
  70.       noError = DoQuestion("%d Errors:  Continue Loading?",ErrorCount);
  71.       ErrorCount = 0;
  72.    }
  73.    DoInfoMessage("Continuing to Load Help...");
  74. }
  75.  
  76.  
  77. /*
  78.  *  FreeHelpItem()
  79.  *
  80.  *  If an topic was given,
  81.  *    Free its name, if any, and its title text, if any
  82.  *    If the topic is not a static one, free it
  83.  */
  84.  
  85. static void FreeHelpItem(theItem)
  86. HELPITEM *theItem;
  87. {
  88.    if (theItem)
  89.    {
  90.       if (theItem->Name && theItem->NameLen)
  91.          FREECHAR(theItem->Name,theItem->NameLen);
  92.       if (theItem->Title && theItem->TitleLen)
  93.          FREECHAR(theItem->Title,theItem->TitleLen);
  94.       if ((theItem->Flags & HLP_STATIC) == 0) FREESTRUCT(HelpItem,theItem);
  95.    }
  96. }
  97.  
  98.  
  99. /*
  100.  *  FreeLineList()
  101.  *
  102.  *  For each line in the list,
  103.  *    if the line has text, free it
  104.  *    if the line is not static, free it
  105.  */
  106.  
  107. static void FreeLineList(theLine)
  108. HELPLINE *theLine;
  109. {
  110.    HELPLINE *tmpLine;
  111.    
  112.    while (theLine)
  113.    {
  114.       tmpLine = theLine;
  115.       theLine = theLine->Next;
  116.       if (tmpLine->Text && tmpLine->TextLen)
  117.           FREECHAR(tmpLine->Text,tmpLine->TextLen);
  118.       if ((tmpLine->Flags & HLP_STATIC) == 0) FREESTRUCT(HelpLine,tmpLine);
  119.    }
  120. }
  121.  
  122.  
  123. /*
  124.  *  FreeHelpList()
  125.  *
  126.  *  while ther are more topics in the list,
  127.  *    Free an subtopics of the topic
  128.  *    Free any help lines of the topic
  129.  *    Free the topic itself
  130.  */
  131.  
  132. static void FreeHelpList(theItem)
  133. HELPITEM *theItem;
  134. {
  135.    HELPITEM *tmpItem;
  136.  
  137.    while (theItem)
  138.    {
  139.       FreeHelpList(theItem->SubTopics);
  140.       FreeLineList(theItem->Text);
  141.       tmpItem = theItem;
  142.       theItem = theItem->Next;
  143.       FreeHelpItem(tmpItem);
  144.    }
  145. }
  146.  
  147.  
  148. /*
  149.  *  ClearHelp()
  150.  *
  151.  *  If the default help was changed by the file,
  152.  *    free the (new) default help and reset the default to the standard one
  153.  *  Free all topics in the help tree
  154.  *  If the help file is open, close it and mare it as unopen
  155.  */
  156.  
  157. void ClearHelp()
  158. {
  159.    if (DefaultHelpTopic != &DefaultHelp)
  160.    {
  161.       FreeHelpList(DefaultHelpTopic);
  162.       DefaultHelpTopic = &DefaultHelp;
  163.    }
  164.    FreeHelpList(&HelpRoot);
  165.    if (HelpFile) fclose(HelpFile);
  166.    HelpFile = NULL;
  167. }
  168.  
  169.  
  170. /*
  171.  *  CanClearText()
  172.  *
  173.  *  While there are more topics
  174.  *    if the topic is not in use and its text is loaded
  175.  *      if the topic has text
  176.  *        free the lines of text and clear the pointer
  177.  *        mark the topic as not having its text loaded
  178.  *        indicate that lines have been freed
  179.  *    if the topic has sub-topics,
  180.  *      do the same for the sub-topics
  181.  *    otherwise
  182.  *      while there are no more topics in the current list, go on to the parent
  183.  *      go on to the next topic
  184.  */
  185.  
  186. static int CanClearText(theItem)
  187. HELPITEM *theItem;
  188. {
  189.    int status = FALSE;
  190.    
  191.    while (theItem)
  192.    {
  193.       if ((theItem->Flags & (HLP_INUSE|HLP_LOADED)) == HLP_LOADED)
  194.       {
  195.          if (theItem->Text)
  196.          {
  197.             FreeLineList(theItem->Text);
  198.             theItem->Text = NULL;
  199.             theItem->Flags &= ~HLP_LOADED;
  200.             status = TRUE;
  201.          }
  202.       }
  203.       if (theItem->SubTopics)
  204.       {
  205.          theItem = theItem->SubTopics;
  206.       } else {
  207.          while (theItem->Next == NULL && theItem->Parent)
  208.             theItem = theItem->Parent;
  209.          theItem = theItem->Next;
  210.       }
  211.    }
  212.    return(status);
  213. }
  214.  
  215.  
  216. /*
  217.  *  CanClearHelpLines()
  218.  *
  219.  *  Try to clear lines of text from the main help tree and the default help
  220.  *  tree, and return TRUE if memory was freed.
  221.  */
  222.  
  223. int CanClearHelpLines()
  224. {
  225.    int status = FALSE;
  226.    
  227.    status = CanClearText(&HelpRoot);
  228.    if (DefaultHelpTopic != &DefaultHelp)
  229.       status |= CanClearText(DefaultHelpTopic);
  230.    return(status);
  231. }
  232.  
  233.  
  234. /*
  235.  *  CanClearHelpTopics()
  236.  *
  237.  *  If the help system is not active,
  238.  *    if there are lines of text in the miain list, or topics in the main list
  239.  *        or the main list has a title,
  240.  *      Clear all the help topics, and close the file
  241.  *      Set the pointers to NULL.
  242.  *      indicate that the clear was successful
  243.  */
  244.  
  245. int CanClearHelpTopics()
  246. {
  247.    int status = FALSE;
  248.  
  249.    if (!HelpActive)
  250.    {
  251.       if (HelpRoot.Text || HelpRoot.SubTopics || HelpRoot.Title)
  252.       {
  253.          ClearHelp();
  254.          HelpRoot.Text = NULL;
  255.          HelpRoot.SubTopics = NULL;
  256.          HelpRoot.Title = NULL;
  257.          status = TRUE;
  258.       }
  259.    }
  260.    return(status);
  261. }
  262.  
  263.  
  264. /*
  265.  *  NewHelpItem()
  266.  *
  267.  *  Get a new help topic structure; if successful
  268.  *    If there is a name for the topic,
  269.  *      try to allocate space for the name
  270.  *      if successful, copy the name, otherwise free the help item
  271.  *    otherwise clera the name area
  272.  *    If the help item was allocated OK,
  273.  *      determine its file position and parent
  274.  *      mark the fact that text errors have not be reported for this item
  275.  */
  276.  
  277. static HELPITEM *NewHelpItem(s)
  278. char *s;
  279. {
  280.    HELPITEM *theItem;
  281.    
  282.    if (NEWSTRUCT(HelpItem,theItem))
  283.    {
  284.       if (s)
  285.       {
  286.          theItem->NameLen = strlen(s);
  287.          if (NEWCHAR(theItem->Name,theItem->NameLen))
  288.          {
  289.             strcpy(theItem->Name,s);
  290.          } else {
  291.             FREESTRUCT(HelpItem,theItem);
  292.             theItem = NULL;
  293.          }
  294.       } else {
  295.          theItem->NameLen = 0;
  296.          theItem->Name = NULL;
  297.       }
  298.       if (theItem)
  299.       {
  300.          theItem->FilePos = ftell(HelpFile);
  301.          theItem->Parent = CurrentNode;
  302.          TextNotReported = TRUE;
  303.       }
  304.    }
  305.    return(theItem);
  306. }
  307.  
  308.  
  309. /*
  310.  *  NewHelpLine()
  311.  *
  312.  *  Allocate a new help line structure; if successful,
  313.  *    get space for the line of text (remove the trailing new-line), and
  314.  *    copy the line of text.
  315.  */
  316.  
  317. static HELPLINE *NewHelpLine(s)
  318. char *s;
  319. {
  320.    HELPLINE *theLine;
  321.    short len;
  322.    
  323.    if (NEWSTRUCT(HelpLine,theLine))
  324.    {
  325.       len = strlen(s);
  326.       if (len > 0 && s[len-1] == '\n') s[--len] = 0;
  327.       if (NEWCHAR(theLine->Text,len))
  328.       {
  329.          strcpy(theLine->Text,s);
  330.          theLine->TextLen = len;
  331.       } else {
  332.          FREESTRUCT(HelpLine,theLine);
  333.          theLine = NULL;
  334.       }
  335.    }
  336.    return(theLine);
  337. }
  338.  
  339.  
  340. /*
  341.  *  ReadHelpLine()
  342.  *
  343.  *  If there have been no file errors,
  344.  *    If we can read the next line from the file
  345.  *      increment the line count
  346.  *    Otherwise
  347.  *      if we're at the end of the file, indicate that
  348.  *      otherwise report the error that occured
  349.  */
  350.  
  351. static void ReadHelpLine()
  352. {
  353.    if (noError)
  354.    {
  355.       if (fgets(Line,MAXBUFFER,HelpFile))
  356.       {
  357.          LineCount++;
  358.       } else {
  359.          if (feof(HelpFile))
  360.          {
  361.             EndOfFile = TRUE;
  362.          } else {
  363.             DosError("Read","Help Line");
  364.             noError = FALSE;
  365.          }
  366.       }
  367.    } else {
  368.       EndOfFile = TRUE;
  369.    }
  370. }
  371.  
  372.  
  373. /*
  374.  *  OpenHelp()
  375.  *
  376.  *  Go back to the initial directory for a moment and try to open the
  377.  *  help file there.  If unsuccessful, try to open the file in HELP:
  378.  *
  379.  *  If the file was found,
  380.  *    clear the line count, and other flags, and start at the top of the tree
  381.  *    read the first line of the file
  382.  *  Otherwise report the trouble openning the file
  383.  */
  384.  
  385. static int OpenHelp()
  386. {
  387.    SwapLocks(); HelpFile = fopen(HELPNAME,"r"); SwapLocks();
  388.    if (HelpFile == NULL) HelpFile = fopen(HelpName,"r");
  389.  
  390.    if (HelpFile)
  391.    {
  392.       LineCount = 0;
  393.       EndOfFile = FALSE; EndHelpSeen = FALSE;
  394.       noError = TRUE; TextNotReported = TRUE; ErrorCount = 0;
  395.       CurrentLevel = 0;
  396.       CurrentNode = &HelpRoot;
  397.       ReadHelpLine();
  398.    } else {
  399.       DosError("Open",HelpName);
  400.    }
  401.    return(HelpFile != NULL);
  402. }
  403.  
  404.  
  405. /*
  406.  *  The valid help file commands
  407.  */
  408.  
  409. static char *HelpCommand[] = {"Title:","Link:","Help:","EndHelp:"};
  410. #define HT_UNKNOWN  0
  411. #define HT_LEVEL    1
  412. #define HT_TITLE    2
  413. #define HT_LINK     3
  414. #define HT_HELP     4
  415. #define HT_END      5
  416.  
  417. #define HT_COUNT    4
  418.  
  419.  
  420. /*
  421.  *  ParseHelp()
  422.  *
  423.  *  Find the end of the first word on the line, and separate it
  424.  *  Clear the trailing new-line character, if any
  425.  *  If the first character is a digit
  426.  *    calculate the level that is specified
  427.  *    if there are non-digits following the level number,
  428.  *      set up for an error
  429.  *    otherwise
  430.  *      indicate that a valid level was provided
  431.  *      move the string pointer on to the beginning of the topic name
  432.  *  Otherwise (not a digit)
  433.  *    see if the first word on the line matches one of the commands
  434.  *    if so, indicate which one, and set the string pointer to the beginning
  435.  *    of parameterfor the command
  436.  */
  437.  
  438. static int ParseHelp(Level,s)
  439. int *Level;
  440. char **s;
  441. {
  442.    int HelpType = HT_UNKNOWN;
  443.    short i;
  444.    char *s1;
  445.  
  446.    *s = s1 = &Line[1];
  447.    while (*s1 > ' ') s1++;
  448.    *s1++ = 0;
  449.    while (*s1 && *s1 != '\n') s1++;
  450.    *s1++ = 0; *s1 = 0;
  451.  
  452.    if (**s >= '0' && **s <= '9')
  453.    {
  454.       *Level = 0;
  455.       while (**s >= '0' && **s <= '9')
  456.       {
  457.          *Level = (*Level) * 10 + (**s) - '0';
  458.          (*s)++;
  459.       }
  460.       if (**s)
  461.       {
  462.          *s = &Line[1];
  463.       } else {
  464.          HelpType = HT_LEVEL;
  465.          (*s)++;
  466.       }
  467.    } else {
  468.       for (i=0; i<HT_COUNT && HelpType == HT_UNKNOWN; i++)
  469.       {
  470.          if (stricmp(HelpCommand[i],*s) == 0)
  471.          {
  472.             HelpType = i + HT_TITLE;
  473.             *s += strlen(*s) + 1;
  474.          }
  475.       }
  476.    }
  477.    return(HelpType);
  478. }
  479.  
  480.  
  481. /*
  482.  *  DoHelpLine()
  483.  *
  484.  *  Find the type of command that was given and do the right thing:
  485.  *
  486.  *  LEVEL:
  487.  *    if the specified level is not the next lower level or is too small,
  488.  *      give an error message
  489.  *    otherwise
  490.  *      find the help node that is the parent of the required topic level
  491.  *      get a new topic structure; if successful
  492.  *        link it into the topic list of the parent topic
  493.  *        set the current node and level
  494.  *      otherwise give an error
  495.  *
  496.  *  TITLE:
  497.  *    if the current topic is linked give an error
  498.  *    otherwise if the current topic already has a title, give an error
  499.  *    otherwise
  500.  *       if a title was supplied as a parameter,
  501.  *         make a copy of the title, if possible (error if not)
  502.  *       otherwise report the missing title parameter
  503.  *
  504.  *  LINK:
  505.  *    if the topic already has a link, report an error
  506.  *    otherwise, if the topic already has text lines, give an error
  507.  *    otherwise
  508.  *      if the topic has a title, warn that it will be ignored, and free it.
  509.  *      copy the link string to the title area, if possible.
  510.  *
  511.  *  HELP:
  512.  *    if the default help has not already been changed,
  513.  *      get a new help topic; if successful
  514.  *        set up the new item as the new default help root
  515.  *      otherwise report an error
  516.  *    otherwise report that HELP has already appeared in the file
  517.  *
  518.  *  END:
  519.  *    check for proper use of ENDHELP, and if OK, go back to
  520.  *    using the main help tree at the top level.
  521.  */
  522.  
  523. static void DoHelpLine()
  524. {
  525.    int Level;
  526.    char *s;
  527.    HELPITEM *theItem;
  528.  
  529.    switch(ParseHelp(&Level,&s))
  530.    {
  531.       case HT_LEVEL:
  532.          if (Level > CurrentLevel+1 || Level < 1)
  533.          {
  534.             HelpError("Invalid Help Topic Level '%d'",Level);
  535.          } else {
  536.             while (Level <= CurrentLevel && CurrentNode->Parent)
  537.             {
  538.                CurrentNode = CurrentNode->Parent;
  539.                CurrentLevel--;
  540.             }
  541.             theItem = NewHelpItem(s);
  542.             if (theItem)
  543.             {
  544.                theItem->Prev = NULL;
  545.                theItem->Next = CurrentNode->SubTopics;
  546.                if (theItem->Next) theItem->Next->Prev = theItem;
  547.                CurrentNode->SubTopics = theItem;
  548.                CurrentNode = theItem;
  549.                CurrentLevel++;
  550.             } else {
  551.                HelpError("Can't Get Memory for Help Topic");
  552.             }
  553.          }
  554.          break;
  555.  
  556.       case HT_TITLE:
  557.          if (CurrentNode->Flags & HLP_LINKED)
  558.          {
  559.             HelpError("LINKed Topics can not have TITLES");
  560.          } else if (CurrentNode->Title) {
  561.             HelpError("Topic already has a TITLE");
  562.          } else {
  563.             CurrentNode->TitleLen = strlen(s);
  564.             if (CurrentNode->TitleLen)
  565.             {
  566.                if (NEWCHAR(CurrentNode->Title,CurrentNode->TitleLen))
  567.                   strcpy(CurrentNode->Title,s);
  568.                  else
  569.                   HelpError("Can't Get Memory for Topic Title");
  570.             } else {
  571.                HelpError("TITLE Text String is Blank");
  572.             }
  573.          }
  574.          break;
  575.  
  576.       case HT_LINK:
  577.          if (CurrentNode->Flags & HLP_LINKED)
  578.          {
  579.             HelpError("Topic Already has a LINK");
  580.          } else if (CurrentNode->Flags & HLP_HASTEXT) {
  581.             HelpError("Topics with Text can not be LINKed");
  582.          } else {
  583.             if (CurrentNode->Title)
  584.             {
  585.                HelpError("LINK will cause TITLE to be Ignored");
  586.                FREECHAR(CurrentNode->Title,CurrentNode->TitleLen);
  587.             }
  588.             CurrentNode->TitleLen = strlen(s);
  589.             if (CurrentNode->TitleLen)
  590.             {
  591.                if (NEWCHAR(CurrentNode->Title,CurrentNode->TitleLen))
  592.                {
  593.                   strcpy(CurrentNode->Title,s);
  594.                   CurrentNode->Flags |= HLP_LINKED;
  595.                } else {
  596.                   HelpError("Can't Get Memory for LINK");
  597.                }
  598.             } else {
  599.                HelpError("LINK String is Blank");
  600.             }
  601.          }
  602.          break;
  603.  
  604.       case HT_HELP:
  605.          if (DefaultHelpTopic == &DefaultHelp)
  606.          {
  607.             theItem = NewHelpItem(NULL);
  608.             if (theItem)
  609.             {
  610.                theItem->Next = theItem->Prev = NULL;
  611.                theItem->Parent = NULL;
  612.                CurrentNode->SubTopics = NULL;
  613.                CurrentNode = theItem;
  614.                CurrentLevel = 0;
  615.                DefaultHelpTopic = theItem;
  616.             } else {
  617.                HelpError("Can't Get Memory for Default Help Topic");
  618.             }
  619.          } else {
  620.             HelpError("Duplicate HELP Command Ignored");
  621.          }
  622.          break;
  623.  
  624.       case HT_END:
  625.          if (DefaultHelpTopic == &DefaultHelp)
  626.          {
  627.             HelpError("ENDHELP Before HELP");
  628.          } else if (EndHelpSeen) {
  629.             HelpError("Duplicate ENDHELP Command Ignored");
  630.          } else {
  631.             CurrentNode = &HelpRoot;
  632.             CurrentLevel = 0;
  633.             EndHelpSeen = TRUE;
  634.          }
  635.          break;
  636.  
  637.       case HT_UNKNOWN:
  638.          HelpError("Unknown HELP Command '%s'",s);
  639.          break;
  640.    }
  641. }
  642.  
  643.  
  644. /*
  645.  *  LoadHelp()
  646.  *
  647.  *  If the help file is already open, return OK
  648.  *  otherwise
  649.  *    put up the info message
  650.  *    and try to open the help file; if OK
  651.  *      while there are more lines in the file,
  652.  *        if the line starts with the command symbol
  653.  *          do the command it specifies
  654.  *        otherwise
  655.  *          if the current topic is linked report the error
  656.  *          otherwise mark the topic as having text
  657.  *        read the next line frlom the file
  658.  *      if an error occured, indicate that the file was not all read
  659.  *    clear the info message
  660.  */
  661.  
  662. int LoadHelp()
  663. {
  664.    int status = FALSE;
  665.    
  666.    if (HelpFile)
  667.    {
  668.       status = TRUE;
  669.    } else {
  670.       DoInfoMessage("Loading Help Topics");
  671.       if (OpenHelp())
  672.       {
  673.          while (!EndOfFile)
  674.          {
  675.             if (Line[0] == '*' && Line[1] != '*')
  676.             {
  677.                DoHelpLine();
  678.             } else if (Line[0] != '!') {
  679.                if ((CurrentNode->Flags & HLP_LINKED) && TextNotReported)
  680.                {
  681.                   HelpError("LINKed Topics can not have Text");
  682.                   TextNotReported = FALSE;
  683.                } else {
  684.                   CurrentNode->Flags |= HLP_HASTEXT;
  685.                }
  686.             }
  687.             ReadHelpLine();
  688.          }
  689.          if (noError = FALSE) DoError("Help Topics Not Completely Loaded");
  690.          status = TRUE;
  691.       }
  692.       ClearInfoMessage();
  693.    }
  694.    return(status);
  695. }
  696.  
  697.  
  698. /*
  699.  *  LoadItem()
  700.  *
  701.  *  If the specified topic is not already loaded and it has text to be loaded
  702.  *    find the start of the topic in the help file,
  703.  *    if that was not possible, give an error
  704.  *    otherwise
  705.  *      while we're not done with the topic,
  706.  *        read the next line of text
  707.  *        if we reached the end of file, we're done,
  708.  *        otherwise
  709.  *          if the line is not a command or a comment
  710.  *            skip duplicate '*' ('**' means '*' as first character of line)
  711.  *            get a new text line structure
  712.  *            if allocated OK,
  713.  *              link the text line into the topics text list
  714.  *            otherwise give an error and quit
  715.  *          otherwise if the line is a command
  716.  *            check whether it is one that ends the help topic
  717.  *      mark the topic as having its text loaded
  718.  *      let the user know if it was not completely loaded
  719.  */
  720.  
  721. void LoadItem(theItem)
  722. HELPITEM *theItem;
  723. {
  724.    int NotDone = TRUE;
  725.    int Level;
  726.    char *s;
  727.    HELPLINE *theLine;
  728.  
  729.    if ((theItem->Flags & (HLP_LOADED|HLP_HASTEXT)) == HLP_HASTEXT)
  730.    {
  731.       if (fseek(HelpFile,theItem->FilePos,0) == -1)
  732.       {
  733.          DosError("Find","Help Text");
  734.       } else {
  735.          noError = TRUE;
  736.          EndOfFile = FALSE;
  737.          EndHelpSeen = FALSE;
  738.          while (NotDone)
  739.          {
  740.             ReadHelpLine(); s = &Line[0];
  741.             if (EndOfFile)
  742.             {
  743.                NotDone = FALSE;
  744.             } else {
  745.                if ((Line[0] != '*' || Line[1] == '*') && Line[0] != '!')
  746.                {
  747.                   if (Line[0] == '*') s++;
  748.                   theLine = NewHelpLine(s);
  749.                   if (theLine)
  750.                   {
  751.                      theLine->Prev = NULL;
  752.                      theLine->Next = theItem->Text;
  753.                      if (theLine->Next) theLine->Next->Prev = theLine;
  754.                      theItem->Text = theLine;
  755.                   } else {
  756.                      DoError("Can't Get Memory for Help Text");
  757.                      NotDone = FALSE; noError = FALSE;
  758.                   }
  759.                } else if (Line[0] == '*') {
  760.                   switch(ParseHelp(&Level,&s))
  761.                   {
  762.                      case HT_LEVEL:
  763.                      case HT_HELP:
  764.                      case HT_END:
  765.                         NotDone = FALSE;
  766.                         break;
  767.                   }
  768.                }
  769.             }
  770.          }
  771.          theItem->Flags |= HLP_LOADED;
  772.          if (noError == FALSE) DoError("Text Not Completely Loaded");
  773.       }
  774.    }
  775. }
  776.  
  777.