/* vi:ts=4:sw=4
 *
 * VIM - Vi IMproved
 *
 * Code Contributions By:	Bram Moolenaar			mool@oce.nl
 *							Tim Thompson			twitch!tjt
 *							Tony Andrews			onecom!wldrdg!tony 
 *							G. R. (Fred) Walter		watmath!watcgl!grwalter 
 */

/*
 * help.c: display help from the vim.hlp file
 */

#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "param.h"
#ifdef JP
#include "jp.h"
#endif

static long helpfilepos;		/* position in help file */
static FILE *helpfd;			/* file descriptor of help file */

#define MAXSCREENS 52			/* one screen for a-z and A-Z */

	void
help()
{
	int		c;
	int		eof;
	int		screens;
	int		i;
	long	filepos[MAXSCREENS];	/* seek position for each screen */
	int		screennr;			/* screen number; index == 0, 'c' == 1, 'd' == 2, etc */
#ifdef MSDOS
	char	*fnamep;
#endif

/*
 * try to open the file specified by the "helpfile" option
 */
	if ((helpfd = fopen(p_hf, READBIN)) == NULL)
	{
#ifdef MSDOS
	/*
	 * for MSDOS: try the DOS search path
     */
		fnamep = searchpath("vim.hlp");
		if (fnamep == NULL || (helpfd = fopen(fnamep, READBIN)) == NULL)
		{
			smsg("Sorry, help file \"%s\" and \"vim.hlp\" not found", p_hf);
			return;
		}
#else
		smsg("Sorry, help file \"%s\" not found", p_hf);
		return;
#endif
	}
	helpfilepos = 0;
	screennr = 0;
	for (i = 0; i < MAXSCREENS; ++i)
		filepos[i] = 0;
	State = HELP;
	for (;;)
	{
		screens = redrawhelp();				/* show one or more screens */
		eof = (screens < 0);
		if (!eof && screennr + screens < MAXSCREENS)
			filepos[screennr + screens] = ftell(helpfd);

		if ((c = vgetc()) == '\n' || c == '\r' || c == Ctrl('C') || c == ESC)
			break;

		if (c == ' ' ||
#if defined(MSDOS) && !defined(DOSGEN)
				(c == K_NUL && vpeekc() == 'Q') ||	/* page down */
#endif
				c == Ctrl('F'))						/* one screen forwards */
		{
			if (screennr < MAXSCREENS && !eof)
				++screennr;
		}
		else if (c == 'a')					/* go to first screen */
			screennr = 0;
		else if (c == 'b' ||
#if defined(MSDOS) && !defined(DOSGEN)
				(c == K_NUL && vpeekc() == 'I') ||	/* page up */
#endif
				c == Ctrl('B'))					/* go one screen backwards */
		{
			if (screennr > 0)
				--screennr;
		}
		else if (isalpha(c))				/* go to specified screen */
		{
			if (isupper(c))
				c = c - 'A' + 'z' + 1;		/* 'A' comes after 'z' */
			screennr = c - 'b';
		}
#if defined(MSDOS) && !defined(DOSGEN)
		if (c == K_NUL)
			c = vgetc();
#endif
		for (i = screennr; i > 0; --i)
			if (filepos[i])
				break;
		fseek(helpfd, filepos[i], 0);
		while (i < screennr)
		{
			while ((c = getc(helpfd)) != '\f' && c != -1)
				;
			if (c == -1)
				break;
			filepos[++i] = ftell(helpfd);	/* store the position just after the '\f' */
		}
		screennr = i;						/* required when end of file reached */
		helpfilepos = filepos[screennr];
	}
	State = NORMAL;
	script_winsize_pp();
	fclose(helpfd);
	updateScreen(CLEAR);
}

	int
redrawhelp()
{
	int nextc = -1;
	int col;
	int	line = 0;
	int	screens = 1;
	char *cp;
#ifdef JP
	int kanji = FALSE;
	static char *kin, *kout, kcode = NUL;
#ifdef ONEW
	char *Onew_version();
#endif

	if (kcode != JP_DISP)
	{
		kin = kanjiin(JP_DISP);
		kout= kanjiout(JP_DISP);
		kcode = JP_DISP;
	}
#endif

	fseek(helpfd, helpfilepos, 0);
	outstr(T_ED);
	windgoto(0,0);
	while(!feof(helpfd))
	{
#ifdef JP
		char tmp[IOSIZE];
		int len;
#endif
		cp = IObuff;
		while( (nextc = getc(helpfd)) != -1 )
		{
			*cp++ = nextc;
			if (nextc == '\n' || nextc == '\f')
				break;
		}
		*cp = NUL;
#ifdef JP
		len = kanjiconvsfrom(IObuff, cp - IObuff, tmp, IOSIZE, NULL,
#ifdef MSDOS
																JP_SANY,
#else
																JP_ANY,
#endif
																NULL);
		tmp[len] = NUL;
		for(cp = tmp; *cp; cp++)
#else /* JP */
		for(cp = IObuff; *cp; cp++)
#endif /* JP */
		{
			if ((nextc = *cp) == Ctrl('B'))		/* begin of invert */
				outstr(T_TI);
			else if (nextc == Ctrl('E'))		/* end of invert */
				outstr(T_TP);
			else if (nextc == '\f')				/* start of next screen */
			{
				if (line < Rows - 24)
				{
					++screens;
/*					outchar('\n');
					++line;
*/
					windgoto(++line, 0);
					col = 0;
				}
				else
					goto nextscreen;
			}
#ifdef DOSGEN
			else if (nextc == '\t')
			{
				do
					outchar(' ');
				while(++col % 8);
			}
#endif
#ifdef JP
			else if (IsKanji(nextc))
			{
				if (!kanji)
				{
					if (kin) outstr(kin);
					kanji = TRUE;
				}
				kanjito(cp, cp + 1, JP_DISP);
				outchar(*cp);
				outchar(* ++cp);
				col += 2;
			}
#endif
			else
			{
#ifdef JP
				if (kanji)
				{
					if (kout) outstr(kout);
					kanji = FALSE;
				}
#endif
				if (nextc == '\n')
				{
					windgoto(++line, 0);
					col = 0;
				}
				else
				{
					outchar((char) nextc);
					col++;
				}
			}
		}
	}
nextscreen:

#ifdef JP
	if (kanji && kout) outstr(kout);

# ifdef ONEW
	sscanf(Onew_version(), "%s", IObuff + 80);
	sprintf(IObuff, "%s+%s", JpVersion, IObuff + 80);
# else
	sprintf(IObuff, "%s/%s", JpVersion, Version);
# endif
	windgoto(0, (int)(Columns - strlen(IObuff) - 1));
	outstrn(IObuff);
#else
	windgoto(0, (int)(Columns - strlen(Version) - 1));
	outstrn(Version);
#endif
	col = (int)Columns - 52;
	if (col < 0)
		col = 0;
	windgoto((int)Rows - 1, col);
	outstrn("<space = next; return = quit; a = index; b = back>");
	return (nextc == -1 ? -1 : screens);
}


syntax highlighted by Code2HTML, v. 0.9.1