/*
** vn news reader.
**
** help.c - print help
**
** see copyright disclaimer / history in vn.c source file
*/
#include <stdio.h>
#include <setjmp.h>
#include "config.h"
#include "tty.h"
#include "tune.h"
#include "node.h"
#include "page.h"
#include "reader.h"
#include "vn.h"

extern int L_allow;
extern int C_allow;
extern int Digest;
extern char *Contstr;
extern char Cxptoi[], Cxrtoi[];

extern int (*Hookfunc)();
extern char *(*Hookhelp)();

static h_print ();

/*
	Help message table.  Character for command, plus its help
	message.  Table order is order of presentation to user.
*/
static struct HELPTAB
{
	char cmd, *msg;
	int dig;
	char *amsg;
} 
Helptab [] =
{
	{ QUIT, "quit", 1, NULL},
	{ UP, "(or up arrow) move up [number of lines]", 1, NULL},
	{ DOWN, "(or down arrow) move down [number of lines]", 1, NULL},
#ifdef PAGEARROW
	{ BACK, "(or left arrow) previous page [number of pages]", 1, NULL},
	{ FORWARD, "(or right arrow) next page [number of pages]", 1, NULL},
#else
	{ BACK, "previous page [number of pages]", 1, NULL},
	{ FORWARD, "next page [number of pages]", 1, NULL},
#endif
	{ GRPBACK, "previous newsgroup [number of newsgroups]", 0, NULL },
	{ GRPFORWARD, "next newsgroup [number of newsgroups]", 0, NULL },
	{ TOPMOVE, "move to top of page", 1, NULL},
	{ BOTMOVE, "move to bottom of page", 1, NULL},
	{ ALTBOTTOM, "move to bottom of page (alternate L)", 1, NULL},
	{ MIDMOVE, "move to middle of page", 1, NULL},
	{ DIGEST, "unpack digest", 1, "exit digest"},
	{ READ, "read article [number of articles]", 1, NULL},
	{ ALTREAD, "read article (alternate 'r')", 1, NULL},
	{ READALL, "read all articles on page", 1, NULL},
	{ READSTRING, "specify articles to read", 1, NULL},
	{ SAVE, "save or pipe article [number of articles]", 1, NULL},
	{ SAVEALL, "save or pipe all articles on page", 1, NULL},
	{ SAVESTRING, "specify articles to save", 1, NULL},
	{ ALTSAVE, "specify articles to save (alternate ctl-s)", 1, NULL},
	{ PRINT, "print article [number of articles]", 1, NULL},
	{ PRINTALL, "print all article on page", 1, NULL},
	{ PRINTSTRING, "specify articles to print", 1, NULL},
	{ UPDATE, "update .newsrc status to cursor", 0, NULL},
	{ UPALL, "update .newsrc status for whole newsgroup", 0, NULL},
	{ UPSEEN, "update .newsrc status for all pages displayed", 0, NULL},
	{ ORGGRP, "recover original .newsrc status for newsgroup", 0, NULL},
	{ ORGSTAT, "recover all original .newsrc status", 0, NULL},
	{ SSTAT, "display count of groups and pages - shown and total", 0, NULL},
	{ GRPLIST, "list newsgroups with new article, updated counts", 0, NULL},
	{ NEWGROUP, "specify newsgroup to display and/or resubscribe to", 1, NULL},
	{ UNSUBSCRIBE, "unsubscribe from group", 0, NULL},
	{ MARK, "mark/unmark article [number of articles]", 1, NULL},
	{ ART_MARK, "mark/unmark article [number of articles]", 1, NULL},
	{ UNMARK, "erase marks on articles", 1, NULL},
	{ MARKSTRING, "specify articles to mark/unmark", 1, NULL},
	{ HEADTOG, "toggle flag for display of headers when reading", 1, NULL},
	{ SETROT, "toggle rotation for reading", 1, NULL},
	{ REDRAW, "redraw screen", 1, NULL},
#ifdef amiga
	{ UNESC, "escape to AMIGADOS to execute a command", 1, NULL},
#else
	{ UNESC, "escape to UNIX to execute a command", 1, NULL},
#endif
	{ PRTVERSION, "show vn version", 1, NULL},
	{ HELP, "show this help menu", 1, NULL}
};

#define HTSIZE (sizeof(Helptab)/sizeof(struct HELPTAB))


#ifdef amiga
extern char pr_buf[];
extern ttputc ();
#endif

#define HHLINES 5	/* lines (CRs + 1) contained in HELP_HEAD */
/*
	help from main screen
*/
help ()
{
	int i,lcount,lim;
	char *hs;
	char c;

	term_set (ERASE);
	lim = L_allow + RECBIAS - 2;
#ifdef amiga
	sprintf(pr_buf,"%s\n","[...] = effect of optional number preceding command\n");
	tputs(pr_buf,1,ttputc);
	sprintf(pr_buf,"%s\n","pipes are specified by filenames beginning with |\n");
	tputs(pr_buf,1,ttputc);
	sprintf(pr_buf,"%s\n","articles specified as a list of numbers, title search string, or\n");
	tputs(pr_buf,1,ttputc);
	sprintf(pr_buf,"%s\n","	* to specify marked articles.  ! may be used to negate any\n");
	tputs(pr_buf,1,ttputc);
#else
	printf("%s\n","[...] = effect of optional number preceding command\n");
	printf("%s\n","pipes are specified by filenames beginning with |\n");
	printf("%s\n","articles specified as a list of numbers, title search string, or\n");
	printf("%s\n","	* to specify marked articles.  ! may be used to negate any\n");
#endif
	lcount = HHLINES;
	for (i=0; i < HTSIZE; ++i)
	{
		if (Digest && !(Helptab[i].dig))
			continue;
		if (Hookfunc != NULL && (*Hookfunc)(Helptab[i].cmd,0,0) >= 0)
			continue;
		++lcount;
		if (Digest && Helptab[i].amsg != NULL)
			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].amsg);
		else
			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].msg);
		if (lcount >= lim)
		{
#ifdef amiga
			sprintf (pr_buf,"\n%s",Contstr);
			tputs(pr_buf,1,ttputc);
#else
			printf ("\n%s",Contstr);
#endif
			getnoctl ();
			term_set (MOVE,0,lim+1);
			term_set (ZAP,0,strlen(Contstr));
			term_set (MOVE,0,lim-1);
			putchar ('\n');
			lcount = 0;
		}
	}
	if (Hookhelp != NULL)
	{
		for (hs=(*Hookhelp)(0,1,&c);
				hs != NULL; hs = (*Hookhelp)(0,0,&c))
		{
			++lcount;
			h_print (Cxptoi[c],hs);
			if (lcount >= lim)
			{
#ifdef amiga
				sprintf (pr_buf,"\n%s",Contstr);
				tputs(pr_buf,1,ttputc);
#else
				printf ("\n%s",Contstr);
#endif
				getnoctl ();
				term_set (MOVE,0,lim+1);
				term_set (ZAP,0,strlen(Contstr));
				term_set (MOVE,0,lim-1);
				putchar ('\n');
				lcount = 0;
			}
		}
	}
	if (lcount > 0)
	{
#ifdef amiga
		sprintf (pr_buf,"\n%s",Contstr);
		tputs(pr_buf,1,ttputc);
#else
		printf ("\n%s",Contstr);
#endif
		getnoctl ();
	}
}

