/* Autoconf patching by David Hedbor, neotron@lysator.liu.se */
/*********************************************************************/
/* file: main.c - main module - signal setup/shutdown etc            */
/*                             TINTIN++                              */
/*          (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t             */
/*                     coded by peter unold 1992                     */
/*********************************************************************/

/* note: a bunch of changes were made here to add readline support -- daw */

#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_TIME_H
#include <time.h>
#endif

#include <signal.h>
#include "tintin.h"
#include <fcntl.h>

#if defined(HAVE_SYS_TERMIO_H) && !defined(BSD_ECHO)
#include <sys/termio.h>
#ifdef HAVE_TCFLAG_T
tcflag_t c_lflag;
cc_t c_cc[NCCS];
#else
unsigned char c_cc[NCC];
unsigned short c_lflag;
#endif
#endif

#ifndef BADSIG
#define BADSIG (void (*)())-1
#endif

/*************** globals ******************/
int case_insensitive = FALSE;	/* @@@added -- perry */
int term_echoing = TRUE;
int echo = DEFAULT_ECHO;
int speedwalk = DEFAULT_SPEEDWALK;
int togglesubs = DEFAULT_TOGGLESUBS;
int presub = DEFAULT_PRESUB;
int redraw = DEFAULT_REDRAW;
int sessionsstarted;
int puts_echoing = TRUE;
int verbose = FALSE;
int alnum = 0;
int acnum = 0;
int subnum = 0;
int varnum = 0;
int hinum = 0;
int pdnum = 0;
int antisubnum = 0;
int verbatim = 0;
char homepath[1025];
char E = 27;

struct session *sessionlist, *activesession;
struct listnode *common_aliases, *common_actions, *common_subs, *common_myvars;
struct listnode *common_highs, *common_antisubs, *common_pathdirs;
char vars[10][BUFFER_SIZE];	/* the %0, %1, %2,....%9 variables */
char tintin_char = DEFAULT_TINTIN_CHAR;
char verbatim_char = DEFAULT_VERBATIM_CHAR;
char system_com[80] = SYSTEM_COMMAND_DEFAULT;
int mesvar[7];
int display_row, display_col, input_row, input_col;
int split_line, term_columns;
char k_input[BUFFER_SIZE];
char done_input[BUFFER_SIZE], prev_command[BUFFER_SIZE];
int hist_num;
int is_split;
int text_came;
void tintin();
void read_mud();
void do_one_line();
void snoop();
void tintin_puts2();

/************ externs *************/
extern int ignore_interrupt;
extern int ticker_interrupted, time0;
extern int tick_size, sec_to_tick;

extern void check_all_actions();	/* new */
extern void myquitsig();
extern struct session *newactive_session();
extern struct session *parse_input();
extern struct session *read_command();
extern struct completenode *complete_head;
extern struct listnode *init_list();
/* extern void term_noecho(); */
extern void read_complete();
extern void syserr();
extern void alarm();
extern int do_one_antisub();
extern void do_one_sub();
extern void do_one_high();
extern void prompt();
int read();
int select();
extern void do_history();
extern int read_buffer_mud();
extern void cleanup_session();
int write();
/* int fwrite(); */
/* int sscanf(); */
/* extern void term_echo(); */

int last_line_length;

extern void initsplit();
/* when the screen size changes, take note of it */
void winchhandler()
{
	/*
	 * select() will see a "syscall interrupted" error;
	 * remember not to worry
	 */
	ignore_interrupt = 1;

	if (is_split)
		initsplit(1);	/* @@@changed -- perry */
	tintin_puts("#SCREEN SIZE RESET (FROM SIGWINCH).", NULL);

	/* we haveta reinitialize the signals for sysv machines */
	if (signal(SIGWINCH, winchhandler) == BADSIG)
		syserr("signal SIGWINCH");
}

/* CHANGED to get rid of double-echoing bug when tintin++ gets suspended */
void tstphandler(sig, code, scp, addr)
     int sig;
     int code;
     struct sigcontext *scp;
     char *addr;
{
	/* select() will see a "syscall interrupted" error; remember not to worry */
	ignore_interrupt = 1;

	cleanscreen();
	kill(getpid(), SIGSTOP);
	dirtyscreen();
	tintin_puts("#RETURNING BACK TO TINTIN++.", NULL);

	/* we haveta reinitialize the signals for sysv machines */
	if (signal(SIGTSTP, tstphandler) == BADSIG)
		syserr("signal SIGTSTP");

	/* the other stuff is obsolete, now that we have readline */
}

