/*  Copyright 1992 John Bovey, University of Kent at Canterbury.
 *
 *  You can do what you like with this source code as long as
 *  you don't try to make money out of it and you include an
 *  unaltered copy of this message (including the copyright).
 */

char xvt_xvt_c_sccsid[] = "@(#)xvt.c	1.2 18/9/92 (UKC)";

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include "rvt.h"
#include "command.h"
#include "xsetup.h"
#include "screen.h"
#include "sbar.h"
#include "token.h"

extern int debugging;
extern char *username;
extern char *nodename;
extern char *rcmd;

static int size_set = 0;	/* flag set once the window size has been set */

/*  Malloc that checks for NULL return.
 */
void *
cmalloc(size)
	int size;
{
	void *s;

	if ((s = (void *)malloc((unsigned int) size)) == NULL)
		abort();
	return (s);
}
/*  Utility function to return a malloced copy of a string.
 */
char *
scopy(str)
	char *str;
{
	char *s;

	if ((s = (char *)malloc(strlen(str) + 1)) == NULL)
		abort();
	strcpy(s, str);
	return (s);
}
/*  Run the command in a subprocess and return a file descriptor for the
 *  master end of the pseudo-teletype pair with the command talking to
 *  the slave.
 */
int
main(int argc, char *argv[])
{
	int i, n, x, y;
	int mode;
	int envc, term_set, iargc;
	char **iargv;
	struct tokenst token;
	char *title;
	char **com_argv, **com_env;
	extern char **environ;

	/* Check for a -V option. */
	for (i = 0; i < argc; i++)
		if (strcmp(argv[i], "-V") == 0) {
			printf("xvt version %s\n", VERSION);
			exit(0);
		}
	/* Make a copy of the command line argument array */
	iargv = (char **) cmalloc((argc + 1) * sizeof(char *));
	for (i = 0; i < argc; i++)
		iargv[i] = argv[i];
	iargv[i] = NULL;
	iargc = argc;

	for (i = 0; i < argc; i++)
		if (strcmp(argv[i], "-l") == 0)
			break;
	if (i < argc - 1 && argv[i+1] != NULL) {
		username = argv[i + 1];
		for (; i < argc && argv[i+2] != NULL; i++)
		   	argv[i] = argv[i+2];
		argc-=2;
		argv[argc] = NULL;
	} else {
		username = NULL;
	}

	i = argc - 1;
	if (argv[i] == NULL || i == 0) {
		usage();
		exit(1);
	}
	nodename = strdup(argv[i]);
	title = strdup(argv[i]);
	argv[i] = NULL;
	argc-=1;

	com_argv = (char **)malloc(sizeof(char *) * 5);
	if (com_argv == NULL)
		exit(1);

	rcmd = getenv("RLOGIN_CMD");
	if (rcmd == NULL)
		rcmd = strdup("rsh");
	if (rcmd == NULL)
		exit(1);
	i = 0;
	com_argv[i] = rcmd;
	i++;
	if (username != NULL) {
		com_argv[i] = strdup("-l");
		if (com_argv[i] == NULL)
			exit(1);
		i++;
		com_argv[i] = strdup(username); i++;
	}
	com_argv[i] = strdup(nodename); i++;
	com_argv[i] = NULL;

	/* Add a TERM entry to the environment. */
	for (i = 0; environ[i] != NULL; i++);
	com_env = (char **) cmalloc((i + 2) * sizeof(char *));
	envc = i;
	term_set = 0;
	for (i = 0; i < envc; i++)
		if (strncmp(environ[i], "TERM=", 5) == 0) {
			com_env[i] = TERM_ENV;
			term_set = 1;
		} else
			com_env[i] = environ[i];
	if (!term_set)
		com_env[envc++] = TERM_ENV;
	com_env[envc] = NULL;
	environ = com_env;

	init_display(argc, argv, iargc, iargv, title);
	init_command(com_argv[0], com_argv);

	for (;;) {
		get_token(&token);
		switch (token.tk_type) {
		case TK_STRING:
			scr_string(token.tk_string, token.tk_length, token.tk_nlcount);
			break;
		case TK_CHAR:
			switch (token.tk_char) {
			case '\n':
				scr_index();
				break;
			case '\r':
				scr_move(0, 0, ROW_RELATIVE);
				break;
			case '\b':
				scr_backspace();
				break;
			case '\t':
				scr_tab();
				break;
			case '\007':	/* bell */
				scr_bell();
				break;
			}
			break;
		case TK_EOF:
			quit(0);
			break;
		case TK_ENTRY:	/* keyboard focus changed */
			scr_focus(1, token.tk_arg[0]);
			break;
		case TK_FOCUS:
			scr_focus(2, token.tk_arg[0]);
			break;
		case TK_EXPOSE:/* window exposed */
			if (!size_set) {

				/* Force a window resize if an exposure event
				 * arrives before the first resize event. */
				resize_window();
				size_set = 1;
			}
			switch (token.tk_region) {
			case SCREEN:
				scr_reset();
				break;
			case SCROLLBAR:
				sbar_reset();
				break;
			}
			break;
		case TK_RESIZE:
			resize_window();
			size_set = 1;
			break;
		case TK_TXTPAR:/* change title or icon name */
			switch (token.tk_arg[0]) {
			case 0:
				change_window_name(token.tk_string);
				change_icon_name(token.tk_string);
				break;
			case 1:
				change_icon_name(token.tk_string);
				break;
			case 2:
				change_window_name(token.tk_string);
				break;
			}
			break;
		case TK_SBSWITCH:
			switch_scrollbar();
			break;
		case TK_SBGOTO:
			scr_move_to(token.tk_arg[0]);
			break;
		case TK_SBUP:
			scr_move_by(token.tk_arg[0]);
			break;
		case TK_SBDOWN:
			scr_move_by(-token.tk_arg[0]);
			break;
		case TK_SELSTART:
			scr_start_selection(token.tk_arg[0], token.tk_arg[1], CHAR);
			break;
		case TK_SELEXTND:
			scr_extend_selection(token.tk_arg[0], token.tk_arg[1], 0);
			break;
		case TK_SELDRAG:
			scr_extend_selection(token.tk_arg[0], token.tk_arg[1], 1);
			break;
		case TK_SELWORD:
			scr_start_selection(token.tk_arg[0], token.tk_arg[1], WORD);
			break;
		case TK_SELLINE:
			scr_start_selection(token.tk_arg[0], token.tk_arg[1], LINE);
			break;
		case TK_SELECT:
			scr_make_selection(token.tk_arg[0]);
			break;
		case TK_SELCLEAR:
			scr_clear_selection();
			break;
		case TK_SELREQUEST:
			scr_send_selection(token.tk_arg[0], token.tk_arg[1],
			    token.tk_arg[2], token.tk_arg[3]);
			break;
		case TK_SELINSRT:
			scr_request_selection(token.tk_arg[0], token.tk_arg[1], token.tk_arg[2]);
			break;
		case TK_SELNOTIFY:
			scr_paste_primary(token.tk_arg[0], token.tk_arg[1], token.tk_arg[2]);
			break;
		case TK_CUU:	/* cursor up */
			n = token.tk_arg[0];
			n = n == 0 ? -1 : -n;
			scr_move(0, n, ROW_RELATIVE | COL_RELATIVE);
			break;
		case TK_CUD:	/* cursor down */
			n = token.tk_arg[0];
			n = n == 0 ? 1 : n;
			scr_move(0, n, ROW_RELATIVE | COL_RELATIVE);
			break;
		case TK_CUF:	/* cursor forward */
			n = token.tk_arg[0];
			n = n == 0 ? 1 : n;
			scr_move(n, 0, ROW_RELATIVE | COL_RELATIVE);
			break;
		case TK_CUB:	/* cursor back */
			n = token.tk_arg[0];
			n = n == 0 ? -1 : -n;
			scr_move(n, 0, ROW_RELATIVE | COL_RELATIVE);
			break;
		case TK_HVP:
		case TK_CUP:	/* position cursor */
			if (token.tk_nargs == 1)
				if (token.tk_arg[0] == 0) {
					x = 0;
					y = 0;
				} else {
					x = 0;
					y = token.tk_arg[0] - 1;
				}
			else {
				y = token.tk_arg[0] - 1;
				x = token.tk_arg[1] - 1;
			}
			scr_move(x, y, 0);
			break;
		case TK_ED:
			scr_erase_screen(token.tk_arg[0]);
			break;
		case TK_EL:
			scr_erase_line(token.tk_arg[0]);
			break;
		case TK_IL:
			n = token.tk_arg[0];
			if (n == 0)
				n = 1;
			scr_insert_lines(n);
			break;
		case TK_DL:
			n = token.tk_arg[0];
			if (n == 0)
				n = 1;
			scr_delete_lines(n);
			break;
		case TK_DCH:
			n = token.tk_arg[0];
			if (n == 0)
				n = 1;
			scr_delete_characters(n);
			break;
		case TK_ICH:
			n = token.tk_arg[0];
			if (n == 0)
				n = 1;
			scr_insert_characters(n);
			break;
		case TK_DA:
			cprintf("\033[?6c");	/* I am a VT102 */
			break;
		case TK_TBC:
			break;
		case TK_SET:
		case TK_RESET:
			mode = (token.tk_type == TK_SET) ? HIGH : LOW;
			if (token.tk_private == '?') {
				switch (token.tk_arg[0]) {
				case 1:
					set_cur_keys(mode);
					break;
				case 6:
					scr_set_decom(mode);
					break;
				case 7:
					scr_set_wrap(mode);
					break;
				case 47:	/* switch to main screen */
					scr_change_screen(mode);
					break;
				}
			} else if (token.tk_private == 0) {
				switch (token.tk_arg[0]) {
				case 4:
					scr_set_insert(mode);
					break;
				}
			}
			break;
		case TK_SGR:
			if (token.tk_nargs == 0)
				scr_change_rendition(RS_NONE);
			else {
				for (i = 0; i < token.tk_nargs; i++) {
					switch (token.tk_arg[i]) {
					case 0:
						scr_change_rendition(RS_NONE);
						break;
					case 1:
						scr_change_rendition(RS_BOLD);
						break;
					case 4:
						scr_change_rendition(RS_ULINE);
						break;
					case 5:
						scr_change_rendition(RS_BLINK);
						break;
					case 7:
						scr_change_rendition(RS_RVID);
						break;
					}
				}
			}
			break;
		case TK_DSR:	/* request for information */
			switch (token.tk_arg[0]) {
			case 6:
				scr_report_position();
				break;
			case 7:/* display name */
				scr_report_display();
				break;
			case 8:/* send magic cookie */
				send_auth();
				break;
			}
			break;
		case TK_DECSTBM:	/* set top and bottom margins */
			if (token.tk_nargs < 2 || token.tk_arg[0] >= token.tk_arg[1])
				scr_set_margins(0, 10000);
			else
				scr_set_margins(token.tk_arg[0] - 1, token.tk_arg[1] - 1);
			break;
		case TK_DECSWH:/* ESC # digit */
			if (token.tk_arg[0] == '8')
				scr_efill();	/* fill screen with Es */
			break;
		case TK_SCS0:
			break;
		case TK_SCS1:
			break;
		case TK_DECSC:
			scr_save_cursor();
			break;
		case TK_DECRC:
			scr_restore_cursor();
			break;
		case TK_DECPAM:
			set_kp_keys(HIGH);
			break;
		case TK_DECPNM:
			set_kp_keys(LOW);
			break;
		case TK_IND:	/* Index (same as \n) */
			scr_index();
			break;
		case TK_NEL:
			break;
		case TK_HTS:
			break;
		case TK_RI:	/* Reverse index */
			scr_rindex();
			break;
		case TK_SS2:
			break;
		case TK_SS3:
			break;
		case TK_DECID:
			cprintf("\033[?6c");	/* I am a VT102 */
			break;
		}
		if (debugging)
			show_token(&token);
	}
}


syntax highlighted by Code2HTML, v. 0.9.1