/*
	help from reader
*/
help_rd()
{
	char *hs;
	char c;

#ifdef amiga
	sprintf(pr_buf,"\n");	/* "confused" tab expansion on first line */
	tputs(pr_buf,1,ttputc);
#else
	printf("\n");	/* "confused" tab expansion on first line */
#endif

	hr_print (Cxrtoi[PG_NEXT],HPG_NEXT);
	hr_print (Cxrtoi[PG_QUIT],HPG_QUIT);
	hr_print (Cxrtoi[PG_FLIP],HPG_FLIP);
	hr_print (Cxrtoi[PG_REWIND],HPG_REWIND);
	hr_print (Cxrtoi[PG_WIND],HPG_WIND);
	hr_print (Cxrtoi[PG_SEARCH],HPG_SEARCH);
	hr_print (Cxrtoi[PG_STEP],HPG_STEP);
	hr_print (Cxrtoi[PG_REPLY],HPG_REPLY);
	hr_print (Cxrtoi[PG_FOLLOW],HPG_FOLLOW);
	hr_print (Cxrtoi[SAVE],HPG_SAVE);
	hr_print (Cxrtoi[PRINT],HPG_PRINT);
	hr_print (Cxrtoi[SETROT],HPG_ROT);
	hr_print (Cxrtoi[HEADTOG],HPG_HEAD);
	hr_print (Cxrtoi[PG_HELP],HPG_HELP);
	if (Hookhelp != NULL)
	{
		for (hs=(*Hookhelp)(1,1,&c);
				hs != NULL; hs = (*Hookhelp)(1,0,&c))
			h_print (Cxrtoi[c],hs);
	}
#ifdef amiga
	sprintf (pr_buf,"%s\n",HPG_DEF);
	tputs(pr_buf,1,ttputc);
#else
	printf ("%s\n",HPG_DEF);
#endif
}

hr_print(c,msg)
char c;
char *msg;
{
	if (Hookfunc == NULL || (*Hookfunc)(c,1,0) < 0)
		h_print(c,msg);
}

srch_help(c,dig)
char c;
int *dig;
{
	int i;

	for (i=0; i < HTSIZE; ++i)
		if (Helptab[i].cmd == c)
			break;
	if (i < HTSIZE)
	{
		*dig = Helptab[i].dig;
		return (0);
	}
	return(-1);
}

/*
	h_print prints a character and a legend for a help menu.
*/
static
h_print(c,s)
char c,*s;
{
	if (strlen(s) > (C_allow - 14))
		s [C_allow - 14] = '\0';
	if (c > ' ' && c != '\177') {
#ifdef amiga
		sprintf (pr_buf,"	 %c - %s\n",c,s);
		tputs(pr_buf,1,ttputc);
#else
		printf ("	 %c - %s\n",c,s);
#endif
	} else
	{
		switch (c)
		{
		case '\177':
#ifdef amiga
			sprintf (pr_buf,"  <delete> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("  <delete> - %s\n",s);  
#endif
			break;
		case '\040':
#ifdef amiga
			sprintf (pr_buf,"   <space> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("   <space> - %s\n",s);  
#endif
			break;
		case '\033':
#ifdef amiga
			sprintf (pr_buf,"  <escape> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("  <escape> - %s\n",s);  
#endif
			break;
		case '\n':
#ifdef amiga
			sprintf (pr_buf,"  <return> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("  <return> - %s\n",s);  
#endif
			break;
		case '\t':
#ifdef amiga
			sprintf (pr_buf,"     <tab> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("     <tab> - %s\n",s);  
#endif
			break;
		case '\b':
#ifdef amiga
			sprintf (pr_buf," <back sp> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf (" <back sp> - %s\n",s);  
#endif
			break;
		case '\f':
#ifdef amiga
			sprintf (pr_buf,"<formfeed> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("<formfeed> - %s\n",s);  
#endif
			break;
		case '\07':
#ifdef amiga
			sprintf (pr_buf,"    <bell> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("    <bell> - %s\n",s);  
#endif
			break;
		case '\0':
#ifdef amiga
			sprintf (pr_buf,"    <null> - %s\n",s);  
			tputs(pr_buf,1,ttputc);
#else
			printf ("    <null> - %s\n",s);  
#endif
			break;
		default:
			if (c < '\033')
			{
				c += 'a' - 1;
#ifdef amiga
				sprintf(pr_buf," control-%c - %s\n",c,s);
				tputs(pr_buf,1,ttputc);
#else
				printf(" control-%c - %s\n",c,s);
#endif
			}
			else {
#ifdef amiga
				printf(pr_buf,"       %c0%o - %s\n",'\\',(int) c,s);
				tputs(pr_buf,1,ttputc);
#else
				printf("       %c0%o - %s\n",'\\',(int) c,s);
#endif
			}
			break;
		}
	}
}
