1 /*
2  *    Terminal Module.
3  *
4  *    based on NxEdit2.04     :: term.c
5  *             FD clone 1.03g :: term.c
6  *             ne 3.00pre17   :: term.c
7  *
8  * Copyright (c) 1999, 2000 SASAKI Shunsuke.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification, immediately at the beginning of the file.
17  * 2. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * Where this Software is combined with software released under the terms of
21  * the GNU Public License ("GPL") and the terms of the GPL would require the
22  * combined work to also be released under the terms of the GPL, the terms
23  * and conditions of this License will apply in addition to those of the
24  * GPL with the exception of any terms or conditions of this License that
25  * conflict with, or are expressly prohibited by, the GPL.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
31  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  */
39 
40 #include	"config.h"
41 
42 #include	<stdio.h>
43 #include	<stdlib.h>
44 #include	<string.h>
45 
46 #ifdef  HAVE_UNISTD_H
47 #   include <unistd.h>
48 #endif
49 
50 #include	<sys/types.h>
51 #include	<errno.h>
52 
53 #ifdef	HAVE_STDARG_H
54 #	include	<stdarg.h>
55 #else
56 #	ifdef	HAVE_VARARGS_H
57 #		include	<varargs.h>
58 #	endif
59 #endif
60 
61 #ifdef	HAVE_FCNTL_H
62 #	include	<fcntl.h>
63 #endif
64 
65 #ifdef	HAVE_SELECT
66 #	ifdef	HAVE_SYS_TIME_H
67 #		include <sys/time.h>
68 #	endif
69 #else
70 #ifdef HAVE_SYS_POLL_H
71 #	include <sys/poll.h>
72 #endif
73 #endif
74 
75 
76 
77 #ifdef	HAVE_TERMCAP_H
78 #	include	<termcap.h>
79 #endif
80 
81 //	short	ospeed=0;
82 	char	PC= '\0';
83 	char	*BC= NULL;
84 	char	*UP= NULL;
85 
86 #ifdef	HAVE_TERMIOS_H
87 
88 #	include	<termios.h>
89 	typedef	struct termios	term_ioctl_t;
90 #	define	term_getattr(t)	tcgetattr(fileno(term.fp_tty), t)
91 #	define	term_setattr(t)	tcsetattr(fileno(term.fp_tty), TCSAFLUSH, t)
92 #	define	term_getspeed()	cfgetospeed(&term.tty)
93 
94 #else
95 #ifdef	HAVE_TERMIO_H
96 
97 #	include	<termio.h>
98 	typedef	struct termio	term_ioctl_t;
99 #	define	term_getattr(t)	ioctl(fileno(term.fp_tty), TCGETA, t)
100 #	define	term_setattr(t)	ioctl(fileno(term.fp_tty), TCSETAF, t)
101 #	define	term_getspeed()	(term.tty.c_cflag & CBAUD)
102 
103 #endif
104 
105 #error	"SGTTY ����������Ʋ�������"
106 
107 #endif
108 
109 #ifndef		STDIN_FILENO
110 #	define	STDIN_FILENO	0
111 #endif
112 
113 #ifndef		IEXTEN
114 #	define	IEXTEN		0
115 #endif
116 
117 
118 /*
119 	#ifdef	NOERRNO
120 	extern int errno;
121 	#endif
122 */
123 
124 #include	"generic.h"
125 #include	"term.h"
126 
127 
128 #define	LN_dispbuf	2048
129 #define	TERMCAPSIZE	2048
130 #define	TTYNAME		"/dev/tty"
131 
132 static	void	term_locate_flush();
133 static	void	term_color_flush();
134 static	void	term_tputs(const char *str);
135 
136 static	void	term_all_flush();
137 
138 
139 static	int 	exit_failed=FALSE;
140 
141 #ifndef	TIOCSTI
142 static	u_char	ungetbuf[16];
143 static	int 	ungetnum = 0;
144 #endif
145 
146 extern	char *tparm(const char *str, ...);
147 
148 
149 typedef	struct
150 {
151 	int 	mode;
152 
153 /* control TTY */
154 	char	*name;
155 	FILE	*fp_tty;
156 	term_ioctl_t	tty;
157 
158 /* control screen */
159 	char	*t_init;
160 	char	*t_keypad;
161 	char	*t_nokeypad;
162 	char	*t_end;
163 	char	*cn_locate;
164 
165 	char	*t_clear;
166 	char	*t_normal;
167 	char	*t_reverse;
168 	char	*t_underline;
169 	char	*t_bold;
170 	char	*l_insert;
171 	char	*l_delete;
172 	char	*ln_insert;
173 	char	*ln_delete;
174 	char	*l_clear;
175 	char	*end_underline;
176 
177 	char	*t_hidecursor;
178 	char	*t_normalcursor;
179 
180 	char	*t_vbell;
181 
182 
183 	int 	sizex, sizey;
184 
185 	int 	md_cursor, md_cursor0;
186 	int 	x, y;		/* cursor location */
187 	int 	x0, y0;		/* latest cursor location */
188 	color_t	cl;			/* now color */
189 	color_t	cl0;		/* latest color */
190 
191 	int		**scr, **scr0;
192 
193 	int 	*tq;
194 	bool	f_cls;
195 }	term_t;
196 
197 static	term_t	term;
198 
199 #define	CS_ignore	0
200 #define	CS_normal	1
201 #define	CS_hide		2
202 
203 
204 #define	SCR_code(cl,ch)	(((cl)&0xff)<<24 | (ch))
205 #define	SCR_char(scr)	((scr)&0xffffff)
206 #define	SCR_color(scr)		(((scr)&0xff000000)>>24)
207 
208 #define	SCR_ignore		-1
209 
210 
tty_fp()211 		FILE	*tty_fp()		{return term.fp_tty;}
term_flush()212 static	void	term_flush()	{fflush(term.fp_tty);}
213 
214 
term_sizex()215 int 	term_sizex()	{return term.sizex;}
term_sizey()216 int 	term_sizey()	{return term.sizey;}
217 
218 
term_getwsize()219 void	term_getwsize()
220 {
221 	int x, y;
222 
223 	x = y = -1;
224 
225 #ifdef	TIOCGWINSZ
226 		{
227 		 struct winsize ws;
228 
229 		 if (ioctl(fileno(term.fp_tty), TIOCGWINSZ, &ws)>=0)
230 		 	{
231 		 	 x = ws.ws_col;
232 		 	 y = ws.ws_row;
233 		 	}
234 		}
235 #endif
236 #ifdef	WIOCGETD
237 	if (x<0&& y<0)
238 		{
239 		 struct uwdate wd;
240 
241 		 if (ioctl(fileno(term.fp_tty), WIOCGETD, &ws)>=0)
242 		 	{
243 		 	 x = ws.uw_width / ws.uw_hs;
244 		 	 y = ws.uw_height / ws.uw_vs;
245 		 	}
246 		}
247 #endif
248 
249 	if (x>0 && y>0)
250 		{
251 		 term.sizex = x;
252 		 term.sizey = y;
253 		}
254 }
255 
term_getent(const char * s_id,const char * s_def)256 char	*term_getent(const char *s_id, const char *s_def)
257 {
258 	char	buf[TERMCAPSIZE+1], *p;
259 	const	char	*cp;
260 
261 	p=buf;
262 	cp=tgetstr(s_id, &p);
263 
264 	if (cp==NULL || *cp=='\0')
265 		cp=s_def;
266 
267 	return mem_strdup(cp);
268 }
269 
270 #if 0
271 static	void	term_tparam(char *s, const char *fmt, int arg1, int arg2)
272 {
273 	while (*fmt!='\0')
274 		{
275 		 if (*fmt!='%')
276 		 	{
277 		 	 *s++=*fmt++;
278 		 	 continue;
279 		 	}
280 
281 		 ++fmt;
282 		 switch(*fmt)
283 		 	{
284 		  case 'd':
285 		  	 sprintf(s, "%d", arg1);
286 		   	 s+=strlen(s);
287 		  	 arg1=arg2;
288 		  	 arg2=0;
289 		  	 break;
290 		  case 'i':
291 		  	 ++arg1;
292 		  	 ++arg2;
293 		  	 break;
294 		  case 'p':
295 		  	 ++fmt;
296 		  	 break;
297 		  case '%':
298 		  	 *s++='%';
299 		  	}
300 		 if (*fmt!='\0')
301 		 	++fmt;
302 		}
303 	*s='\0';
304 }
305 #endif
306 
term_queue_clear()307 void	term_queue_clear()
308 {
309 	int 	i;
310 
311 	for (i=0; i<term.sizey; ++i)
312 		term.tq[i]=0;
313 }
314 
term_scroll(int n)315 void	term_scroll(int n)
316 {
317 	term.tq[term.y]+=n;
318 }
319 
320 
term_scr_clr(int * scr,int x)321 static	void	term_scr_clr(int *scr, int x)
322 {
323 	while(x<term.sizex)
324 		scr[x++]= SCR_code(AC_normal, ' ');
325 }
326 
327 
term_cls()328 void	term_cls()
329 {
330 	int 	i, j;
331 
332 	term_queue_clear();
333 	term.f_cls=TRUE;
334 
335 	for (i=0; i<term.sizey; ++i)
336 		term_scr_clr(term.scr[i], 0);
337 }
338 
term_scr_init()339 static	void	term_scr_init()
340 {
341 	int 	i;
342 
343 	term.scr = mem_alloc(term.sizey * sizeof (void *));
344 	term.scr0= mem_alloc(term.sizey * sizeof (void *));
345 
346 	for (i=0; i<term.sizey; ++i)
347 		{
348 		 term.scr[i] = mem_alloc(term.sizex * sizeof(int));
349 		 term.scr0[i]= mem_alloc(term.sizex * sizeof(int));
350 
351 		 term_scr_clr(term.scr[i], 0);
352 		 term_scr_clr(term.scr0[i], 0);
353 		}
354 
355 	term.f_cls=FALSE;
356 	term.tq= mem_alloc(term.sizey * sizeof(int));
357 	term_queue_clear();
358 }
359 
360 
361 #define	TM_none 		0
362 #define	TM_keypad		1
363 #define	TM_init			2
364 #define	TM_tinit		4
365 #define	TM_ansicolor	8
366 
term_setmode(int mode)367 static	void	term_setmode(int mode)
368 {
369 	if ((mode& TM_init)&& !(term.mode& TM_init))
370 		{
371 		 if (mode& TM_tinit)
372 		 	term_tputs(term.t_init);
373 		 term_tputs(term.t_normal);
374 
375 //		 term_scr_fin();
376 		 term_getwsize();
377 		 term_scr_init();
378 
379 		 term.x0 =0;
380 		 term.y0 =0;
381 		 term.cl =AC_normal;
382 		 term.cl0=AC_normal;
383 		 term.md_cursor0=CS_ignore;
384 		}
385 
386 	if ((mode& TM_keypad)&& !(term.mode& TM_keypad))
387 		term_tputs(term.t_keypad);
388 
389 	if ((term.mode& TM_keypad)&& !(mode& TM_keypad))
390 		term_tputs(term.t_nokeypad);
391 
392 	if ((term.mode& TM_init)&& !(mode& TM_init))
393 		{
394 		 term_tputs(term.t_normal);
395 		 term_tputs(term.t_clear);
396 		 term_tputs(term.t_normalcursor);
397 
398 		 if (term.mode& TM_tinit)
399 		 	term_tputs(term.t_end);
400 		}
401 
402 	term.mode=mode;
403 
404 	term_flush();
405 }
406 
term_getmode()407 static	int 	term_getmode()
408 {
409 	return term.mode;
410 }
411 
412 
413 
term_stop()414 void	term_stop()	/* atexit�����ΤǴ���Ū�ˤ�����Ū�˸Ƥ�ɬ�פϤʤ� */
415 {
416 	if (exit_failed)
417 		return;
418 	exit_failed=TRUE;
419 
420 	term_setattr(&term.tty);
421 	term_setmode(TM_none);
422 
423 	term.fp_tty=stdout;
424 }
425 
term_start()426 void	term_start()
427 {
428 	term_ioctl_t	tty;
429 
430 	memcpy(&tty, &term.tty, sizeof(term_ioctl_t));
431 	tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ISIG | ICANON | IEXTEN);
432 	tty.c_iflag |= IGNBRK;
433 	tty.c_iflag &= ~(ICRNL | BRKINT | IXON);
434 	tty.c_oflag &= ~(ONLCR| OPOST);
435 	tty.c_cc[VTIME]= 0;
436 	tty.c_cc[VMIN]= 1;
437 	term_setattr(&tty);
438 
439 	term_setmode(TM_init| TM_tinit| TM_keypad| TM_ansicolor);
440 
441 	exit_failed=FALSE;
442 	atexit(term_stop);
443 }
444 
445 
term_init()446 void	term_init()
447 {
448 	static	char	tbuf[TERMCAPSIZE+1];
449 
450 	term.fp_tty=fopen(TTYNAME, "w+");
451 	if (term.fp_tty==NULL)
452 		term.fp_tty=stdout;
453 
454 	term.mode=TM_none;
455 	term_getattr(&term.tty);
456 
457 	term.name= getenv("TERM");
458 	if (term.name==NULL)
459 		term.name="";
460 	if (tgetent(tbuf, term.name) <= 0)
461 		{
462 //		 warning("No termcap presented.");
463 		 report_puts("No termcap presented.");
464 		 term.sizey=24;
465 		 term.sizex=79;
466 
467 		 term.t_init         = "";
468 		 term.t_end          = "";
469 		 term.t_keypad       = "\033[?1h\033=";
470 		 term.t_nokeypad     = "\033[?1l\033>";
471 		 term.t_normalcursor = "";
472 		 term.t_hidecursor     = "";
473 		 term.t_vbell        = "\007";
474 		 term.t_clear        = "\033[;H\033[2J";
475 		 term.t_normal       = "\033[m";
476 		 term.t_bold         = "\033[1m";
477 		 term.t_reverse      = "\033[7m";
478 		 term.t_underline    = "\033[4m";
479 		 term.end_underline  = "\033[m";
480 		 term.l_clear        = "\033[K";
481 		 term.l_insert       = "\033[L";
482 		 term.l_delete       = "\033[M";
483 		 term.ln_insert      = "\033[%dL";
484 		 term.ln_delete      = "\033[%dM";
485 		 term.cn_locate      = "\033[%i%d;%dH";
486 		} else
487 		{
488 		 term.sizey = tgetnum("li");
489 		 term.sizex = tgetnum("co");
490 		 if (!tgetflag("am"))
491 		 	term.sizex--;
492 
493 		 PC=*term_getent("pc", ""); //!! ���ݤʤΤ�Free���Ƥ��ʤ�
494 		 BC=term_getent("bc", "\010");
495 		 UP=term_getent("up", "\033[A");
496 //		 ospeed = term_getspeed();
497 
498 		 term.t_init         =term_getent("ti", "");
499 		 term.t_end          =term_getent("te", "");
500 		 term.t_keypad       =term_getent("ks", "");
501 		 term.t_nokeypad     =term_getent("ke", "");
502 		 term.t_normalcursor =term_getent("ve", "");
503 		 term.t_hidecursor     =term_getent("vi", "");
504 		 term.t_vbell        =term_getent("vb", "\007");
505 		 term.t_clear        =term_getent("cl", "\033[;H\033[2J");
506 		 term.t_normal       =term_getent("me", "\033[m");
507 		 term.t_bold         =term_getent("md", "\033[1m");
508 		 term.t_reverse      =term_getent("mr", "\033[7m");
509 		 term.t_underline    =term_getent("us", "\033[4m");
510 		 term.end_underline  =term_getent("ue", "\033[m");
511 		 term.l_clear        =term_getent("ce", "\033[K");
512 		 term.l_insert       =term_getent("al", "\033[L");
513 		 term.l_delete       =term_getent("dl", "\033[M");
514 		 term.ln_insert       =term_getent("AL", "");
515 		 term.ln_delete       =term_getent("DL", "");
516 		 term.cn_locate       =term_getent("cm", "\033[%i%d;%dH");
517 		}
518 }
519 
term_report()520 void	term_report()
521 {
522 	report_puts("ü������:\n");
523 	report_printf("  x = %d, y = %d\n", term.sizex, term.sizey);
524 
525 	report_puts("ɽ����������:\n");
526 
527 	report_printf("  term.t_init = %s\n", term.t_init);
528 	report_printf("  term.t_end = %s\n", term.t_end);
529 	report_printf("  term.t_keypad = %s\n", term.t_keypad);
530 	report_printf("  term.t_nokeypad = %s\n", term.t_nokeypad);
531 	report_printf("  term.t_normalcursor = %s\n", term.t_normalcursor);
532 	report_printf("  term.t_hidecursor = %s\n", term.t_hidecursor);
533 	report_printf("  term.t_vbell = %s\n", term.t_vbell);
534 	report_printf("  term.t_clear = %s\n", term.t_clear);
535 	report_printf("  term.t_normal = %s\n", term.t_normal);
536 	report_printf("  term.t_bold = %s\n", term.t_bold);
537 	report_printf("  term.t_reverse = %s\n", term.t_reverse);
538 	report_printf("  term.t_underline = %s\n", term.t_underline);
539 	report_printf("  term.end_underline = %s\n", term.end_underline);
540 	report_printf("  term.l_clear = %s\n", term.l_clear);
541 	report_printf("  term.l_insert = %s\n", term.l_insert);
542 	report_printf("  term.l_delete = %s\n", term.l_delete);
543 	report_printf("  term.ln_insert = %s\n", term.ln_insert);
544 	report_printf("  term.ln_delete = %s\n", term.ln_delete);
545 	report_printf("  term.cn_locate = %s\n", term.cn_locate);
546 }
547 
term_kflush()548 void	term_kflush()
549 {
550 	tcflush(fileno(term.fp_tty), TCIFLUSH);
551 }
552 
term_dputc(int c)553 static	int		term_dputc(int c)			{return fputc(c, term.fp_tty);}
term_tputs(const char * s)554 static	void	term_tputs(const char *s)	{tputs(s, term.sizey, term_dputc);}
555 
556 
557 
558 
term_getch()559 int 	term_getch()
560 {
561 	u_char	ch;
562 	int 	i;
563 
564 	while ((i=read(fileno(term.fp_tty), &ch, sizeof(u_char))) < 0 && errno == EINTR);
565 	if (i < sizeof(u_char)) return(EOF);
566 	return((int)ch);
567 
568 
569 /*	while ((ch=fgetc(term.fp_tty))==EOF)
570 		{
571 		 if (!ferror(term.fp_tty) || errno != EINTR)
572 		 	{
573 		 	 clearerr(term.fp_tty);
574 			 return EOF;
575 		 	}
576 		}
577 */
578 }
579 
term_kbhit(u_long usec)580 int 	term_kbhit(u_long usec)
581 {
582 #ifdef HAVE_SELECT
583 	fd_set readfds;
584 	struct timeval timeout;
585 
586 	timeout.tv_sec  = 0;
587 	timeout.tv_usec = usec;
588 	FD_ZERO(&readfds);
589 	FD_SET (STDIN_FILENO, &readfds);
590 
591 	return (select(1, &readfds, NULL, NULL, &timeout));
592 
593 #else
594 #ifdef HAVE_SYS_POLL_H
595 	struct poolfd	pf;
596 
597 	pf.fd      = STDIN_FILENO;
598 	pf.events  = POLLIN;
599 	pf.revents = 0;
600 
601 	return (poll(&pf, 1, usec * 1000));
602 
603 #else
604 	return 1;
605 
606 #endif
607 #endif
608 }
609 
term_bell()610 void	term_bell()
611 {
612 	term_tputs(term.t_vbell);
613 	term_flush();
614 }
615 
term_csr_flush()616 void	term_csr_flush()
617 {
618 	int 	x,y;
619 
620 	x=term.x;
621 	y=term.y;
622 
623 	if (term.md_cursor0 != CS_hide)
624 		{
625 		 term_tputs(term.t_hidecursor);
626 		 term.md_cursor0 = CS_hide;
627 		}
628 	term_all_flush();
629 
630 	if (term.md_cursor0 != term.md_cursor)
631 		{
632 		 if (term.md_cursor == CS_normal)
633 		  	term_tputs(term.t_normalcursor); else
634 		  	term_tputs(term.t_hidecursor);
635 
636 		 term.md_cursor0 = term.md_cursor;
637 		}
638 
639 	if (term.md_cursor == CS_hide)
640 		term_locate(0, term.sizex-1); else
641 		term_locate(y, x);
642 
643 	term_locate_flush();
644 	term_flush();
645 }
646 
term_csrn()647 void	term_csrn()
648 {
649 	term.md_cursor=CS_normal;
650 }
651 
term_csrh()652 void	term_csrh()
653 {
654 	term.md_cursor=CS_hide;
655 }
656 
term_ungetch(u_char c)657 void	term_ungetch(u_char c)
658 {
659 #ifdef	TIOCSTI
660 	ioctl(fileno(term.fp_tty), TIOCSTI, &c);
661 #else
662 	if (ungetnum >= sizeof(ungetbuf) / sizeof(u_char) - 1)
663 		return;
664 	ungetbuf[ungetnum++] = c;
665 #endif
666 }
667 
term_regetch(c)668 int 	term_regetch(c)
669 {
670 #ifndef	TIOCSTI
671 	if (ungetnum > 0)
672 		return (int)ungetbuf[--ungetnum];
673 #endif
674 
675 	return -1;
676 }
677 
678 
term_locate_flush()679 static	void	term_locate_flush()
680 {
681 	char	*p, *q, buf[LN_dispbuf+1];
682 	int 	n;
683 
684 	if (term.x==term.x0 && term.y==term.y0)
685 		return;
686 
687 //fprintf(stderr, "$ %d,%d -> %d,%d %d/%d"
688 // ,term.y0, term.x0, term.y, term.x, term.cl0, term.cl);
689 
690 	p=tgoto(term.cn_locate, term.x, term.y);
691 
692 //	term_tputs(p);
693 //	return;
694 
695 
696 	q=buf;
697 	n=strlen(p);
698 
699 	if (term.y0>term.y)
700 		goto failed;
701 
702 	if (term.x < term.x0)
703 		{
704 		 if (term.x0-term.x >= term.x+1)
705 		 	{
706 		 	 *q++='\r';
707 		 	 term.x0=0;
708 		 	 --n;
709 		 	} else
710 		 	{
711 		 	 while (n>0 && term.x0 > term.x)
712 		 	 	{
713 		 	 	 *q++='\b';
714 		 	 	 --term.x0;
715 		 	 	 --n;
716 		 	 	}
717 		 	}
718 		}
719 
720 	while (n>0 && term.y0 < term.y)
721 		{
722 		 *q++='\n';
723 		 ++term.y0;
724 		 --n;
725 		}
726 
727 	if (n<=0 || term.x0!=term.x || term.y0!=term.y)
728 		{
729 failed:
730 //fprintf(stderr, " ***\n");
731 		 term_tputs(p);
732 		}else
733 		{
734 		 *q='\0';
735 		 term_tputs(buf);
736 //		 fputs(buf, term.fp_tty);
737 //fprintf(stderr, "[%s]\n", buf);
738 		}
739 
740 	term.x0 = term.x;
741 	term.y0 = term.y;
742 }
743 
term_locate(int y,int x)744 void	term_locate(int y,int x)
745 {
746 	term.x=x;
747 	term.y=y;
748 }
749 
750 
751 
752 
753 
term_clrtoe()754 void	term_clrtoe()
755 {
756 	term_scr_clr(term.scr[term.y], term.x);
757 }
758 
759 #define	iseuc(c)	( (u_char)(c)>=0xa1 &&(u_char)(c)<=0xfe)
760 
nbytes(int c)761 static	int 	nbytes(int c)
762 {
763 	if (c==0)
764 		return 0;
765 
766 	if ((c&0xff)==0x8e)	// Ⱦ�Ѥ���
767 		return 2;
768 
769 	if ((c&0xff)==0x8f)
770 		return 2;
771 
772 	if ((c&0xff)>=0xa1 && (c&0xff)<=0xfe)
773 		return 2;
774 	return 1;
775 }
776 
777 
term_puts(const char * s)778 void	term_puts(const char *s)
779 {
780 	int 	n;
781 
782 	if (term.y>=term.sizey)
783 		return ;
784 
785 	if (term.x>0 && term.scr[term.y][term.x]==SCR_ignore)
786 		fprintf(stderr, "+");
787 
788 	if (term.x>0 && term.scr[term.y][term.x]==SCR_ignore)
789 		term.scr[term.y][term.x-1]= SCR_code(AC_normal, ' ');
790 
791 	while (*s!='\0' && term.x <term.sizex)
792 		{
793 // ctl code ����??
794 
795 		 if (nbytes(*s)==1)
796 		 	term.scr[term.y][term.x]= SCR_code(term.cl, *s&0xff); else
797 		 	{
798 		 	 if (term.x+1==term.sizex)
799 		 	 	break;
800 		 	 n=(*s&0xff)<<8 | (*(s+1)&0xff);
801 		 	 term.scr[term.y][term.x]= SCR_code(term.cl, n);
802 		 	 term.scr[term.y][++term.x]= SCR_ignore;
803 		 	 ++s;
804 		 	}
805 
806 		 ++term.x;
807 		 ++s;
808 		}
809 
810 	if (term.x<term.sizex && term.scr[term.y][term.x]==SCR_ignore)
811 		term.scr[term.y][term.x]= SCR_code(AC_normal, ' ');
812 }
813 
term_putch(int c)814 void	term_putch(int c)
815 {
816 	char	buf[1+1];
817 
818 	*buf=c&0xff;
819 	buf[1]='\0';
820 
821 	term_puts(buf);
822 }
823 
term_printf(const char * fmt,...)824 void	term_printf(const char *fmt, ...)
825 {
826 	va_list	args;
827 	char	buf[LN_dispbuf+1];
828 
829 	va_start(args,fmt);
830 	vsprintf(buf, fmt, args);
831 	va_end(args);
832 
833 	term_puts(buf);
834 }
835 
836 #define	isreverse(cl)	((cl)&AC_reverse)
837 #define	isunder(cl)		((cl)&AC_under)
838 #define	isbold(cl)		((cl)&AC_bold)
839 
840 
term_color_flush()841 static	void	term_color_flush()
842 {
843 /*	if (isunder(term.cl0) && !isunder(term.cl))
844 		{
845 		 term_tputs(term.end_underline);
846 		 if (strcmp(term.t_normal, term.end_underline)==0)
847 		 	term.cl0 =  AC_normal; else
848 		 	term.cl0 &= ~AC_under;
849 		}
850 */
851 	if (	(isunder(term.cl0) && !isunder(term.cl))     ||
852 			(isreverse(term.cl0) && !isreverse(term.cl)) ||
853 			(isbold(term.cl0)    && !isbold(term.cl))    )
854 		{
855 		 term_tputs(term.t_normal);
856 		 term.cl0=AC_normal;
857 		}
858 
859 	if (term.mode& TM_ansicolor)
860 		{
861 		 if (AC_color(term.cl0)!=AC_normal && AC_color(term.cl)==AC_normal)
862 		 	{
863 		 	 term_tputs(term.t_normal);
864 		 	 term.cl0=AC_normal;
865 		 	}
866 
867 		 if (AC_color(term.cl)!=AC_color(term.cl0))
868 		 	{
869 		 	 char	buf[20+1];
870 
871 		 	 sprintf(buf, "\x1b[3%dm", AC_color(term.cl)-8 );
872 		 	 term_tputs(buf);
873 		 	}
874 		}
875 
876 
877 	if (!isreverse(term.cl0)&&isreverse(term.cl))
878 		term_tputs(term.t_reverse);
879 	if (!isunder(term.cl0)&&isunder(term.cl))
880 		term_tputs(term.t_underline);
881 	if (!isbold(term.cl0)&&isbold(term.cl))
882 		term_tputs(term.t_bold);
883 
884 	term.cl0=term.cl;
885 }
886 
term_color(color_t cl)887 void	term_color(color_t cl)	{term.cl = cl;}
term_color_normal()888 void	term_color_normal()		{term.cl = AC_normal;}
889 
term_color_reverse()890 void	term_color_reverse()	{term.cl |= AC_reverse;}
term_color_underline()891 void	term_color_underline()	{term.cl |= AC_under;}
term_color_bold()892 void	term_color_bold()		{term.cl |= AC_bold;}
893 
894 
term_cftocol(const char * s)895 color_t	term_cftocol(const char *s)
896 {
897 	color_t	cl;
898 
899 	cl=AC_normal;
900 	if (s==NULL)
901 		return cl;
902 	for (;*s!='\0';++s)
903 		{
904 		 switch(toupper(*s))
905 		 	{
906 		  case 'U':
907 		  	 cl|=AC_under;
908 		  	 continue;
909 		  case 'R':
910 		  	 cl|=AC_reverse;
911 		  	 continue;
912 		  case 'B':
913 		  	 cl|=AC_bold;
914 		  	 continue;
915 		 	}
916 
917 		 if (isdigit(*s))
918 		 	cl |= AC_color(*s-'0'+8);
919 		}
920 	return cl;
921 }
922 
term_color_enable()923 void	term_color_enable()
924 {
925 	if ((term_getmode()& TM_ansicolor)==0)
926 		term_setmode(term_getmode()| TM_ansicolor);
927 }
928 
term_color_disable()929 void	term_color_disable()
930 {
931 	if ((term_getmode()& TM_ansicolor)!=0)
932 		term_setmode(term_getmode()& ~TM_ansicolor);
933 }
934 
term_scroll_dn(int n)935 static	void	term_scroll_dn(int n)
936 {
937 	char	buf[LN_dispbuf+1];
938 
939 	if (*term.ln_insert!='\0')
940 		{
941 //		 term_tparam(buf, term.ln_insert, n, 0);
942 //		 term_tputs(buf);
943 		 term_tputs(tparm(term.ln_insert, n));
944 		} else
945 		{
946 		 while (n-->0)
947 		 	term_tputs(term.l_insert);
948 		}
949 }
950 
term_scroll_up(int n)951 static	void	term_scroll_up(int n)
952 {
953 	char	buf[LN_dispbuf+1];
954 
955 	if (*term.ln_delete!='\0')
956 		{
957 //		 term_tparam(buf, term.ln_delete, n, 0);
958 //		 term_tputs(buf);
959 		 term_tputs(tparm(term.ln_delete, n));
960 		} else
961 		{
962 		 while (n-->0)
963 		 	term_tputs(term.l_delete);
964 		}
965 }
966 
967 
term_all_flush()968 static	void	term_all_flush()
969 {
970 	int 	i, j;
971 	int 	n;
972 	bool	f, cf;
973 	int 	x;
974 
975 	int		*p, *p0;
976 
977 	if (term.f_cls)
978 		{
979 		 term_color_normal();
980 		 term_color_flush();
981 		 term_tputs(term.t_clear);
982 
983 		 term.x  = 0;
984 		 term.y  = 0;
985 		 term.x0 = 0;
986 		 term.y0 = 0;
987 
988 		 for (i=0; i<term.sizey; ++i)
989 		 	term_scr_clr(term.scr0[i], 0);
990 		 term.f_cls=FALSE;
991 		}
992 
993 	for (i=0; i<term.sizey; ++i)
994 		{
995 		 if (term.tq[i]>0)
996 		 	{
997 		 	 term_color_normal();
998 		 	 term_color_flush();
999 		 	 term_locate(i, 0);
1000 		 	 term_locate_flush();
1001 		 	 term_scroll_dn(term.tq[i]);
1002 
1003 		 	 while(term.tq[i]>0)
1004 		 	 	{
1005 		 	 	 void	*p;
1006 
1007 		 	 	 p=term.scr0[term.sizey-1];
1008 
1009 		 	 	 memmove(term.scr0+i+1, term.scr0+i,
1010 		 	 	   sizeof(void *)* (term.sizey-i-1));
1011 
1012 		 	 	 term.scr0[i]=p;
1013 		 		 term_scr_clr(term.scr0[i], 0);
1014 		 		 --term.tq[i];
1015 		 	 	}
1016 		 	}
1017 
1018 		 if (term.tq[i]<0)
1019 		 	{
1020 		 	 term_color_normal();
1021 		 	 term_color_flush();
1022 		 	 term_locate(i, 0);
1023 		 	 term_locate_flush();
1024 		 	 term_scroll_up(0-term.tq[i]);
1025 
1026 		 	 while(term.tq[i]<0)
1027 		 	 	{
1028 		 	 	 void	*p;
1029 
1030 		 	 	 p=term.scr0[i];
1031 
1032 		 	 	 memmove(term.scr0+i, term.scr0+i+1,
1033 		 	 	   sizeof(void *)* (term.sizey-i-1));
1034 
1035 		 	 	 term.scr0[term.sizey-1]=p;
1036 		 		 term_scr_clr(term.scr0[term.sizey-1], 0);
1037 		 		 ++term.tq[i];
1038 		 	 	}
1039 		 	}
1040 		}
1041 
1042 
1043 	for (term.y=0; term.y<term.sizey; ++term.y)
1044 		{
1045 //fprintf(stderr, "\n%d:\n", term.y);
1046 		 term.x=0;
1047 
1048 		 cf=FALSE;
1049 		 for (n=term.sizex; n>0; --n)
1050 		 	{
1051 		 	 if (term.scr[term.y][n-1] != SCR_code(AC_normal, ' '))
1052 		 	 	break;
1053 
1054 		 	 if (term.scr[term.y][n-1] != term.scr0[term.y][n-1])
1055 		 	 	cf=TRUE;
1056 		 	}
1057 
1058 		 p =term.scr [term.y];
1059 		 p0=term.scr0[term.y];
1060 
1061 		 while(term.x<n)
1062 		 	{
1063 		 	 int 	x;
1064 
1065 //fprintf(stderr, "%d ", term.x);
1066 		 	 f=FALSE;
1067 		 	 x=term.x;
1068 		 	 if (nbytes((p[x]&0xff00)>>8)==2 || nbytes((p0[x]&0xff00)>>8)==2)
1069 		 	 	{
1070 		 	 	 while(nbytes((p[x]&0xff00)>>8)==2 || nbytes((p0[x]&0xff00)>>8)==2)
1071 		 	 	 	{
1072 		 	 	 	 if (p[x]!=p0[x])
1073 		 	 	 	 	f=TRUE;
1074 		 	 	 	 ++x;
1075 		 	 	 	}
1076 		 	 	} else
1077 		 	 	{
1078 		 	 	 while(x<n && nbytes((p[x]&0xff00)>>8)!=2 && nbytes((p0[x]&0xff00)>>8)!=2)
1079 		 	 	 	{
1080 		 	 	 	 if (!f && p[x]!=p0[x])
1081 		 	 	 	 	{
1082 		 	 	 	 	 term.x=x;
1083 		 	 	 	 	 f=TRUE;
1084 		 	 	 	 	}
1085 		 	 	 	 if (f && p[x]==p0[x])
1086 		 	 	 	 	break;
1087 		 	 	 	 ++x;
1088 		 	 	 	}
1089 		 	 	}
1090 
1091 		 	 if (x>n)
1092 		 	 	x=n;	// error
1093 
1094 		 	 if (!f)
1095 		 	 	{
1096 		 	 	 term.x=x;
1097 		 	 	 continue;
1098 		 	 	}
1099 
1100 		 	 term_locate_flush();
1101 		 	 while(term.x<x)
1102 		 	 	{
1103 		 	 	 int 	c;
1104 
1105 		  	 	 term_color(SCR_color(p[term.x]));
1106 		  	 	 term_color_flush();
1107 
1108 		 	 	 c=SCR_char(p[term.x]);
1109 		 		 if ((c&0xffff00)==0)
1110 		 		 	fputc(c, term.fp_tty); else
1111 		 		 	{
1112 		 		 	 fputc((c&0xff00)>>8, term.fp_tty);
1113 		 		 	 fputc(c&0xff, term.fp_tty);
1114 		 	 	 	 p0[term.x]=p[term.x];
1115 		 		 	 ++term.x0;
1116 		 		 	 ++term.x;
1117 		 		 	}
1118 		 	 	 p0[term.x]=p[term.x];
1119 		 	 	 ++term.x0;
1120 		 	 	 ++term.x;
1121 		 	 	}
1122 		 	}
1123 
1124 		 if (cf)
1125 		 	{
1126 		 	 term_locate_flush();
1127 		 	 term_color(AC_normal);
1128 		 	 term_color_flush();
1129 		 	 term_tputs(term.l_clear);
1130 
1131 		 	 term_scr_clr(p0, n);
1132 		 	}
1133 		}
1134 	term_flush();
1135 }
1136 
1137