#include <stdlib.h>
#include <stdio.h>
#include <readline/readline.h>
#include <malloc.h>

int match(char*a, char*b)
{
  while (isspace(*a)) a++;
  while (isspace(*b)) b++;
  while (*a && !isspace(*a) && toupper(*a) == toupper(*b)) a++,b++;
  return (*a == '\0' || isspace(*a));
}

void dohelp(FILE*file, int level, char*topic, char*prompt)
{
  long offset, matchpos;
  int pos, next, i, poff, nsubtopic, lookahead;
  char line[128];
  char *newtopic;

  poff = strlen(prompt);
  offset = ftell(file);

  while (1) {
    /* Parse topic */
    pos = 0;
    while (isspace(topic[pos]) || topic[pos]=='?') pos++; /* Skip blanks */
    for (next=pos; topic[next] && !isspace(topic[next]); next++) ;
    while (isspace(topic[next])) next++;
    
    /* Scan file for topic */
    matchpos = -1L;
    nsubtopic = 0;
    while (fgets(line, sizeof(line), file)) {
      if (!isdigit(line[0])) continue; /* Not a topic line, so skip it */
      if (line[0]-'0' < level) break;   /* Start of supertopic, so break */
      if (line[0]-'0' > level) continue; /* Start of subtopic, so skip it */

      /* Grab topic off the line and see if it matches */
      nsubtopic++;
      line[strlen(line)-1] = '\0';       
      for (i=1; isspace(line[i]); i++) ;
      if (!match(topic+pos, line+i)) continue; 

      matchpos = ftell(file);
      if (topic[next]) { 
	/* Command line includes subtopic, so search for it */
	prompt[poff]=' '; strcpy(prompt+poff+(poff!=0?1:0),line+i);
	dohelp(file, level+1, topic+next, prompt);
      }
      else if (topic[pos]) { 
	/* Command line only contains topic, so process here */
	/* Display topic name */
	prompt[poff]=' '; strcpy(prompt+poff+(poff!=0?1:0),line+i);
	printf("%s\n", prompt);

	/* Display topic information */
	lookahead = fgetc(file);
	ungetc(lookahead, file);
	while (lookahead >= 0 && !isdigit(lookahead)) {
	  /* Skip comments starting with '!' TR July 2000 */
	  fgets(line, sizeof(line), file);
	  if (line[0]!='!')
	    printf("%s", line);
	  lookahead = fgetc(file);
	  ungetc(lookahead, file);
	}
 
	/* Process subtopics, if any */
	if (isdigit(lookahead) && lookahead-'0' > level) {
	  printf("\n Additional information available:\n\n"); 
	  /* printf("\nSee also:\n\n"); */
	  fseek(file, matchpos, SEEK_SET); /* Back up to that subtopic again */
	  dohelp(file, level+1, topic+next, prompt);
	}
      }
      else { 
	/* No topic on command line, so list all topics */
	/* Now do carriage return after every 4 topics. TR July 2000 */
	if ( ((nsubtopic-1)%4)==3) {
	  printf("%-19s \n", line+i);
	  /* printf("i= %i nsubtopic= %i \n", i, nsubtopic); */
	  }
	else {
          printf("%-19s ", line+i);
	  /* printf("i= %i nsubtopic= %i \n", i, nsubtopic); */
        }
	 
      }
    }

    if (matchpos == -1L) {
      /* Match not found, so loop through again, this time without a topic
       * so that the list of all topics is printed.
       */
      prompt[poff]=' '; strcpy(prompt+poff+(poff!=0?1:0),topic+pos);
      printf("No match found for %s.\nTry the following:\n\n", prompt);
      fseek(file, offset, SEEK_SET);
      strcpy(topic, "");
      continue;
    }
    else printf("\n");
    
    fseek(file, offset, SEEK_SET);
    prompt[poff]=' '; strcpy(prompt+poff+(poff!=0?1:0), "topic? ");
#ifdef noreadline
        printf("%s", prompt);
	newtopic = malloc(128);
	if (newtopic && !fgets(newtopic, 127, stdin)) {
		free(newtopic);
		newtopic = NULL;
		}
	else {
		newtopic[strlen(newtopic)-1] = '\0';	/* strip \n */
		}
#else
       newtopic = readline(prompt); 
#endif
    *topic = '\0';
    if (newtopic) {
      if (*newtopic) strcpy(topic, newtopic);
      free(newtopic);
    }
    if (!*topic) return;
  }
}

void help_(char*path, char*node, char*def, 
    int pathlen, int nodelen, int deflen) {
#define MAX_NAME 132
  char filename[MAX_NAME], topic[MAX_NAME], prompt[MAX_NAME];
  int i, j, k;
  char *helpdir;
  FILE *file;
  
  if (nodelen > 132) nodelen = 132;
  if (deflen > 132) deflen = 132;


  /* Grab the help directory */
  for (k=0; k<pathlen && path[k] == ' '; k++) ; /* trim leading blanks */
  if ((path == NULL) || (k ==pathlen) ) {
    helpdir = getenv("MSRHELP");
    if (helpdir == NULL) {
      printf("'setenv MSRHELP <helpdir>' and restart program.\n");
      return;
    }
    for (i=0; helpdir[i] && i < MAX_NAME; i++) filename[i]=helpdir[i];
    if (i && filename[i-1] != '/') filename[i++] = '/';
  }

  if ((path != NULL) && (k != pathlen) ) {

  /* Copy path over from fortran */
    for (k=0; k<pathlen && path[k] == ' '; k++) ; /* trim leading blanks */
    printf("help-unx.c: path trimming: %i ...%s...\n", k, path); 
    for (i=0; i<(pathlen-k) && i < MAX_NAME; i++) 
       filename[i] = path[i+k];
    for (i=pathlen-k-1; filename[i] == ' '; i--) ;
    if (i && filename[i-1] != '/') filename[i++] = '/';
    }

/*  printf("help-unx.c: helpdir: ...%s...\n", helpdir); */
/*  printf("help-unx.c: path: %i ...%s...\n", pathlen, path); */
/*  printf("help-unx.c: node: %i ...%s...\n", nodelen, node); */


  /* Copy filename over from fortran */
  for (k=0; k<nodelen && node[k] == ' '; k++) ; /* trim leading blanks */
/*   printf("help-unx.c: node trimming: %i ...%s...\n", k, node); */
  for (j=0; j<(nodelen-k) && i+j < MAX_NAME; j++) 
       filename[i+j] = node[j+k];
  for (j=nodelen-k-1; j && filename[i+j] == ' '; j--) ;
  if (j == -1) strcpy(filename+i, "users.hlp"); /* default if no help node */
  else strcpy(filename+i+j+1, ".hlp"); /* Add .hlp extension. */

/*  printf("help-unx.c: filename: %i %i %i \n", i, j, k); */
/*  printf("help-unx.c: filename: ...%s...\n", filename); */
  /* Open help file */
  file = fopen(filename, "r");
  if (file == NULL) {
    printf("help-unx.c: Help file unavailable: %s\n", filename);
    return;
  }

  /* Copy initial topic over from fortran */
  for (i=0; i < deflen && i < MAX_NAME; i++) topic[i] = def[i];
  topic[deflen] = '\0';
  
  *prompt = '\0';
  printf("help-unx.c: %s\n", filename);
  printf(" \n");
  printf("    Information available:\n");
  printf(" \n");

  dohelp(file, 1, topic, prompt);
  fclose (file);
}

#if 0
main()
{
  help_(".", "san", "", 1, 3, 0);
}
#endif
