/* keys.c - central menu file reading function
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif				/* HAVE_CONFIG_H */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include "hook.h"
#include "terminal.h"
#include "viewmenu.h"


int menuview_exitup = 0;
char **menuview_files = 0;
int menuview_depth = 0;
long menuview_listed_status = 0;
int menuview_abort = 0;
extern time_t scan_last_update;


/* Read the given menu "file", using "ldbfile" as an LDB file and "keypath"
 * as the current keypath. The menu title is "title". "flags" should be 0.
 *
 * Returns 0 if returned because of [RET], if [Q] or [ESC][Q], 2 if the file
 * could not be found or the parameters were invalid. 3 is returned if
 * [SPACE] caused the return.
 */
int read_menu(char *file, char *ldbfile, char *keypath, char *title,
	      int flags)
{
	char okp[MENUVIEW_KEYPATHLEN + 1];
	char *a;
	menudata_t data;
	int c, i, j, e;
	int editable = 0;
	int hidetitle = 0;
	struct stat sb;
	int scanonly = 0;
	char first = 1;

	if (getenv("BBS_SCANONLY")) {
		scanonly = 1;
		flags = flags | MENUFLAG_SCAN;
	}

	if (menuview_depth < 0)
		menuview_depth = 0;
	if (menuview_depth > MENUVIEW_KEYPATHLEN)
		menuview_depth = MENUVIEW_KEYPATHLEN;

	if (!menuview_files) {
		menuview_files =
		    malloc(sizeof(char *) * (MENUVIEW_KEYPATHLEN + 1));
	}

	if (flags & MENUFLAG_HIDETITLE)
		hidetitle = 1;

	if (!file)
		return (MENUQUIT_ERROR);

	data = calloc(1, sizeof(*data));
	if (!data)
		return (MENUQUIT_ERROR);

	a = getenv("MONO_KEYPATH");
	if (a)
		strncpy(okp, a, MENUVIEW_KEYPATHLEN);
	else
		okp[0] = 0;
	okp[MENUVIEW_KEYPATHLEN] = 0;

	data->flags = flags;
	data->menu = 0;
	data->ldbfile = ldbfile;
	data->title_lines = 0;
	data->offset = 0;
	data->quit = 0;
	data->fd = -1;
	data->status = -1;
	data->last_resize = 0;
	if (flags & MENUFLAG_LISTED)
		data->status = menuview_listed_status;

	strncpy(data->file, ldb_filename(file), MENUVIEW_BUFLEN);
	strncpy(data->keypath, (keypath) ? keypath : "",
		MENUVIEW_KEYPATHLEN);
	strncpy(data->title, (title) ? title : "", MENUVIEW_BUFLEN);

	if (flags == 0)
		strcpy(data->title, "Main Menu");

	data->file[MENUVIEW_BUFLEN - 4] = 0;
	data->keypath[MENUVIEW_BUFLEN] = 0;
	data->title[MENUVIEW_BUFLEN] = 0;

	if (menuview_files) {		    /* deal with recursive menus */
		for (i = 0; i < menuview_depth; i++) {
			if (!strcmp(menuview_files[i], data->file)) {
				menuview_exitup = i + 1;
				menuview_files[menuview_depth] = 0;
				free(data);
				return (0);
			}
		}
	}

	setenv("MONO_KEYPATH", data->keypath, 1);

	if (menuview_loadmenu(data)) {
		free(data);
		return (MENUQUIT_ERROR);
	}

	if (flags & MENUFLAG_LISTED)
		strcat(data->file, "/.");

	strncpy(data->buf, data->keypath, sizeof(data->buf));

	if (data->menu->viewfile) {
		if (data->menu->viewalways) {
			if (menuview_viewalways
			    (data, data->menu->viewfile, title)) {
				menu_free(data->menu);
				data->menu = 0;
				menuview_files[menuview_depth] = 0;
				free(data);
				return (0);
			}
		} else {
			if (menuview_viewfile
			    (data, data->menu->viewfile, title)) {
				menu_free(data->menu);
				data->menu = 0;
				menuview_files[menuview_depth] = 0;
				free(data);
				return (0);
			}
		}
	}

	menuview_files[menuview_depth] = data->file;
	menuview_depth++;

	if (flags & MENUFLAG_SCAN) {
		data->quit = MENUQUIT_RETURN;
		menuview_scan(data);	    /* submenu scan */
		if (data->quit == MENUQUIT_RETURN)
			data->quit = 0;
	}

	if (flags == 0) {
		bbs_hook(HOOK_CHECK_MSGS, "yes", 0);
		menuview_redraw(data);
		rf_redraw = 0;
		if (data->menu->num_entries < 1)
			data->quit = 3;
	} else
		rf_redraw = 1;

	if (!stat(data->file, &sb) && (sb.st_uid == getuid()))
		editable = 1;

	if ((data->quit == 0) && (!scanonly)) {
		if (hidetitle) {
			bbs_hook(HOOK_SET_ACTION, 0, "");
		} else {
			bbs_hook(HOOK_SET_ACTION, "In ", data->title);
		}
		bbs_hook(HOOK_SET_KEYPATH, data->keypath, 0);
	}

	e = 0;

	do {

		if (editable)
			data->menu->allow_edit = 1;
		if (data->menu->allow_edit)
			editable = 1;

		if (menuview_abort) {
			e = 0;
			data->quit = MENUQUIT_RETURN;
			rf_redraw = 0;
		}

		if ((menuview_exitup < menuview_depth)
		    && (menuview_exitup != 0)) {
			e = 0;
			data->quit = MENUQUIT_RETURN;
		} else
			menuview_exitup = 0;

		if (data->quit != 0)
			continue;

		if (scanonly) {
			c = ' ';
		} else if ((first) && (flags & MENUFLAG_READNOW)) {
			c = t_getch();
		} else {
			c = t_getchar(1);   /* read a keypress */
		}

		if (!scanonly)
			t_checksize();	    /* check for terminal resize */

		first = 0;

		if (!scanonly)
			bbs_hook(HOOK_KEY_PRESSED, 0, &c);

		switch (c) {

		case 12:
			rf_redraw = 1;
			break;

		case 'q':
		case 'Q':
			if ((flags == 0) && (bbs_hook(HOOK_IN_BBS, 0, 0)))
				break;
			data->quit = MENUQUIT_QUIT;
			if (flags != 0)
				e = 1;
			break;

		case 10:
		case 13:
			if (flags != 0) {
				data->quit = MENUQUIT_RETURN;
				e = 1;
			}
			break;

		case '.':
			if (data->menu->allow_edit) {
				menuview_edit(data);
				menuview_wipe_footer(data);
				menuview_footer(data);
			}
			break;

		case ' ':
			if (flags & MENUFLAG_SPECIAL)
				break;
			scan_last_update = 0;
			if (!scanonly)
				bbs_hook(HOOK_SET_ACTION, 0, "Scanning");
			menuview_scan(data);
			if ((flags != 0) && (data->quit != 0)) {
				data->quit = MENUQUIT_SCAN;
			} else
				data->quit = 0;
			rf_redraw = 1;
			break;

		case '+':
			if (data->menu->num_entries + data->title_lines -
			    data->offset >= t_rows) {
				data->offset +=
				    (t_rows - data->title_lines) - 1;
				rf_redraw = 1;
			}
			break;

		case '-':
			if (data->offset > 0) {
				data->offset -=
				    (t_rows - data->title_lines) - 1;
				rf_redraw = 1;
			}
			break;

		case '=':
			if (flags & MENUFLAG_SPECIAL)
				break;
			menuview_setsubs(data);
			menuview_wipe_footer(data);
			menuview_footer(data);
			break;

		case 8:
		case 127:		    /* [BACKSPACE] */
		case KEY_DC:
			if (flags & MENUFLAG_SPECIAL)
				break;
			menuview_wipe_footer(data);
			t_goto(0, t_rows - 1);
			t_centre("\035R *** Updating *** \035r");
			for (i = 0; i < data->menu->num_entries; i++) {
				if (data->menu->menu[i].key == 0)
					continue;
				if (data->menu->menu[i].
				    status & MENU_STATUS_NOLAST)
					continue;
				j = data->menu->menu[i].type;
				if ((j == MENU_ENTRY_COMMENTFILE)
				    || (j == MENU_ENTRY_FORMATTED)
				    || (j == MENU_ENTRY_READONLY)
				    || (j == MENU_ENTRY_UNFORMATTED)
				    || (j == MENU_ENTRY_VTANSI)) {
					menuview_catchup(data,
							 &(data->menu->
							   menu[i]));
				}
			}
			rf_redraw = 1;
			break;

		case 24:		    /* ^X */
			if (!bbs_hook(HOOK_IS_EXTERNAL, data, 0)) {
				menuview_shell(data);
				rf_redraw = 1;
			}
			break;

		case '?':
			menuview_help(data);
			break;

		case -1:
		case 0:
			bbs_hook(HOOK_CHECK_MSGS, "yes", 0);
			break;

		default:
			for (i = 0; (i < data->menu->num_entries)
			     && (toupper(data->menu->menu[i].key) !=
				 toupper(c)); i++);
			if (i < data->menu->num_entries) {
				menuview_action(data,
						&(data->menu->menu[i]));
				setenv("MONO_KEYPATH", data->keypath, 1);
				if (data->quit != MENUQUIT_QUIT)
					data->quit = MENUQUIT_DUMMY;
				if (((menuview_exitup < menuview_depth)
				     && (menuview_exitup != 0))
				    || (menuview_abort)) {
					rf_redraw = 0;
					data->quit = MENUQUIT_QUIT;
				} else
					rf_redraw = 1;
			} else {
				bbs_hook(HOOK_KEY_MENU, data, &c);
			}
			if (flags & MENUFLAG_SPECIAL) {
				first = 1;
				flags |= MENUFLAG_READNOW;
			}
			break;
		}

		if (menuview_abort) {
			e = 0;
			data->quit = MENUQUIT_RETURN;
			rf_redraw = 0;
		}

		if ((menuview_exitup < menuview_depth)
		    && (menuview_exitup != 0)) {
			e = 0;
			data->quit = MENUQUIT_RETURN;
			rf_redraw = 0;
		}

		if (editable)
			data->menu->allow_edit = 1;
		if (data->menu->allow_edit)
			editable = 1;

		if (rf_redraw && (data->quit == 0) && (!scanonly)) {	/* update screen */
			if (hidetitle) {
				bbs_hook(HOOK_SET_ACTION, 0, "");
			} else {
				bbs_hook(HOOK_SET_ACTION, "In ",
					 data->title);
			}
			bbs_hook(HOOK_SET_KEYPATH, data->keypath, 0);
			menuview_redraw(data);
			rf_redraw = 0;
			if (data->menu->num_entries < 1)
				data->quit = 3;
		}

		if (data->quit == MENUQUIT_DUMMY)
			data->quit = 0;

	} while (data->quit == 0);

	if (data->quit != MENUQUIT_SCAN)
		menuview_wipe_footer(data);

	menuview_files[menuview_depth] = 0;

	menu_free(data->menu);
	data->menu = 0;
	for (c = 0; c < data->title_lines; c++) {
		free(data->titleline[c]);
		data->titleline[c] = 0;
	}

	if ((e) && (!scanonly)) {
		t_goto(0, t_rows - 1);
		t_centre("Exit Current Menu");
	}

	c = data->quit - 1;
	menuview_depth--;

	if (okp[0] != 0) {		    /* reset keypath */
		setenv("MONO_KEYPATH", okp, 1);
		if (!scanonly)
			bbs_hook(HOOK_SET_KEYPATH, okp, 0);
	}

	free(data);
	return (c);
}

/* EOF */
