⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rl.c

📁 Linux下的MUD客户端程序
💻 C
字号:
/* New for v2.0: readline support -- daw *//* this is the main bunch of code for readline; lots of misc stuff here */#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#include <sys/types.h>#include <sys/time.h>#include <stdio.h>#include <errno.h>#include <readline/readline.h>#include "tintin.h"/* note: changed to allow autodetection/manual change of screensize,   //SN */static int SPLITLINE;static int COLS;/* this gets set when user hits control-z, so we don't worry about EINTR */int			ignore_interrupt;/* what column we were at in the top window; only for split mode */static int		topwin_col = 0;#define ISAPROMPT(x)	(strchr((x), '>'))/* some readline stuff */int			(*rl_event_hook)();int			(*rl_completion_entry_function)();extern int		_rl_last_c_pos;extern int		_rl_eof_char;extern int		readline_echoing_p;extern int		history_expand();extern int		errno;extern struct session	*sessionlist, *activesession;extern int		is_split;extern int		redraw;extern int		puts_echoing;extern struct session	*parse_input();extern struct session	*newactive_session();extern char		*rltab_generate();extern char		*rlhist_expand();void			tintin_puts();extern char             *getenv();extern char             *tgetstr();extern char             *get_arg_in_braces();static voidctrl_r_redraw(count, key)	int	count;	int	key;{	if (is_split) {		goto_rowcol(SPLITLINE+1, 0);		erase_toeol();	} else		printf("\n");	fflush(stdout);	_rl_last_c_pos = 0;	rl_forced_update_display();}static void	readmud();/* for use with rl_event_hook */static voidbait(/* void */){	fd_set		readfds;	struct session	*s, *t;	struct timeval	to;	int		rv, maybe_redraw;	FD_ZERO(&readfds);	while (!FD_ISSET(0, &readfds)) {		FD_ZERO(&readfds);		FD_SET(0, &readfds);	/* stdin */		for (s=sessionlist; s; s=s->next)			FD_SET(s->socket, &readfds);		to.tv_sec = checktick(); /* 100 */		to.tv_usec = 0;		ignore_interrupt = 0;		rv = select(FD_SETSIZE, &readfds, NULL, NULL, &to);		if (rv == 0)			continue;	/* timeout */		else if (rv < 0 && errno == EINTR && ignore_interrupt)			continue;	/* user hit ^Z; don't worry, be happy */		else if (rv < 0)			syserr("select");		maybe_redraw = 0;		for (s=sessionlist; s; s=t) {			t = s->next;	/* s may be free()d out from under us */			if (FD_ISSET(s->socket, &readfds)) {				readmud(s);				maybe_redraw = 1;			}		}		if (maybe_redraw && redraw && !is_split)			ctrl_r_redraw();	}}voidinitrl(/* void */){	rl_readline_name = "tintin++";	rl_completion_entry_function = (int (*)()) rltab_generate;	using_history();	stifle_history(HISTORY_SIZE);	rl_variable_bind("horizontal-scroll-mode", "on");	rl_bind_key('\022', ctrl_r_redraw);	/* control-r */	rl_bind_key_in_map('\022', ctrl_r_redraw, vi_movement_keymap);	rl_bind_key_in_map('\022', ctrl_r_redraw, vi_insertion_keymap);	rl_event_hook = (int (*)()) bait;	/*	 * a hack to let ^d work like it used to in old tt++:	 * by default, readline won't let you rebind the eof	 * character when it's at the start of the line, so	 * let's pull the wool over readline.	 * bug: remember to undo the stty!  check portability!	 */	_rl_eof_char = '\001'; /* control-b : something innocuous */	system("stty eof '^b'");	rl_bind_key('\004', rl_get_previous_history); /* control-d */	rl_bind_key_in_map('\004', rl_get_previous_history, vi_movement_keymap);	rl_bind_key_in_map('\004', rl_get_previous_history,vi_insertion_keymap);}/* Autodetect screensize: Code gotten from v1.64DEV *//* //SN                                            */void setSCREENSIZE(p_line,p_cols)  int *p_line, *p_cols;{  register char *s;  if ((s = getenv("LINES")) != (char *) 0)    *p_line = atoi(s);  else    *p_line = tgetnum("li");  if (*p_line <= 0)    *p_line = 24;   if ((s = getenv("COLUMNS")) != (char *) 0)    *p_cols = atoi(s);   else    *p_cols = tgetnum("co");   if (*p_cols <= 0)    *p_cols = 80;}/* Changed to allow screensize detection/manual set,   //SN *//* turn on split mode */static voidinitsplit(/* void */){        SPLITLINE--;	is_split = 1;	topwin_col = 0;	reset();	erase_screen();	scroll_region(1, SPLITLINE-1);	goto_rowcol(SPLITLINE, 0);	printf(" ---- ");	goto_rowcol(SPLITLINE+1, 0);	save_pos();	fflush(stdout);}/* Removed the wrap-at-end-of-screen code, //SN */static voidprintline(s, isaprompt)	char	*s;{   topwin_col = 0;   puts(s);}voidmainloop(/* void */){	char	*line;	initrl();	/* Already done in main()        initsplit();	*/	for (;;) {		line = readline("");		if (line == NULL)			syserr("readline() == NULL");		line = rlhist_expand(line);		if (line == NULL)			continue;		if (is_split)			goto_rowcol(SPLITLINE-1, topwin_col);		/* commands will echo to the top screen */		if (is_split)			printline(line, 0);		activesession = parse_input(line, activesession);		if (is_split) {			goto_rowcol(SPLITLINE+1, 0);			erase_toeol();			fflush(stdout);		}		free(line);	}}/* an uncalled noop -- for now */static voidsee_prompt(b, l)	char	*b;	int	l;{	/* soon this will try to recognize prompts and process them */	/* maybe use IACGA */}/* data waiting on this mud session; read & display it; do the dirty work */static voidreadmud(s)	struct session	*s;{	char	thebuffer[2*BUFFER_SIZE+1], *buf, *p, *q;	char	linebuf[BUFFER_SIZE], header[BUFFER_SIZE];	int	rv, i, headerlen;	buf = thebuffer + BUFFER_SIZE;	rv = read_buffer_mud(buf, s);	if (rv == 0) {		cleanup_session(s);		if (s == activesession)			activesession = newactive_session();		return;	} else if (rv < 0)		syserr("readmud: read");	buf[++rv] = '\0';	if (s == activesession)		header[0] = '\0';	else if (s->snoopstatus)		sprintf(header, "%s%% ", s->name);	else		return;	headerlen = strlen(header);	if (s->old_more_coming) {		p = s->last_line;		buf -= strlen(p);		while (*p)			*buf++ = *p++;		buf -= strlen(s->last_line);		s->last_line[0] = '\0';	}	logit(s, buf);	if (is_split) {		save_pos();		goto_rowcol(SPLITLINE-1, topwin_col);	}	/* separate into lines and print away */	for (p=buf; p && *p; p=q) {		if ((q = strchr(p, '\n')) == NULL && s->more_coming)			break;		if (q) {			*q++ = '\0';			if (*q == '\r')			/* ignore \r's */				q++;		}		strcpy(linebuf, p);		do_one_line(linebuf, s);		/* changes linebuf */		if (strcmp(linebuf, ".") != 0) {			strcat(header, linebuf);			printline(header, (q == NULL) && ISAPROMPT(header));			header[headerlen] = '\0';		}	}	if (p && *p)		strcpy(s->last_line, p);	if (is_split)		restore_pos();	fflush(stdout);	/* q: do we need to do some sort of redraw here?  i don't think so */	/* a: no, i do it at the end of mainloop() [for now] */}/* * output to screen should go through this function * the output is NOT checked for actions or anything */voidtintin_puts2(cptr, ses)	char		*cptr;	struct session	*ses;{	char	*p;	if ((ses != activesession && ses != 0) || !puts_echoing)		return;	if (is_split) {		goto_rowcol(SPLITLINE-1, topwin_col);	}	printline(cptr, 0);	fflush(stdout);	/* q: do we need to do some sort of redraw here?  i don't think so */	/* a: right now, i think so */	if (redraw && !is_split)		ctrl_r_redraw();}/***********************************************//* the #statusline command * By Sverre Normann *//***********************************************//* Syntax: #statusline {text}                  *//***********************************************//* Used to write the statusline in split-mode  *//***********************************************/void statusline_command(arg, ses)  char   *arg;  struct session *ses;{  char left[BUFFER_SIZE], temp[BUFFER_SIZE];  if (is_split) {    arg=get_arg_in_braces(arg, left, 1);    substitute_vars(left,temp);    substitute_myvars(temp,left,ses);        goto_rowcol(SPLITLINE, topwin_col);                erase_toeol();    printf(left);    goto_rowcol(SPLITLINE-1, 0);        }  else {    tintin_puts2("#Error using #statusline: Split mode not set!",ses);  }   } /* * output to screen should go through this function * the output IS treated as though it came from the mud */voidtintin_puts(cptr, ses)	char		*cptr;	struct session	*ses;{	/* bug! doesn't do_one_line() sometimes send output to stdout? */	/* bug: doesn't do_one_line() modify it's input?  are we ok here? */	if (ses)		do_one_line(cptr, ses);	tintin_puts2(cptr, ses);  }/* nobody needs tintin_puts3 anymore*//* get a clean screen without the split crap; useful for ^Z, quitting, etc */voidcleanscreen(/* void */){	/* i think term_echo() was unportable.  try to avoid using echo.c */	/* term_echo(); */	system("stty echo");	/* a hack, admittedly */	/* undo the "stty eof '^b'" from initrl() */	system("stty eof '^d'");	if (!is_split)		return;	scroll_region(1, 24);	erase_screen();	reset();	fflush(stdout);}/* undo cleanscreen(); useful after ^Z */voiddirtyscreen(/* void */){	if (is_split)		initsplit();	/* put the eof = ^b back; see cleanscreen() and initrl() */	system("stty eof '^b'");}/* quit tintin++ and print a message */voidquitmsg(m)	char	*m;{	struct session	*s;	for (s=sessionlist; s; s=s->next)		cleanup_session(s);	cleanscreen();	if (m)		printf("%s\n", m);	printf("Goodbye from tintin++.\n");	exit(0);}/* quit tintin++ fast!  for use with signal() */voidmyquitsig(/* void */){	quitmsg(NULL);}/* note: split command was changed to allow automatic/manual setting of screen size  *//* - no arguments -> automatic detection                                             *//* - else -> params are given on the format {lines,columns}                          *//* //SN                                                                              */voidsplit_command(arg,ses)  char   *arg;  struct session *ses;{  char lines[BUFFER_SIZE], cols[BUFFER_SIZE],       temp[BUFFER_SIZE];  int  c,l;  if (is_split) {    tintin_puts2("#Error in #split: Already in split mode.",ses);  }  else {    arg=get_arg_in_braces(arg, lines, 0);    substitute_vars(lines,temp);    substitute_myvars(temp,lines,ses);    if (!*lines) {      setSCREENSIZE(&SPLITLINE,&COLS);      initsplit();    }    else {      if (sscanf(lines,"%d,%d",&l,&c)!=2)        tintin_puts2("#Error. Syntax: #split {lines,columns}  Params optional.",ses);      else {        SPLITLINE=l;        COLS=c;        initsplit();      }    }  }}voidunsplit_command(/* void */){	cleanscreen();	is_split = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -