/* 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(""); return (nextc == -1 ? -1 : screens); }