/* simhelp.c

   written by Don Robert Maszle
   27 July 1992
   
   Copyright (c) 1993.  Don Maszle, Frederic Bois.  All rights reserved.

   -- Revisions -----
     Logfile:  SCCS/s.simhelp.c
    Revision:  1.1
        Date:  7/14/93
     Modtime:  19:14:53
      Author:  @a
   -- SCCS  ---------

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>


#define MAX_HELP_LINE 100		/*-- Length of help line */
#define MAX_KEYWORD 40			/*-- Length of help key */
#define NO_MATCH    (-1)

#ifndef TRUE
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif


static char *vszHelpFilename = "simhelp.txt";


typedef enum tagSOF_FLAGS {
  SOF_READ
} SOF_FLAGS;

/* IgnoreCase_strstr

   returns non-NULL if szSub matches the head of szSearch, ignoring
   case.
*/

char *IgnoreCase_strstr (char *szSearch, char *szSub)
{
  char *szSearchSave = szSearch;
  
  if (!szSearch || !szSub)
    return NULL;

  while (*szSub && *szSearch &&
	 tolower(*szSearch) == tolower(*szSub)) {
    szSearch++;			/*-- Don't inc these in the macro tolower()! */
    szSub++;
  }  /* while */
				/*-- Matched if nothing left of szSub! */
  return (*szSub ? NULL : szSearchSave);
}  /* *IgnoreCase_strstr */


/* FindNextMatch

   searches the given file for the szKeyword in brackets at the
   beginning of the line.  Returns TRUE if a match is found and
   leaves the pfileHelp set to the beginning of the the relevant help
   section.
*/

BOOL FindNextMatch (FILE *pfileHelp, char *szTestKeyword)
{
  int ch;
  BOOL bFound = FALSE;
  char szKeyword[MAX_KEYWORD];
  
  if (pfileHelp)
    while (!feof(pfileHelp)) {
      ch = getc (pfileHelp);

      switch (ch) {
	case EOF:
	  goto Exit_FindNextMatch;	/*-- Stop processsing */
	  break;

	case '[':
	  while (!bFound) {
	    while ((ch = getc(pfileHelp)) == ' ' /*-- Skip whitespace */
		   || ch == '\t' || ch == '\n')
	      ;
	    if (ch == ']')	/*-- No more keys left here */
	      break;

	    ungetc (ch, pfileHelp);
	    fscanf (pfileHelp, "%[^]\n \t]", szKeyword);
	    bFound = ((int) IgnoreCase_strstr(szKeyword, szTestKeyword));
	  }  /* while */
	  fscanf (pfileHelp, "%*[^\n]");
	  getc (pfileHelp);
	  if (bFound)
	    goto Exit_FindNextMatch;	/*-- Found one! */
	  break;

	default:
	  ungetc (ch, pfileHelp);
	  fscanf (pfileHelp, "%*[^\n]");  getc (pfileHelp);
	  break;		/*-- Continue looking next line */
    }  /* switch */
  }  /* while */

Exit_FindNextMatch:
  return (bFound);
}  /* FindNextMatch */


char PauseForKey (char *szKeys)
{
  int ch;
  printf ("-- More --");

  do {
    ch = getchar();
  } 
  while (!strchr (szKeys, ch));
  return ch;
}  /* PauseForKey */


/* MoreToNextTopic

   displays the text in a file from lPos to the next occurence of
   `[keyword]' at the begining of a line.
*/

void MoreToNextTopic (FILE *pfile)
{
  int ch;
#define LINES_PER_PAGE 22
  long cLines = 0;
  char szLine[MAX_HELP_LINE];

  while (!feof(pfile)) {
    ch = getc (pfile);
    if (ch == '[') {
      ungetc (ch, pfile);
      break;
    }  /* if */
    if (ch == '\n')
      putchar ('\n');
    else {
      szLine[0] = '\0';
      fscanf (pfile, "%[^\n]", szLine);
      getc (pfile);
      printf ("%c%s\n", ch, szLine);
    }  /* else */
    cLines++;
    if (!(cLines % LINES_PER_PAGE)) {
      char chKey = PauseForKey ("\n qQ");
      cLines = 0;
      if (tolower(chKey) == 'q')
	break;
    }  /* if */
  }  /* while */
}  /* MoreToNextTopic */

void ShowTopics (FILE *pfileHelp)
{
  printf ("Topics not implemented.\n");
}  /* ShowTopics */

/* SimOpenFile

   Opens file with the specified access priveledges.
   
   Return non-zero on error.
*/

int SimOpenFile (FILE **ppfile, char *szFilename, SOF_FLAGS sofFlags)
{
  int iError = 0;

  *ppfile = NULL;
  
  switch (sofFlags) {
    case SOF_READ:
      *ppfile = fopen (szFilename, "r");
      break;

    default:
      fprintf (stderr, "SimOpenFiles unknown flags :%x\n", sofFlags);
  }  /* switch */

  return (!ppfile);  
}  /* SimOpenFile */


void ShowHelpMessage (char *const szProgName)
{
  printf ("\nHelp!  For help on a topic enter\n\t%s -h topic\n\n",
	  szProgName);
  printf ("Several topics are:  Usage, Intro, Commands, and Topics\n\n");
}  /* ShowHelpMessage */

/* ShowHelp

   displays help about keyword szKeyword if it can find an exact
   match or an abbreviated match int the vszHelpFilename.
*/

void ShowHelp (char *szKeyword)
{
  FILE *pfileHelp;
  BOOL bFound = FALSE;

  printf ("Help topic: `%s'\n\n", szKeyword);
  
  if (!SimOpenFile(&pfileHelp, vszHelpFilename, SOF_READ)) {
    if (IgnoreCase_strstr("Topics", szKeyword))
      ShowTopics (pfileHelp);
    else {
      while (FindNextMatch (pfileHelp, szKeyword)) {
	if (bFound) {		/*-- Pause between sections */
	  char chKey = PauseForKey ("\n qQ");
	  if (tolower(chKey) == 'q')
	    break;
	}  /* if */
	MoreToNextTopic (pfileHelp);
	bFound = TRUE;
      }  /* while */
    
      if (!bFound)
	fprintf (stderr, "** Sorry, no help available on topic `%s' "
		 "in documentation `%s'.\n", szKeyword, vszHelpFilename);
    }  /* else */
  }  /* if */
}  /* ShowHelp */


