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