/* input.c - read a line of input
 */

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

int t_quit_pos = 0;			 /* position at which we quit */

extern int menuview_exitup;

void t_disp_string(char *, char *, int, int);


/* Display "prompt" on the bottom line, and read up to "maxlen" bytes into
 * "buffer".
 *
 * Returns 0 if a line was input, 1 if it was aborted by t_quit_input - in
 * which case the current position is stored, and when called again with
 * t_quit_input == 1, will restore the previous position (and also clear
 * t_quit_input). Kludge kludge.
 *
 * t_quit_input is automatically set if ^L is pressed.
 *
 * Returns 2 if [ESC] was pressed.
 */
int t_input(char *prompt, char *buffer, int maxlen)
{
	char finished = 0;
	char redraw_now = 1;
	int c, i, j;

	t_disp_string(prompt, buffer, maxlen, -1);

	i = strlen(buffer);

	if (t_quit_input) {
		i = t_quit_pos;
		t_quit_input = 0;
	}

	do {

		if (redraw_now) {
			redraw_now = 0;
			t_disp_string(prompt, 0, -1, -1);
			t_disp_string(prompt, buffer, 0, i);
		}

		c = t_getchar(10);

		bbs_hook(HOOK_KEY_PRESSED, 0, &c);

		if (menuview_exitup)
			c = 10;		    /* allow autologout */

		switch (c) {
		case KEY_NONE:
		case KEY_UNKNOWN:
		case KEY_NPAGE:
		case KEY_PPAGE:
		case KEY_DOWN:
		case 9:
		case KEY_UP:
			break;

		case 2:		    /* ^B */
		case KEY_LEFT:
			i--;
			if (i < 0)
				i = 0;
			else
				t_disp_string(prompt, buffer, 0, i);
			break;

		case 6:		    /* ^F */
		case KEY_RIGHT:
			i++;
			if (i > strlen(buffer)) {
				i = strlen(buffer);
			} else {
				t_disp_string(prompt, buffer, -1, i);
			}
			break;

		case 1:		    /* ^A */
		case KEY_HOME:
			i = 0;
			t_disp_string(prompt, buffer, -1, i);
			break;

		case 5:		    /* ^E */
		case KEY_END:
			i = strlen(buffer);
			t_disp_string(prompt, buffer, -1, i);
			break;

		case 8:		    /* ^H */
		case 127:
			i--;
			if (i < 0) {
				i = 0;
			} else {
				j = i;
				do {
					buffer[j] = buffer[j + 1];
					j++;
				} while (buffer[j] != 0);
			}
			t_disp_string(prompt, buffer, i, i);
			break;

		case 4:		    /* ^D */
		case KEY_DC:
			j = i;
			do {
				buffer[j] = buffer[j + 1];
				j++;
			} while (buffer[j] != 0);
			t_disp_string(prompt, buffer, i, i);
			break;

		case -27:
		case 27:
			finished = 3;
			break;
		case 10:
			finished = 1;
			break;

		case 12:
			redraw_now = 1;
			t_quit_input = 1;
			break;		    /* ^L */

		default:
			if (c > 128)
				c -= 128;
			j = strlen(buffer);
			if ((j < (maxlen - 1)) && (c > 31) && (c < 256)) {
				while (j >= i) {
					buffer[j + 1] = buffer[j];
					j--;
				}
				buffer[i] = c;
				t_disp_string(prompt, buffer, i, i + 1);
				i++;
			}
			break;
		}

		if (t_quit_input) {
			t_quit_pos = i;
			finished = 2;
		}

	} while (!finished);

	if (finished == 3)
		return (2);
	if (finished == 2)
		return (1);
	return (0);
}


/* Display input string.
 */
void t_disp_string(char *prompt, char *buffer, int maxlen, int pos)
{
	static int ml, xpos, leftpos, absleft;
	int x, a, b;
	int maxx;

	if (pos < 0) {
		t_goto(0, t_rows - 1);
		t_clrtoeol();
		t_goto(0, t_rows - 1);
		t_write(prompt);
		absleft = strlen(prompt);
		if (buffer) {
			ml = maxlen;
			xpos = 0;
			leftpos = 0;
		}
		return;
	}

	maxx = t_cols - 1 - absleft;

	while ((xpos = pos - leftpos) < 0) {
		leftpos -= 20;
		maxlen = 0;
	}

	while ((xpos = pos - leftpos) >= maxx) {
		leftpos += 20;
		maxlen = 0;
	}

	if (leftpos < 0) {
		leftpos = 0;
		maxlen = 0;
	}

	if (maxlen >= 0) {
		x = maxlen - leftpos;
		a = maxlen;
		if (x < 0) {
			a = maxlen - x;
			x = 0;
		}
		t_goto(absleft + x, t_rows - 1);
		t_clrtoeol();
		t_goto(absleft + x, t_rows - 1);
		b = maxx - x;
		x = 0;
		while ((x < b) && (buffer[x + a] != 0))
			x++;
		write(STDOUT_FILENO, buffer + a, x);
	}

	t_goto(absleft + xpos, t_rows - 1);
}

/* EOF */
