/*
 *	Copyright (C) 1993  TGV, Incorporated.
 *
 *	Help
 */

#include "comnd.h"
#include <stdio.h>
#include <lbrdef.h>
#include <lhidef.h>
#include <hlpdef.h>

extern unsigned long LBR$OUTPUT_HELP(), LIB$PUT_OUTPUT(), LIB$GET_INPUT();
static int Add_Help_Entry();

struct Descr {
    int Size;
    char *Ptr;
};

struct CONTEXT {
    char Help_File_Name[512];
    struct Descr HelpLib_Dsc;
    struct Keyword_Table *Table;
};

struct Keyword_Table {
	int current_entries;
	int maximum_entries;
	struct tbluk_keyword keywords[1];
};

static char Atom_Buffer[128];

static struct CONTEXT *Current_Context = (struct CONTEXT *) 0;

Init_CMD_Help(helplib, Context)
char *helplib;
struct CONTEXT **Context;
{
	/*
	 *  If we've already initialized this context, then make it
	 *  the current context...
	 */
	if (Context && *Context) {
	    Current_Context = *Context;
	}
	/*
	 *  Else create a new context...
	 */
	Current_Context = (struct CONTEXT *) malloc(sizeof(struct CONTEXT));
	strcpy(Current_Context->Help_File_Name, helplib);
	Current_Context->HelpLib_Dsc.Ptr = Current_Context->Help_File_Name;
	Current_Context->HelpLib_Dsc.Size = strlen(Current_Context->Help_File_Name);
	Current_Context->Table = (struct Keyword_Table *) 0;
	/*
	 *  Maybe return it...
	 */
	if (Context)
	    *Context = Current_Context;
}


static int Add_Help_Entry(key_name_desc, rfa)
struct Descr *key_name_desc;
unsigned long int rfa[];
{
	char *Help_Keyword;
	struct tbluk_keyword New_Keyword;

	Help_Keyword = (char *)malloc(key_name_desc->Size + 1);
	if (Help_Keyword == 0) {
		printf("ERROR: Out of memory.\n");
		exit(1);
	}
	strncpy(Help_Keyword,
		key_name_desc->Ptr,
		key_name_desc->Size);
	Help_Keyword[key_name_desc->Size] = 0;
	/*
	 *	Add the keyword entry
	 */
	New_Keyword.flags = 0;
	New_Keyword.keyword = Help_Keyword;
	New_Keyword.user_data = 0;
	tbadd_jsys(&New_Keyword,Current_Context->Table);

/*    printf("\t%s\n",Help_Keyword); */
	return(1);
}

CMD_Help(Comnd_State)
struct comnd_state *Comnd_State;
{
	int Clear_Atom_Buffer = 0;
	
static struct comnd_function Commands_LOCAL_1 = {
	COMND_CONFIRM,
	0,
	0,
	(int)0,
	0,
	0,
	0};

static struct comnd_function Commands = {
	COMND_KEYWORD,
	(COMND_HELP_VALID),
	&Commands_LOCAL_1,
	(int)0,
	"command, ",
	0,
	0};

	
static struct comnd_function Commands2 = {
	COMND_TEXT,
	0,
	0,
	(int)0,
	0,
	0,
	0};

	struct tbluk_keyword *t;
	struct comnd_function *f;
	struct Descr HelpEnt_Dsc;
	unsigned int help_flags;
	char Help_String[512];

	if (!Current_Context->Table) {
	    int i;

	    union {
		struct lhidef lib_h;
		unsigned long int lib_array[128];
	    } lib_header;

	    unsigned long int library_index;
	    unsigned long int status;
	    static unsigned long int one = 1;
	    static unsigned long int func = LBR$C_READ;
	    static unsigned long int type = LBR$C_TYP_HLP;

	    status = LBR$INI_CONTROL(&library_index,
				     &func,
				     &type,
				     0);
	    if (!(status & 1)) {LIB$SIGNAL(status); return;}

	    status = LBR$OPEN(&library_index,
			      &Current_Context->HelpLib_Dsc,
			      0,
			      0,
			      0,
			      0,
			      0);
	    if (!(status & 1)) {LIB$SIGNAL(status); return;}

	    status = LBR$GET_HEADER(&library_index,
				    &lib_header);
	    if (!(status & 1)) {LIB$SIGNAL(status); return;}
/*	    printf("number of entries = %d\n",lib_header.lib_h.lhi$l_modcnt); */

	    Current_Context->Table = (struct Keyword_Table *)
				     malloc(sizeof(*Current_Context->Table) +
					    sizeof(Current_Context->Table->keywords) *
					    (lib_header.lib_h.lhi$l_modcnt-1));
	    Current_Context->Table->current_entries = 0;
	    Current_Context->Table->maximum_entries = lib_header.lib_h.lhi$l_modcnt;

	    status = LBR$GET_INDEX(&library_index,
				   &one,
				   Add_Help_Entry);
	    if (!(status & 1)) {LIB$SIGNAL(status); return;}
	}
	/*
	 *	Do noise
	 */
	__noise("on command",Comnd_State);
	/*
	 *	Set up the Atom Buffer if there isn't one...
	 */
	if (!Comnd_State->atom_buffer) {
	    Clear_Atom_Buffer=1;
	    Comnd_State->atom_buffer = Atom_Buffer;
	    Comnd_State->atom_buffer_size = sizeof(Atom_Buffer);
	}

	/*
	 *	Get Help topic
	 */
	Commands.data = (int) Current_Context->Table;
	COMND(Comnd_State,&Commands,&t,&f);
	if (f->code == COMND_CONFIRM)
		Help_String[0] = '\0';
	else {
		strcpy(Help_String, t->keyword);
		/*
		 *	Get the rest of the line
		 */
		COMND(Comnd_State,&Commands2,0,0);
		/*
		 *  Add the string
		 */
		if (*Comnd_State->atom_buffer) {
		    strcat(Help_String," ");
		    strcat(Help_String,Comnd_State->atom_buffer);
		}
		/*
		 *	Confirm
		 */
			__confirm(Comnd_State);
	}	

	if (Clear_Atom_Buffer) {
	    Comnd_State->atom_buffer = 0;
	    Comnd_State->atom_buffer_size = 0;
	}
	/*
	 *	Do help
	 */
	HelpEnt_Dsc.Ptr = Help_String;
	HelpEnt_Dsc.Size = strlen(Help_String);
	help_flags = HLP$M_PROMPT | HLP$M_HELP;
	LBR$OUTPUT_HELP(LIB$PUT_OUTPUT,
			0,
			&HelpEnt_Dsc,
			&Current_Context->HelpLib_Dsc,
			&help_flags,
			LIB$GET_INPUT);
}
