176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* -*- c -*- ------------------------------------------------------------- *
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Copyright 2004-2005 Murali Krishnan Ganapathy - All Rights Reserved
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   This program is free software; you can redistribute it and/or modify
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   it under the terms of the GNU General Public License as published by
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Boston MA 02111-1307, USA; either version 2 of the License, or
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   (at your option) any later version; incorporated herein by reference.
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "help.h"
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h>
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "string.h"
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "com32io.h"
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/loadfile.h>	// to read entire file into memory
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint nc, nr; // Number of columns/rows of the screen
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanchar helpbasedir[HELPDIRLEN];	// name of help directory limited to HELPDIRLEN
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// Find the occurence of the count'th \n in buffer (or NULL) if not found
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic char *findline(char *buffer, int count)
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int ctr;
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char *p = buffer - 1;
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (count < 1)
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return buffer;
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (ctr = 0; ctr < count; ctr++) {
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	p = strchr(p + 1, '\n');
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (p == NULL)
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    return NULL;
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return p;
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// return the number of lines in buffer
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int countlines(char *buffer)
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int ans;
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const char *p;
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    p = buffer - 1;
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ans = 1;
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (p) {
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	p = strchr(p + 1, '\n');
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ans++;
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return ans;
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// Print numlines of text starting from buf
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void printtext(char *buf, int from)
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char *f, *t;
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int nlines, i;
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    // clear window to print
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    nlines = nr - HELP_BODY_ROW - HELP_BOTTOM_MARGIN - 1;
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    f = findline(buf, from);
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!f)
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return;			// nothing to print
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (*f == '\n')
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	f++;			// start of from+1st line
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    t = f;
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (i = 0; i < nlines; i++) {
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        gotoxy(HELP_BODY_ROW + i, HELP_LEFT_MARGIN);
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        clear_end_of_line();
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        putchar(SO);
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        gotoxy(HELP_BODY_ROW + i, nc - 1);
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        putch(LEFT_BORDER, 0x07);
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        putchar(SI);
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        gotoxy(HELP_BODY_ROW + i, HELP_LEFT_MARGIN);
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        while (*t != '\n') {
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (*t == '\0')
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return;
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            putchar(*t);
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            t++;
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        putchar('\n');
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        t++;
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid showhelp(const char *filename)
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char ph;
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char *title, *text;
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    union {
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char *buffer;
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	void *vbuf;
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } buf;			// This is to avoild type-punning issues
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char line[512];
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    size_t size;
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int scan;
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int rv, numlines, curr_line;
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (getscreensize(1, &nr, &nc)) {
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* Unknown screen size? */
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        nc = 80;
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        nr = 24;
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ph = nr - HELP_BODY_ROW;
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cls();
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Turn autowrap off, to avoid scrolling the menu */
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    printf(CSI "?7l");
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (filename == NULL) {	// print file contents
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        strcpy(line, "Filename not given");
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto puke;
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rv = loadfile(filename, (void **)&buf.vbuf, &size);	// load entire file into memory
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (rv < 0) {		// Error reading file or no such file
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        sprintf(line, "Error reading file or file not found\n file=%s", filename);
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        goto puke;
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    title = buf.buffer;
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    text = findline(title, 1);	// end of first line
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    *text++ = '\0';		// end the title string and increment text
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    // Now we have a file just print it.
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    numlines = countlines(text);
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    curr_line = 0;
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    scan = KEY_ESC + 1;		// anything except ESCAPE
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* top, left, bottom, right, attr */
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    drawbox(0, 0, nr - 1, nc - 1, 0x07);
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (scan != KEY_ESC) {
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Title */
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    gotoxy(1, (nc - strlen(title)) / 2);
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fputs(title, stdout);
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    drawhorizline(2, HELP_LEFT_MARGIN - 1, nc - HELP_RIGHT_MARGIN, 0x07, 0);	// dumb==0
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Text */
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	printtext(text, curr_line);
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    gotoxy(HELP_BODY_ROW - 1, nc - HELP_RIGHT_MARGIN);
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (curr_line > 0)
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    putchar(HELP_MORE_ABOVE);
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	else
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    putchar(' ');
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	gotoxy(nr - HELP_BOTTOM_MARGIN - 1, nc - HELP_RIGHT_MARGIN);
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (curr_line < numlines - ph)
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    putchar(HELP_MORE_BELOW);
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	else
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    putchar(' ');
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    scan = get_key(stdout, 0); // wait for user keypress
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	switch (scan) {
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case KEY_HOME:
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line = 0;
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case KEY_END:
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line = numlines;
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case KEY_UP:
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line--;
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case KEY_DOWN:
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line++;
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case KEY_PGUP:
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line -= ph;
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case KEY_PGDN:
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line += ph;
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	default:
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (curr_line > numlines - ph)
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line = numlines - ph;
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (curr_line < 0)
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    curr_line = 0;
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanout:
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cls();
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpuke:
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    gotoxy(HELP_BODY_ROW, HELP_LEFT_MARGIN);
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fputs(line, stdout);
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (1) {
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        scan = get_key(stdin, 0);
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (scan == KEY_ESC)
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            break;
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    goto out;
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid runhelp(const char *filename)
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char fullname[HELPDIRLEN + 16];
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cls();
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cursoroff();
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (helpbasedir[0] != 0) {
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	strcpy(fullname, helpbasedir);
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	strcat(fullname, "/");
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	strcat(fullname, filename);
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	showhelp(fullname);
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	showhelp(filename);	// Assume filename is absolute
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid runhelpsystem(unsigned int helpid)
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char filename[15];
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    sprintf(filename, "hlp%05d.txt", helpid);
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    runhelp(filename);
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid init_help(const char *helpdir)
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (helpdir != NULL)
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	strcpy(helpbasedir, helpdir);
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    else
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	helpbasedir[0] = 0;
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid close_help(void)
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
232