/**************************************************************************/
/* main() - show title - setup signals - init lists - readcoms - tintin() */
/**************************************************************************/

int main(argc, argv, environ)
     int argc;
     char **argv;
     char **environ;
{
	struct session *ses;
	char *strptr, temp[BUFFER_SIZE];
	int arg_num;
	int fd;

#if defined(SOCKS)
	SOCKSinit(argv[0]);
#endif

/*
   #if defined(SYSV)
   init_echo();
   #endif
 */
	is_split = FALSE;
	ses = NULL;

	/* new with readline */
	rltab_read();

	tintin_puts2("##################################################", ses);
	sprintf(temp, "#              T I N T I N + + %-18s%1s", VERSION_NUM, "#");
	tintin_puts2(temp, ses);
	tintin_puts2("#        THIS IS A DEVELOPMENT VERSION!!!        #", ses);
	tintin_puts2("#  (T)he k(I)cki(N) (T)ickin d(I)kumud clie(N)t  #", ses);
	tintin_puts2("#                a DIKU-mud client               #", ses);
	tintin_puts2("#     new code by Bill Reiss, David A. Wagner    #", ses);
	tintin_puts2("#      Joann Ellsworth, Jeremy C. Jack 1994      #", ses);
	tintin_puts2("# thanks to Peter Unold for original TINTIN code #", ses);
	tintin_puts2("##################################################", ses);

	if (signal(SIGTERM, myquitsig) == BADSIG)
		syserr("signal SIGTERM");
	if (signal(SIGINT, myquitsig) == BADSIG)
		syserr("signal SIGINT");
	/* CHANGED to get rid of double-echoing bug when tintin++ gets suspended */
	if (signal(SIGTSTP, tstphandler) == BADSIG)
		syserr("signal SIGTSTP");
	if (signal(SIGWINCH, winchhandler) == BADSIG)
		syserr("signal SIGWINCH");

	common_aliases = init_list();
	common_actions = init_list();
	common_subs = init_list();
	common_myvars = init_list();
	common_highs = init_list();
	common_antisubs = init_list();
	common_pathdirs = init_list();
	mesvar[0] = DEFAULT_ALIAS_MESS;
	mesvar[1] = DEFAULT_ACTION_MESS;
	mesvar[2] = DEFAULT_SUB_MESS;
	mesvar[3] = DEFAULT_ANTISUB_MESS;
	mesvar[4] = DEFAULT_HIGHLIGHT_MESS;
	mesvar[5] = DEFAULT_VARIABLE_MESS;
	mesvar[6] = DEFAULT_PATHDIR_MESS;
	*homepath = '\0';
	if (!strcmp(DEFAULT_FILE_DIR, "HOME"))
		if (strptr = (char *) getenv("HOME"))
			strcpy(homepath, strptr);
		else
			*homepath = '\0';
	else
		strcpy(homepath, DEFAULT_FILE_DIR);
	arg_num = 1;
	if (argc > 1 && argv[1]) {
		if (*argv[1] == '-' && *(argv[1] + 1) == 'v') {
			arg_num = 2;
			verbose = TRUE;
		}
	}
	if (argc > arg_num && argv[arg_num]) {
		activesession = read_command(argv[arg_num], NULL);
	}
	else {
		strcpy(temp, homepath);
		strcat(temp, "/.tintinrc");
		if ((fd = open(temp, O_RDONLY)) > 0) {	/* Check if it exists */
			close(fd);
			activesession = read_command(temp, NULL);
		}
		else {
			if (strptr = (char *) getenv("HOME")) {
				strcpy(homepath, strptr);
				strcpy(temp, homepath);
				strcat(temp, "/.tintinrc");
				if ((fd = open(temp, O_RDONLY)) > 0) {	/* Check if it exists */
					close(fd);
					activesession = read_command(temp, NULL);
				}
			}
		}
	}
	mainloop();
	return 1;
}

/**********************************************************/
/* do all of the functions to one line of buffer          */
/**********************************************************/
void do_one_line(line, ses)
     char *line;
     struct session *ses;
{
	if (!presub && !ses->ignore)
		check_all_actions(line, ses);
	if (!togglesubs)
		if (!do_one_antisub(line, ses))
			do_one_sub(line, ses);
	if (presub && !ses->ignore)
		check_all_actions(line, ses);
	do_one_high(line, ses);
}