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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "hook.h"
#include "terminal.h"
#include "viewfile.h"
#include "viewmenu.h"

int rf_redraw = 0;
int rf_viewing_messages = 0;


/* Read the given file.
 *
 * Returns 0 if returned after reaching end of file, 1 if not (eg [Q]), 2 if
 * the file could not be found or the parameters were invalid.
 */
int read_file(struct LDB *ldb_entry, char *title, unsigned long flags,
	      char *commentfile)
{
	struct RF_Data data;
	char action[1024];
	char keypath[64];
	struct stat sb;
	char *ptr;
	char *a;
	int c, x;

	if (!ldb_entry)
		return (2);

	if (getenv("BBS_SCANONLY"))
		return 0;

	ptr = 0;
	action[0] = 0;
	bbs_hook(HOOK_GET_ACTION, &ptr, 0);
	if (ptr)
		strncpy(action, ptr, sizeof(action) - 1);
	ptr = 0;
	keypath[0] = 0;
	bbs_hook(HOOK_GET_KEYPATH, &ptr, 0);
	if (ptr)
		strncpy(keypath, ptr, sizeof(keypath) - 1);

	if (flags & MENU_STATUS_READONLY) { /* readonly sanity check */
		flags ^= (flags & MENU_STATUS_ADD);
		flags ^= (flags & MENU_STATUS_DELETE);
		flags ^= (flags & MENU_STATUS_EDIT);
		flags |= MENU_STATUS_BARDELETE;
	}

	if (stat(ldb_entry->realname, &sb) != 0) {	/* try to stat() file */
		return (2);
	}

	if (!S_ISREG(sb.st_mode)) {	    /* not a regular file */
		return (2);
	}

	data.fd = open(ldb_entry->realname, O_RDONLY);
	if (data.fd < 0)
		return (2);

	data.title = title;
	data.ldb_entry = ldb_entry;
	data.line_pos = 0;
	data.aborted = 0;
	data.done = 0;
	data.search_buf[0] = 0;
	data.last_scanned = 0;
	data.commentfile = commentfile;
	data.flags = flags;

	rf_redraw = 0;

	rf_get_line_positions(&data);	    /* scan for line positions */
	if (!rf_get_current_line(&data))    /* find current line */
		rf_redraw_screen(&data);

	do {

		if (menuview_exitup != 0) {
			data.aborted = 1;
			continue;
		}

		c = t_getchar(1);	    /* read a keypress */

		if (c == ' ') {		    /* check BBS_SPACE_EXIT */
			a = getenv("BBS_SPACE_EXIT");
			if (!a)
				x = 0;
			else
				x = atoi(a);
			if (x)
				c = 'C';    /* [SPACE] -> [C] */
		}

		t_checksize();		    /* check for terminal resize */

		bbs_hook(HOOK_KEY_PRESSED, 0, &c);

		if (rf_get_current_line(&data))
			rf_redraw = 0;	    /* check for file change */

		if (rf_redraw) {
			bbs_hook(HOOK_SET_ACTION, 0, action);
			bbs_hook(HOOK_SET_KEYPATH, keypath, 0);
			rf_redraw_screen(&data);
			rf_redraw = 0;
		}

		switch (c) {

		case 12:
			rf_redraw = 1;
			break;

		case 'q':
		case 'Q':
			data.aborted = 1;
			break;

		case ' ':
		case KEY_NPAGE:
		case KEY_RIGHT:
			rf_scroll_forward(&data, t_rows - 2);
			break;

		case 'c':
		case 'C':
			if (rf_percent(&data) == 100)
				data.done = 1;
			rf_scroll_forward(&data, t_rows - 2);
			break;

		case KEY_DOWN:
			rf_scroll_forward(&data, 1);
			break;

		case 10:
		case 13:
			if (rf_percent(&data) == 100)
				data.done = 1;
			rf_scroll_forward(&data, 1);
			break;

		case KEY_UP:
			rf_scroll_back(&data, 1);
			break;

		case KEY_PPAGE:
		case KEY_LEFT:
		case '-':
		case 'b':
		case 'B':
			rf_scroll_back(&data, t_rows - 2);
			break;

		case 1:		    /* ^A */
		case KEY_HOME:
		case '0':
			rf_goto_top(&data);
			break;

		case KEY_END:
		case 5:		    /* ^E */
		case '$':
		case 'z':
		case 'Z':
			rf_goto_end(&data);
			break;

		case 'a':
		case 'A':
			rf_add_to_file(&data, 0);
			break;

		case 'e':
		case 'E':
			if (!bbs_hook(HOOK_IS_EXTERNAL, 0, 0))
				rf_add_to_file(&data, 1);
			break;

		case '.':
			rf_edit_file(&data);
			break;

		case 'G':
		case 'g':
			rf_goto(&data);
			break;

		case '/':
			rf_search(&data);
			break;

		case '\\':
			rf_search_backwards(&data);
			break;

		case 'i':
		case 'I':
			rf_view_index(&data);
			break;

		case '[':
			rf_skipedit_back(&data);
			break;
		case ']':
			rf_skipedit_forward(&data);
			break;

		case 'K':
		case 'k':
			rf_entry_copy(&data);
			break;

		case 'M':
		case 'm':
			rf_mail_file(&data);
			break;

		case '?':
			rf_view_help(&data);
			break;

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

		default:
			bbs_hook(HOOK_KEY_FILE, &data, &c);
			break;
		}

	} while ((!data.done) && (!data.aborted));

	data.ldb_entry->at_end =
	    (data.ldb_entry->current_line >= data.num_lines) ? 1 : 0;

	rf_wipe_footer(&data);

	close(data.fd);
	if (data.line_pos)
		free(data.line_pos);

	return (data.aborted);
}

/* EOF */
