/* getch.c - read a character from stdin
 */

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include "terminal.h"


/* Read a character from stdin, translating arrow keys etc as defined in
 * "terminal.h", returning the key pressed or KEY_NONE if no data was waiting.
 * If -27 is returned, then ESCAPE was pressed, and another key is waiting.
 */
int t_getch(void)
{
	fd_set fds;
	struct timeval tv;
	int c, i, status, fin;
	static unsigned char buffer[16];
	static unsigned char b2[2];
	static int e = 0;

	status = 0;

	if (t_clearscreen) {		    /* clear-screen flag set? */
		t_clearscreen = 0;
		return (12);		    /* yes - return ^L */
	}

	if (e) {			    /* character from [ESC] before? */
		c = e;
		e = 0;
		return (c);
	}

	FD_ZERO(&fds);
	FD_SET(STDIN_FILENO, &fds);
	tv.tv_sec = 0;
	tv.tv_usec = 0;

	if (select(STDIN_FILENO + 1, &fds, 0, 0, &tv) <= 0)
		return (KEY_NONE);

	buffer[0] = 0;
	read(STDIN_FILENO, buffer, 1);
	c = buffer[0];

	if (c != 27)
		return (c);

	tv.tv_sec = 0;
	tv.tv_usec = 500000;		    /* 0.5 sec */

	FD_ZERO(&fds);
	FD_SET(STDIN_FILENO, &fds);

	if (!select(STDIN_FILENO + 1, &fds, 0, 0, &tv))
		return (27);

	buffer[0] = 0;
	i = 0;
	fin = 0;

	do {
		c = read(STDIN_FILENO, b2, 1);
		if (c > 0) {
			c = b2[0];
			if (c > 31) {
				buffer[i++] = c;
				buffer[i] = 0;
			}
			if (isalpha(c))
				fin = 1;
			if (c == 'O')
				fin = 0;
			if (fin == 0) {
				tv.tv_sec = 0;
				tv.tv_usec = 500000;
				FD_ZERO(&fds);
				FD_SET(STDIN_FILENO, &fds);
				status =
				    select(STDIN_FILENO + 1, &fds, 0, 0,
					   &tv);
				if (c == '~')
					status = 0;
			}
		} else {
			status = 0;
		}
	} while ((fin == 0) && (status == 1) && (i < 15));

	if (strcmp(buffer, "[A") == 0)
		return (KEY_UP);
	if (strcmp(buffer, "[B") == 0)
		return (KEY_DOWN);
	if (strcmp(buffer, "[C") == 0)
		return (KEY_RIGHT);
	if (strcmp(buffer, "[D") == 0)
		return (KEY_LEFT);
	if (strcmp(buffer, "[F") == 0)
		return (KEY_END);
	if (strcmp(buffer, "[H") == 0)
		return (KEY_HOME);
	if (strcmp(buffer, "OA") == 0)
		return (KEY_UP);
	if (strcmp(buffer, "OB") == 0)
		return (KEY_DOWN);
	if (strcmp(buffer, "OC") == 0)
		return (KEY_RIGHT);
	if (strcmp(buffer, "OD") == 0)
		return (KEY_LEFT);
	if (strcmp(buffer, "OF") == 0)
		return (KEY_END);
	if (strcmp(buffer, "OH") == 0)
		return (KEY_HOME);
	if (strcmp(buffer, "[5~") == 0)
		return (KEY_PPAGE);
	if (strcmp(buffer, "[6~") == 0)
		return (KEY_NPAGE);
	if (strcmp(buffer, "[1~") == 0)
		return (KEY_HOME);
	if (strcmp(buffer, "[4~") == 0)
		return (KEY_END);
	if (strcmp(buffer, "[3~") == 0)
		return (KEY_DC);

	if (isalpha(buffer[0])) {	    /* not a code - probably just a fast typist */
		e = buffer[0];
		return (-27);
	}

	return (KEY_UNKNOWN);
}

/* EOF */
