1 /* $Id: terms.c,v 1.57 2007/05/30 04:44:00 inu Exp $ */
3 * An original curses library for EUC-kanji by Akinori ITO, December 1989
4 * revised by Akinori ITO, January 1995
15 #ifdef HAVE_SYS_SELECT_H
16 #include <sys/select.h>
18 #ifndef __MINGW32_VERSION
19 #include <sys/ioctl.h>
22 #endif /* __MINGW32_VERSION */
28 #include <osreldate.h>
29 #if (__FreeBSD_version >= 400017)
30 #include <sys/consio.h>
33 #include <machine/console.h>
35 int (*sysm_handler) (int x, int y, int nbs, int obs);
36 static int cwidth = 8, cheight = 16;
37 static int xpix, ypix, nbs, obs = 0;
38 #endif /* use_SYSMOUSE */
40 static int is_xterm = 0;
42 void mouse_init(), mouse_end();
44 #endif /* USE_MOUSE */
46 static char *title_str = NULL;
59 #if defined(__CYGWIN__)
61 #include <sys/cygwin.h>
62 static int isWinConsole = 0;
64 #define TERM_CYGWIN_RESERVE_IME 2
65 static int isLocalConsole = 0;
67 #if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE)
68 int cygwin_mouse_btn_swapped = 0;
71 #if defined(SUPPORT_WIN9X_CONSOLE_MBCS)
72 static HANDLE hConIn = INVALID_HANDLE_VALUE;
73 static int isWin95 = 0;
75 static int iConIn, nConIn, nConInMax;
80 OSVERSIONINFO winVersionInfo;
82 winVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
83 if (GetVersionEx(&winVersionInfo) == 0) {
84 fprintf(stderr, "can't get Windows version information.\n");
87 if (winVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
96 enable_win9x_console_input(void)
98 if (isWin95 && isWinConsole && isLocalConsole &&
99 hConIn == INVALID_HANDLE_VALUE) {
100 hConIn = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
101 FILE_SHARE_READ | FILE_SHARE_WRITE,
102 NULL, OPEN_EXISTING, 0, NULL);
103 if (hConIn != INVALID_HANDLE_VALUE) {
110 disable_win9x_console_input(void)
112 if (hConIn != INVALID_HANDLE_VALUE) {
114 hConIn = INVALID_HANDLE_VALUE;
119 expand_win32_console_input_buffer(int n)
121 if (nConIn + n >= nConInMax) {
124 nConInMax = ((nConIn + n) / 2 + 1) * 3;
126 ConInV = GC_MALLOC_ATOMIC(nConInMax);
127 memcpy(ConInV, oldv, nConIn);
132 read_win32_console_input(void)
137 if (PeekConsoleInput(hConIn, &rec, 1, &nevents) && nevents) {
138 switch (rec.EventType) {
140 expand_win32_console_input_buffer(3);
142 if (ReadConsole(hConIn, &ConInV[nConIn], 1, &nevents, NULL)) {
152 ReadConsoleInput(hConIn, &rec, 1, &nevents);
158 read_win32_console(char *s, int n)
160 KEY_EVENT_RECORD *ker;
162 if (hConIn == INVALID_HANDLE_VALUE)
163 return read(tty, s, n);
167 if (iConIn < nConIn) {
168 if (n > nConIn - iConIn)
171 memcpy(s, ConInV, n);
173 if ((iConIn += n) >= nConIn)
181 while (!read_win32_console_input()) ;
187 #endif /* SUPPORT_WIN9X_CONSOLE_MBCS */
192 #define MY_BUFSIZE 1024
194 char pszNewWindowTitle[MY_BUFSIZE];
195 char pszOldWindowTitle[MY_BUFSIZE];
197 GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
198 wsprintf(pszNewWindowTitle, "%d/%d",
199 GetTickCount(), GetCurrentProcessId());
200 SetConsoleTitle(pszNewWindowTitle);
202 hwndFound = FindWindow(NULL, pszNewWindowTitle);
203 SetConsoleTitle(pszOldWindowTitle);
207 #if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE)
211 struct per_process *p;
213 p = (struct per_process *)cygwin_internal(CW_USER_DATA);
215 return (p->dll_major * 1000) + p->dll_minor;
222 check_cygwin_console(void)
224 char *term = getenv("TERM");
229 if (term && strncmp(term, "cygwin", 6) == 0) {
230 isWinConsole = TERM_CYGWIN;
233 hWnd = GetConsoleHwnd();
234 if (hWnd != INVALID_HANDLE_VALUE) {
235 if (IsWindowVisible(hWnd)) {
239 if (strncmp(getenv("LANG"), "ja", 2) == 0) {
240 isWinConsole = TERM_CYGWIN_RESERVE_IME;
242 #ifdef SUPPORT_WIN9X_CONSOLE_MBCS
244 if (isWin95 && ttyslot() != -1) {
249 #if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE)
250 if (cygwin_version() <= 1003015) {
251 /* cygwin DLL 1.3.15 or earler */
252 cygwin_mouse_btn_swapped = 1;
256 #endif /* __CYGWIN__ */
258 char *getenv(const char *);
259 MySignalHandler reset_exit(SIGNAL_ARG), error_dump(SIGNAL_ARG);
260 void setlinescols(void);
264 #define SIGIOT SIGABRT
265 #endif /* not SIGIOT */
269 typedef struct termio TerminalMode;
270 #define TerminalSet(fd,x) ioctl(fd,TCSETA,x)
271 #define TerminalGet(fd,x) ioctl(fd,TCGETA,x)
272 #define MODEFLAG(d) ((d).c_lflag)
273 #define IMODEFLAG(d) ((d).c_iflag)
274 #endif /* HAVE_TERMIO_H */
276 #ifdef HAVE_TERMIOS_H
279 typedef struct termios TerminalMode;
280 #define TerminalSet(fd,x) tcsetattr(fd,TCSANOW,x)
281 #define TerminalGet(fd,x) tcgetattr(fd,x)
282 #define MODEFLAG(d) ((d).c_lflag)
283 #define IMODEFLAG(d) ((d).c_iflag)
284 #endif /* HAVE_TERMIOS_H */
288 typedef struct sgttyb TerminalMode;
289 #define TerminalSet(fd,x) ioctl(fd,TIOCSETP,x)
290 #define TerminalGet(fd,x) ioctl(fd,TIOCGETP,x)
291 #define MODEFLAG(d) ((d).sg_flags)
292 #endif /* HAVE_SGTTY_H */
294 #ifdef __MINGW32_VERSION
296 typedef unsigned char cc_t;
297 typedef unsigned int speed_t;
298 typedef unsigned int tcflag_t;
303 tcflag_t c_iflag; /* input mode flags */
304 tcflag_t c_oflag; /* output mode flags */
305 tcflag_t c_cflag; /* control mode flags */
306 tcflag_t c_lflag; /* local mode flags */
307 cc_t c_line; /* line discipline */
308 cc_t c_cc[NCCS]; /* control characters */
309 speed_t c_ispeed; /* input speed */
310 speed_t c_ospeed; /* output speed */
312 typedef struct termios TerminalMode;
313 #define TerminalSet(fd,x) (0)
314 #define TerminalGet(fd,x) (0)
315 #define MODEFLAG(d) (0)
328 #endif /* __MINGW32_VERSION */
331 #define MAX_COLUMN 400
333 /* Screen properties */
334 #define S_SCREENPROP 0x0f
335 #define S_NORMAL 0x00
336 #define S_STANDOUT 0x01
337 #define S_UNDERLINE 0x02
341 /* Sort of Character */
342 #define C_WHICHCHAR 0xc0
345 #define C_WCHAR1 0x40
346 #define C_WCHAR2 0x80
350 #define CHMODE(c) ((c)&C_WHICHCHAR)
351 #define SETCHMODE(var,mode) ((var) = (((var)&~C_WHICHCHAR) | mode))
353 #define SETCH(var,ch,len) ((var) = New_Reuse(char, (var), (len) + 1), \
354 strncpy((var), (ch), (len)), (var)[len] = '\0')
356 #define SETCH(var,ch,len) ((var) = (ch))
359 /* Charactor Color */
360 #define COL_FCOLOR 0xf00
361 #define COL_FBLACK 0x800
362 #define COL_FRED 0x900
363 #define COL_FGREEN 0xa00
364 #define COL_FYELLOW 0xb00
365 #define COL_FBLUE 0xc00
366 #define COL_FMAGENTA 0xd00
367 #define COL_FCYAN 0xe00
368 #define COL_FWHITE 0xf00
369 #define COL_FTERM 0x000
371 #define S_COLORED 0xf00
374 /* Background Color */
375 #define COL_BCOLOR 0xf000
376 #define COL_BBLACK 0x8000
377 #define COL_BRED 0x9000
378 #define COL_BGREEN 0xa000
379 #define COL_BYELLOW 0xb000
380 #define COL_BBLUE 0xc000
381 #define COL_BMAGENTA 0xd000
382 #define COL_BCYAN 0xe000
383 #define COL_BWHITE 0xf000
384 #define COL_BTERM 0x0000
386 #define S_BCOLORED 0xf000
387 #endif /* USE_BG_COLOR */
390 #define S_GRAPHICS 0x10
394 #define SETPROP(var,prop) (var = (((var)&S_DIRTY) | prop))
398 #define L_UNUSED 0x02
399 #define L_NEED_CE 0x04
400 #define L_CLRTOEOL 0x08
402 #define ISDIRTY(d) ((d) & L_DIRTY)
403 #define ISUNUSED(d) ((d) & L_UNUSED)
404 #define NEED_CE(d) ((d) & L_NEED_CE)
406 typedef unsigned short l_prop;
408 typedef struct scline {
419 static TerminalMode d_ioval;
421 static FILE *ttyf = NULL;
424 char bp[1024], funcstr[256];
426 char *T_cd, *T_ce, *T_kr, *T_kl, *T_cr, *T_bt, *T_ta, *T_sc, *T_rc,
427 *T_so, *T_se, *T_us, *T_ue, *T_cl, *T_cm, *T_al, *T_sr, *T_md, *T_me,
428 *T_ti, *T_te, *T_nd, *T_as, *T_ae, *T_eA, *T_ac, *T_op;
431 #if defined(__CYGWIN__)
433 #endif /* defined(__CYGWIN__) */
435 static int max_LINES = 0, max_COLS = 0;
436 static int tab_step = 8;
437 static int CurLine, CurColumn;
438 static Screen *ScreenElem = NULL, **ScreenImage = NULL;
439 static l_prop CurrentMode = 0;
440 static int graph_enabled = 0;
442 static char gcmap[96];
444 extern int tgetent(char *, char *);
445 extern int tgetnum(char *);
446 extern int tgetflag(char *);
447 extern char *tgetstr(char *, char **);
448 extern char *tgoto(char *, int, int);
449 extern int tputs(char *, int, int (*)(char));
450 void clear(), wrap(), touch_line(), touch_column(int);
452 void need_clrtoeol(void);
454 void clrtoeol(void); /* conflicts with curs_clear(3)? */
456 static int write1(char);
464 #define MOVE(line,column) writestr(tgoto(T_cm,column,line));
467 #define W3M_TERM_INFO(name, title, mouse) name, title, mouse
468 #define NEED_XTERM_ON (1)
469 #define NEED_XTERM_OFF (1<<1)
471 #define NEED_CYGWIN_ON (1<<2)
472 #define NEED_CYGWIN_OFF (1<<3)
475 #define W3M_TERM_INFO(name, title, mouse) name, title
478 static char XTERM_TITLE[] = "\033]0;w3m: %s\007";
479 static char SCREEN_TITLE[] = "\033k%s\033\134";
481 static char CYGWIN_TITLE[] = "w3m: %s";
485 static struct w3m_term_info {
491 } w3m_term_info_list[] = {
492 {W3M_TERM_INFO("xterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))},
493 {W3M_TERM_INFO("kterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))},
494 {W3M_TERM_INFO("rxvt", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))},
495 {W3M_TERM_INFO("Eterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))},
496 {W3M_TERM_INFO("mlterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))},
497 {W3M_TERM_INFO("screen", SCREEN_TITLE, 0)},
499 {W3M_TERM_INFO("cygwin", CYGWIN_TITLE, (NEED_CYGWIN_ON|NEED_CYGWIN_OFF))},
501 {W3M_TERM_INFO(NULL, NULL, 0)}
511 if (isatty(0)) /* stdin */
515 tty = open(ttyn, O_RDWR);
517 /* use stderr instead of stdin... is it OK???? */
520 ttyf = fdopen(tty, "w");
522 check_cygwin_console();
524 TerminalGet(tty, &d_ioval);
525 if (displayTitleTerm != NULL) {
526 struct w3m_term_info *p;
527 for (p = w3m_term_info_list; p->term != NULL; p++) {
528 if (!strncmp(displayTitleTerm, p->term, strlen(p->term))) {
529 title_str = p->title_str;
536 char *term = getenv("TERM");
538 struct w3m_term_info *p;
539 for (p = w3m_term_info_list; p->term != NULL; p++) {
540 if (!strncmp(term, p->term, strlen(p->term))) {
541 is_xterm = p->mouse_flag;
552 ttymode_set(int mode, int imode)
554 #ifndef __MINGW32_VERSION
557 TerminalGet(tty, &ioval);
558 MODEFLAG(ioval) |= mode;
560 IMODEFLAG(ioval) |= imode;
561 #endif /* not HAVE_SGTTY_H */
563 while (TerminalSet(tty, &ioval) == -1) {
564 if (errno == EINTR || errno == EAGAIN)
566 printf("Error occured while set %x: errno=%d\n", mode, errno);
567 reset_exit(SIGNAL_ARGLIST);
573 ttymode_reset(int mode, int imode)
575 #ifndef __MINGW32_VERSION
578 TerminalGet(tty, &ioval);
579 MODEFLAG(ioval) &= ~mode;
581 IMODEFLAG(ioval) &= ~imode;
582 #endif /* not HAVE_SGTTY_H */
584 while (TerminalSet(tty, &ioval) == -1) {
585 if (errno == EINTR || errno == EAGAIN)
587 printf("Error occured while reset %x: errno=%d\n", mode, errno);
588 reset_exit(SIGNAL_ARGLIST);
590 #endif /* __MINGW32_VERSION */
595 set_cc(int spec, int val)
599 TerminalGet(tty, &ioval);
600 ioval.c_cc[spec] = val;
601 while (TerminalSet(tty, &ioval) == -1) {
602 if (errno == EINTR || errno == EAGAIN)
604 printf("Error occured: errno=%d\n", errno);
605 reset_exit(SIGNAL_ARGLIST);
608 #endif /* not HAVE_SGTTY_H */
626 writestr(T_op); /* turn off */
628 if (!Do_not_use_ti_te) {
634 writestr(T_se); /* reset terminal */
636 TerminalSet(tty, &d_ioval);
641 reset_exit(SIGNAL_ARG)
646 #endif /* USE_MOUSE */
653 error_dump(SIGNAL_ARG)
655 mySignal(SIGIOT, SIG_DFL);
664 mySignal(SIGHUP, reset_exit);
665 mySignal(SIGINT, reset_exit);
666 mySignal(SIGQUIT, reset_exit);
667 mySignal(SIGTERM, reset_exit);
668 mySignal(SIGILL, error_dump);
669 mySignal(SIGIOT, error_dump);
670 mySignal(SIGFPE, error_dump);
672 mySignal(SIGBUS, error_dump);
674 /* mySignal(SIGSEGV, error_dump); */
683 for (c = 0; c < 96; c++)
684 gcmap[c] = (char)(c + ' ');
690 for (i = 0; i < n - 1; i += 2) {
691 c = (unsigned)T_ac[i] - ' ';
692 if (c >= 0 && c < 96)
693 gcmap[c] = T_ac[i + 1];
697 #define graphchar(c) (((unsigned)(c)>=' ' && (unsigned)(c)<128)? gcmap[(c)-' '] : (c))
698 #define GETSTR(v,s) {v = pt; suc = tgetstr(s,&pt); if (!suc) v = ""; else v = allocStr(suc, -1); }
708 ent = getenv("TERM") ? getenv("TERM") : DEFAULT_TERM;
710 fprintf(stderr, "TERM is not set\n");
711 reset_exit(SIGNAL_ARGLIST);
714 r = tgetent(bp, ent);
716 /* Can't find termcap entry */
717 fprintf(stderr, "Can't find termcap entry %s\n", ent);
718 reset_exit(SIGNAL_ARGLIST);
721 GETSTR(T_ce, "ce"); /* clear to the end of line */
722 GETSTR(T_cd, "cd"); /* clear to the end of display */
723 GETSTR(T_kr, "nd"); /* cursor right */
727 T_kl = "\b"; /* cursor left */
735 GETSTR(T_cr, "cr"); /* carriage return */
736 GETSTR(T_ta, "ta"); /* tab */
737 GETSTR(T_sc, "sc"); /* save cursor */
738 GETSTR(T_rc, "rc"); /* restore cursor */
739 GETSTR(T_so, "so"); /* standout mode */
740 GETSTR(T_se, "se"); /* standout mode end */
741 GETSTR(T_us, "us"); /* underline mode */
742 GETSTR(T_ue, "ue"); /* underline mode end */
743 GETSTR(T_md, "md"); /* bold mode */
744 GETSTR(T_me, "me"); /* bold mode end */
745 GETSTR(T_cl, "cl"); /* clear screen */
746 GETSTR(T_cm, "cm"); /* cursor move */
747 GETSTR(T_al, "al"); /* append line */
748 GETSTR(T_sr, "sr"); /* scroll reverse */
749 GETSTR(T_ti, "ti"); /* terminal init */
750 GETSTR(T_te, "te"); /* terminal end */
751 GETSTR(T_nd, "nd"); /* move right one space */
752 GETSTR(T_eA, "eA"); /* enable alternative charset */
753 GETSTR(T_as, "as"); /* alternative (graphic) charset start */
754 GETSTR(T_ae, "ae"); /* alternative (graphic) charset end */
755 GETSTR(T_ac, "ac"); /* graphics charset pairs */
756 GETSTR(T_op, "op"); /* set default color pair to its original value */
757 #if defined( CYGWIN ) && CYGWIN < 1
758 /* for TERM=pcansi on MS-DOS prompt. */
763 T_ac = "l\001k\002m\003j\004x\005q\006n\020a\024v\025w\026u\027t\031";
788 if (getenv("WINDOWID")) {
789 FILE *fd = popen("scrsize", "rt");
791 fscanf(fd, "%i %i", &COLS, &LINES);
796 #elif defined(HAVE_TERMIOS_H) && defined(TIOCGWINSZ)
799 i = ioctl(tty, TIOCGWINSZ, &wins);
800 if (i >= 0 && wins.ws_row != 0 && wins.ws_col != 0) {
804 #endif /* defined(HAVE-TERMIOS_H) && defined(TIOCGWINSZ) */
805 if (LINES <= 0 && (p = getenv("LINES")) != NULL && (i = atoi(p)) >= 0)
807 if (COLS <= 0 && (p = getenv("COLUMNS")) != NULL && (i = atoi(p)) >= 0)
810 LINES = tgetnum("li"); /* number of line */
812 COLS = tgetnum("co"); /* number of column */
813 if (COLS > MAX_COLUMN)
815 if (LINES > MAX_LINE)
817 #if defined(__CYGWIN__)
818 LASTLINE = LINES - (isWinConsole == TERM_CYGWIN_RESERVE_IME ? 2 : 1);
819 #endif /* defined(__CYGWIN__) */
827 if (LINES + 1 > max_LINES) {
828 max_LINES = LINES + 1;
830 ScreenElem = New_N(Screen, max_LINES);
831 ScreenImage = New_N(Screen *, max_LINES);
833 if (COLS + 1 > max_COLS) {
835 for (i = 0; i < max_LINES; i++) {
837 ScreenElem[i].lineimage = New_N(char *, max_COLS);
838 bzero((void *)ScreenElem[i].lineimage, max_COLS * sizeof(char *));
840 ScreenElem[i].lineimage = New_N(char, max_COLS);
842 ScreenElem[i].lineprop = New_N(l_prop, max_COLS);
845 for (i = 0; i < LINES; i++) {
846 ScreenImage[i] = &ScreenElem[i];
847 ScreenImage[i]->lineprop[0] = S_EOL;
848 ScreenImage[i]->isdirty = 0;
850 for (; i < max_LINES; i++) {
851 ScreenElem[i].isdirty = L_UNUSED;
867 if (T_ti && !Do_not_use_ti_te)
879 #endif /* SCREEN_DEBUG */
884 move(int line, int column)
886 if (line >= 0 && line < LINES)
888 if (column >= 0 && column < COLS)
893 #define M_SPACE (S_SCREENPROP|S_COLORED|S_BCOLORED|S_GRAPHICS)
894 #else /* not USE_BG_COLOR */
895 #define M_SPACE (S_SCREENPROP|S_COLORED|S_GRAPHICS)
896 #endif /* not USE_BG_COLOR */
900 need_redraw(char *c1, l_prop pr1, char *c2, l_prop pr2)
902 if (!c1 || !c2 || strcmp(c1, c2))
906 need_redraw(char c1, l_prop pr1, char c2, l_prop pr2)
912 return (pr1 ^ pr2) & M_SPACE & ~S_DIRTY;
914 if ((pr1 ^ pr2) & ~S_DIRTY)
920 #define M_CEOL (~(M_SPACE|C_WHICHCHAR))
936 addmch(char *pc, size_t len)
946 static Str tmp = NULL;
949 int width = wtf_width((wc_uchar *) pc);
953 Strcopy_charp_n(tmp, pc, len);
960 if (CurColumn == COLS)
962 if (CurColumn >= COLS)
964 p = ScreenImage[CurLine]->lineimage;
965 pr = ScreenImage[CurLine]->lineprop;
966 dirty = &ScreenImage[CurLine]->isdirty;
969 /* Eliminate unprintables according to * iso-8859-*.
970 * Particularly 0x96 messes up T.Dickey's * (xfree-)xterm */
975 if (pr[CurColumn] & S_EOL) {
976 if (c == ' ' && !(CurrentMode & M_SPACE)) {
980 for (i = CurColumn; i >= 0 && (pr[i] & S_EOL); i--) {
981 SETCH(p[i], SPACE, 1);
982 SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII);
986 if (c == '\t' || c == '\n' || c == '\r' || c == '\b')
987 SETCHMODE(CurrentMode, C_CTRL);
990 SETCHMODE(CurrentMode, C_WCHAR1);
992 else if (!IS_CNTRL(c))
993 SETCHMODE(CurrentMode, C_ASCII);
997 /* Required to erase bold or underlined character for some * terminal
1000 i = CurColumn + width - 1;
1005 (((pr[i] & S_BOLD) && need_redraw(p[i], pr[i], pc, CurrentMode)) ||
1006 ((pr[i] & S_UNDERLINE) && !(CurrentMode & S_UNDERLINE)))) {
1011 if (pr[i] & S_EOL) {
1012 SETCH(p[i], SPACE, 1);
1013 SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII);
1017 for (i++; i < COLS && CHMODE(pr[i]) == C_WCHAR2; i++)
1025 if (CurColumn + width > COLS) {
1027 for (i = CurColumn; i < COLS; i++) {
1028 SETCH(p[i], SPACE, 1);
1029 SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII);
1033 if (CurColumn + width > COLS)
1035 p = ScreenImage[CurLine]->lineimage;
1036 pr = ScreenImage[CurLine]->lineprop;
1038 if (CHMODE(pr[CurColumn]) == C_WCHAR2) {
1040 for (i = CurColumn - 1; i >= 0; i--) {
1041 l_prop l = CHMODE(pr[i]);
1042 SETCH(p[i], SPACE, 1);
1043 SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII);
1050 if (CHMODE(CurrentMode) != C_CTRL) {
1051 if (need_redraw(p[CurColumn], pr[CurColumn], pc, CurrentMode)) {
1052 SETCH(p[CurColumn], pc, len);
1053 SETPROP(pr[CurColumn], CurrentMode);
1055 touch_column(CurColumn);
1057 SETCHMODE(CurrentMode, C_WCHAR2);
1058 for (i = CurColumn + 1; i < CurColumn + width; i++) {
1059 SETCH(p[i], SPACE, 1);
1060 SETPROP(pr[i], (pr[CurColumn] & ~C_WHICHCHAR) | C_WCHAR2);
1063 for (; i < COLS && CHMODE(pr[i]) == C_WCHAR2; i++) {
1064 SETCH(p[i], SPACE, 1);
1065 SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII);
1075 else if (c == '\t') {
1076 dest = (CurColumn + tab_step) / tab_step * tab_step;
1081 p = ScreenImage[CurLine]->lineimage;
1082 pr = ScreenImage[CurLine]->lineprop;
1084 for (i = CurColumn; i < dest; i++) {
1085 if (need_redraw(p[i], pr[i], SPACE, CurrentMode)) {
1086 SETCH(p[i], SPACE, 1);
1087 SETPROP(pr[i], CurrentMode);
1094 else if (c == '\n') {
1097 else if (c == '\r') { /* Carriage return */
1100 else if (c == '\b' && CurColumn > 0) { /* Backspace */
1103 while (CurColumn > 0 && CHMODE(pr[CurColumn]) == C_WCHAR2)
1112 if (CurLine == LASTLINE)
1119 touch_column(int col)
1121 if (col >= 0 && col < COLS)
1122 ScreenImage[CurLine]->lineprop[col] |= S_DIRTY;
1128 if (!(ScreenImage[CurLine]->isdirty & L_DIRTY)) {
1130 for (i = 0; i < COLS; i++)
1131 ScreenImage[CurLine]->lineprop[i] &= ~S_DIRTY;
1132 ScreenImage[CurLine]->isdirty |= L_DIRTY;
1140 CurrentMode |= S_STANDOUT;
1146 CurrentMode &= ~S_STANDOUT;
1155 l_prop *pr = ScreenImage[CurLine]->lineprop;
1156 pr[CurColumn] ^= S_STANDOUT;
1158 if (CHMODE(pr[CurColumn]) != C_WCHAR2) {
1159 for (i = CurColumn + 1; CHMODE(pr[i]) == C_WCHAR2; i++)
1160 pr[i] ^= S_STANDOUT;
1168 CurrentMode |= S_BOLD;
1174 CurrentMode &= ~S_BOLD;
1180 CurrentMode |= S_UNDERLINE;
1186 CurrentMode &= ~S_UNDERLINE;
1192 CurrentMode |= S_GRAPHICS;
1198 CurrentMode &= ~S_GRAPHICS;
1204 if (!UseGraphicChar)
1206 return T_as[0] != 0 && T_ae[0] != 0 && T_ac[0] != 0;
1210 setfcolor(int color)
1212 CurrentMode &= ~COL_FCOLOR;
1213 if ((color & 0xf) <= 7)
1214 CurrentMode |= (((color & 7) | 8) << 8);
1218 color_seq(int colmode)
1220 static char seqbuf[32];
1221 sprintf(seqbuf, "\033[%dm", ((colmode >> 8) & 7) + 30);
1227 setbcolor(int color)
1229 CurrentMode &= ~COL_BCOLOR;
1230 if ((color & 0xf) <= 7)
1231 CurrentMode |= (((color & 7) | 8) << 12);
1235 bcolor_seq(int colmode)
1237 static char seqbuf[32];
1238 sprintf(seqbuf, "\033[%dm", ((colmode >> 12) & 7) + 40);
1241 #endif /* USE_BG_COLOR */
1243 #define RF_NEED_TO_MOVE 0
1245 #define RF_NONEED_TO_MOVE 2
1247 #define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_BCOLORED|S_GRAPHICS)
1248 #else /* not USE_BG_COLOR */
1249 #define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_GRAPHICS)
1250 #endif /* not USE_BG_COLOR */
1254 int line, col, pcol;
1255 int pline = CurLine;
1256 int moved = RF_NEED_TO_MOVE;
1262 l_prop *pr, mode = 0;
1263 l_prop color = COL_FTERM;
1265 l_prop bcolor = COL_BTERM;
1266 #endif /* USE_BG_COLOR */
1270 wc_putc_init(InnerCharset, DisplayCharset);
1272 for (line = 0; line <= LASTLINE; line++) {
1273 dirty = &ScreenImage[line]->isdirty;
1274 if (*dirty & L_DIRTY) {
1276 pc = ScreenImage[line]->lineimage;
1277 pr = ScreenImage[line]->lineprop;
1278 for (col = 0; col < COLS && !(pr[col] & S_EOL); col++) {
1279 if (*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) {
1280 if (need_redraw(pc[col], pr[col], SPACE, 0))
1284 if (pr[col] & S_DIRTY)
1288 if (*dirty & (L_NEED_CE | L_CLRTOEOL)) {
1289 pcol = ScreenImage[line]->eol;
1291 *dirty &= ~(L_NEED_CE | L_CLRTOEOL);
1298 if (line < LINES - 2 && pline == line - 1 && pcol == 0) {
1300 case RF_NEED_TO_MOVE:
1308 case RF_NONEED_TO_MOVE:
1317 if (*dirty & (L_NEED_CE | L_CLRTOEOL)) {
1324 for (; col < COLS; col++) {
1325 if (pr[col] & S_EOL)
1329 * some terminal emulators do linefeed when a
1330 * character is put on COLS-th column. this behavior
1331 * is different from one of vt100, but such terminal
1332 * emulators are used as vt100-compatible
1333 * emulators. This behaviour causes scroll when a
1334 * character is drawn on (COLS-1,LINES-1) point. To
1335 * avoid the scroll, I prohibit to draw character on
1338 #if !defined(USE_BG_COLOR) || defined(__CYGWIN__)
1342 if (line == LINES - 1 && col == COLS - 1)
1344 #endif /* !defined(USE_BG_COLOR) || defined(__CYGWIN__) */
1345 if ((!(pr[col] & S_STANDOUT) && (mode & S_STANDOUT)) ||
1346 (!(pr[col] & S_UNDERLINE) && (mode & S_UNDERLINE)) ||
1347 (!(pr[col] & S_BOLD) && (mode & S_BOLD)) ||
1348 (!(pr[col] & S_COLORED) && (mode & S_COLORED))
1350 || (!(pr[col] & S_BCOLORED) && (mode & S_BCOLORED))
1351 #endif /* USE_BG_COLOR */
1352 || (!(pr[col] & S_GRAPHICS) && (mode & S_GRAPHICS))) {
1353 if ((mode & S_COLORED)
1355 || (mode & S_BCOLORED)
1356 #endif /* USE_BG_COLOR */
1359 if (mode & S_GRAPHICS)
1364 if ((*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) ?
1365 need_redraw(pc[col], pr[col], SPACE,
1366 0) : (pr[col] & S_DIRTY)) {
1367 if (pcol == col - 1)
1369 else if (pcol != col)
1372 if ((pr[col] & S_STANDOUT) && !(mode & S_STANDOUT)) {
1376 if ((pr[col] & S_UNDERLINE) && !(mode & S_UNDERLINE)) {
1378 mode |= S_UNDERLINE;
1380 if ((pr[col] & S_BOLD) && !(mode & S_BOLD)) {
1384 if ((pr[col] & S_COLORED) && (pr[col] ^ mode) & COL_FCOLOR) {
1385 color = (pr[col] & COL_FCOLOR);
1386 mode = ((mode & ~COL_FCOLOR) | color);
1387 writestr(color_seq(color));
1390 if ((pr[col] & S_BCOLORED)
1391 && (pr[col] ^ mode) & COL_BCOLOR) {
1392 bcolor = (pr[col] & COL_BCOLOR);
1393 mode = ((mode & ~COL_BCOLOR) | bcolor);
1394 writestr(bcolor_seq(bcolor));
1396 #endif /* USE_BG_COLOR */
1397 if ((pr[col] & S_GRAPHICS) && !(mode & S_GRAPHICS)) {
1401 if (!graph_enabled) {
1409 if (pr[col] & S_GRAPHICS)
1410 write1(graphchar(*pc[col]));
1411 else if (CHMODE(pr[col]) != C_WCHAR2)
1412 wc_putc(pc[col], ttyf);
1414 write1((pr[col] & S_GRAPHICS) ? graphchar(pc[col]) :
1421 moved = RF_NEED_TO_MOVE;
1422 for (; col < COLS && !(pr[col] & S_EOL); col++)
1425 *dirty &= ~(L_NEED_CE | L_CLRTOEOL);
1426 if (mode & M_MEND) {
1427 if (mode & (S_COLORED
1430 #endif /* USE_BG_COLOR */
1433 if (mode & S_GRAPHICS) {
1436 wc_putc_clear_status();
1446 MOVE(CurLine, CurColumn);
1457 for (i = 0; i < LINES; i++) {
1458 ScreenImage[i]->isdirty = 0;
1459 p = ScreenImage[i]->lineprop;
1460 for (j = 0; j < COLS; j++) {
1464 CurrentMode = C_ASCII;
1467 #ifdef USE_RAW_SCROLL
1478 int cli = CurLine, cco = CurColumn;
1492 j = (i + n) % LINES;
1495 ScreenImage[i] = ScreenImage[j];
1497 j = (i + n) % LINES;
1502 for (i = 0; i < n; i++) {
1503 t = ScreenImage[LINES - 1 - i];
1505 for (j = 0; j < COLS; j++)
1506 t->lineprop[j] = S_EOL;
1515 int cli = CurLine, cco = CurColumn;
1529 j = (LINES + i - n) % LINES;
1532 ScreenImage[i] = ScreenImage[j];
1534 j = (LINES + i - n) % LINES;
1538 if (T_sr && *T_sr) {
1540 for (i = 0; i < n; i++) {
1543 for (j = 0; j < COLS; j++)
1544 t->lineprop[j] = S_EOL;
1550 for (i = 0; i < LINES; i++) {
1552 t->isdirty |= L_DIRTY | L_NEED_CE;
1553 for (j = 0; j < COLS; j++) {
1554 t->lineprop[j] |= S_DIRTY;
1565 /* Clear to the end of line as the need arises */
1566 l_prop *lprop = ScreenImage[CurLine]->lineprop;
1568 if (lprop[CurColumn] & S_EOL)
1571 if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) ||
1572 ScreenImage[CurLine]->eol > CurColumn)
1573 ScreenImage[CurLine]->eol = CurColumn;
1575 ScreenImage[CurLine]->isdirty |= L_NEED_CE;
1579 /* XXX: conflicts with curses's clrtoeol(3) ? */
1582 { /* Clear to the end of line */
1584 l_prop *lprop = ScreenImage[CurLine]->lineprop;
1586 if (lprop[CurColumn] & S_EOL)
1589 if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) ||
1590 ScreenImage[CurLine]->eol > CurColumn)
1591 ScreenImage[CurLine]->eol = CurColumn;
1593 ScreenImage[CurLine]->isdirty |= L_CLRTOEOL;
1595 for (i = CurColumn; i < COLS && !(lprop[i] & S_EOL); i++) {
1596 lprop[i] = S_EOL | S_DIRTY;
1602 clrtoeol_with_bcolor(void)
1607 if (!(CurrentMode & S_BCOLORED)) {
1614 CurrentMode = (CurrentMode & (M_CEOL | S_BCOLORED)) | C_ASCII;
1615 for (i = CurColumn; i < COLS; i++)
1624 clrtoeol_with_bcolor();
1626 #else /* not USE_BG_COLOR */
1633 #endif /* not USE_BG_COLOR */
1636 clrtobot_eol(void (*clrtoeol) ())
1645 for (; CurLine < LINES; CurLine++)
1654 clrtobot_eol(clrtoeol);
1660 clrtobot_eol(clrtoeolx);
1668 l_prop *lprop = ScreenImage[CurLine]->lineprop;
1670 ScreenImage[CurLine]->isdirty &= ~L_CLRTOEOL;
1680 while (*s != '\0') {
1681 len = wtf_len((wc_uchar *) s);
1692 addnstr(char *s, int n)
1698 for (i = 0; *s != '\0';) {
1699 width = wtf_width((wc_uchar *) s);
1702 len = wtf_len((wc_uchar *) s);
1708 for (i = 0; i < n && *s != '\0'; i++)
1714 addnstr_sup(char *s, int n)
1720 for (i = 0; *s != '\0';) {
1721 width = wtf_width((wc_uchar *) s);
1724 len = wtf_len((wc_uchar *) s);
1730 for (i = 0; i < n && *s != '\0'; i++)
1739 #ifndef HAVE_SGTTY_H
1741 ttymode_reset(ICANON, IXON);
1742 ttymode_set(ISIG, 0);
1743 #ifdef HAVE_TERMIOS_H
1745 #else /* not HAVE_TERMIOS_H */
1747 #endif /* not HAVE_TERMIOS_H */
1749 #else /* HAVE_SGTTY_H */
1751 ttymode_set(CBREAK, 0);
1753 #endif /* HAVE_SGTTY_H */
1757 #ifndef HAVE_SGTTY_H
1759 ttymode_set(ICANON, 0);
1760 #ifdef HAVE_TERMIOS_H
1762 #else /* not HAVE_TERMIOS_H */
1764 #endif /* not HAVE_TERMIOS_H */
1766 #else /* HAVE_SGTTY_H */
1768 ttymode_reset(CBREAK, 0);
1770 #endif /* HAVE_SGTTY_H */
1775 ttymode_set(ECHO, 0);
1781 ttymode_reset(ECHO, 0);
1786 #ifndef HAVE_SGTTY_H
1788 #define TTY_MODE ISIG|ICANON|ECHO|IEXTEN
1789 #else /* not IEXTEN */
1790 #define TTY_MODE ISIG|ICANON|ECHO
1791 #endif /* not IEXTEN */
1793 ttymode_reset(TTY_MODE, IXON | IXOFF);
1794 #ifdef HAVE_TERMIOS_H
1796 #else /* not HAVE_TERMIOS_H */
1798 #endif /* not HAVE_TERMIOS_H */
1800 #else /* HAVE_SGTTY_H */
1802 ttymode_set(RAW, 0);
1804 #endif /* HAVE_SGTTY_H */
1808 #ifndef HAVE_SGTTY_H
1811 /* On XFree86/OS2, some scrambled characters
1812 * will appear when asserting IEXTEN flag.
1814 ttymode_set((TTY_MODE) & ~IEXTEN, 0);
1816 ttymode_set(TTY_MODE, 0);
1818 #ifdef HAVE_TERMIOS_H
1820 #else /* not HAVE_TERMIOS_H */
1822 #endif /* not HAVE_TERMIOS_H */
1824 #else /* HAVE_SGTTY_H */
1826 ttymode_reset(RAW, 0);
1828 #endif /* HAVE_SGTTY_H */
1842 if (title_str != NULL) {
1844 if (isLocalConsole && title_str == CYGWIN_TITLE) {
1846 buff = Sprintf(title_str, s);
1847 if (buff->length > 1024) {
1848 Strtruncate(buff, 1024);
1850 SetConsoleTitle(buff->ptr);
1852 else if (isLocalConsole || !isWinConsole)
1854 fprintf(ttyf, title_str, s);
1864 #ifdef SUPPORT_WIN9X_CONSOLE_MBCS
1865 read_win32_console(&c, 1)
1870 if (errno == EINTR || errno == EAGAIN)
1872 /* error happend on read(2) */
1874 break; /* unreachable */
1886 /* read(tty, &c, 1); */
1887 while (read(tty, &c, 1) < (ssize_t) 1) {
1888 if (errno == EINTR || errno == EAGAIN)
1890 /* error happend on read(2) */
1892 break; /* unreachable */
1905 #endif /* USE_GPM */
1916 while (select(tty + 1, &rfd, NULL, NULL, NULL) <= 0) {
1917 if (errno == EINTR) {
1920 key = (*sysm_handler) (x, y, nbs, obs);
1931 if (is_xterm || !sysm_handler)
1934 return sysm_getch();
1938 sysmouse(SIGNAL_ARG)
1940 struct mouse_info mi;
1942 mi.operation = MOUSE_GETINFO;
1943 if (ioctl(tty, CONS_MOUSECTL, &mi) == -1)
1948 nbs = mi.u.data.buttons & 0x7;
1949 /* for cosmetic bug in syscons.c on FreeBSD 3.[34] */
1950 mi.operation = MOUSE_HIDE;
1951 ioctl(tty, CONS_MOUSECTL, &mi);
1952 mi.operation = MOUSE_SHOW;
1953 ioctl(tty, CONS_MOUSECTL, &mi);
1955 #endif /* USE_SYSMOUSE */
1956 #endif /* USE_MOUSE */
1970 if (c == '[' || c == 'O') {
1973 if (is_xterm && c == 'M') {
1986 sleep_till_anykey(int sec, int purge)
1993 TerminalGet(tty, &ioval);
2002 ret = select(tty + 1, &rfd, 0, 0, &tim);
2003 if (ret > 0 && purge) {
2008 er = TerminalSet(tty, &ioval);
2010 printf("Error occured: errno=%d\n", errno);
2011 reset_exit(SIGNAL_ARGLIST);
2018 #define XTERM_ON {fputs("\033[?1001s\033[?1000h",ttyf); flush_tty();}
2019 #define XTERM_OFF {fputs("\033[?1000l\033[?1001r",ttyf); flush_tty();}
2020 #define CYGWIN_ON {fputs("\033[?1000h",ttyf); flush_tty();}
2021 #define CYGWIN_OFF {fputs("\033[?1000l",ttyf); flush_tty();}
2024 /* Linux console with GPM support */
2030 extern int gpm_process_mouse(Gpm_Event *, void *);
2035 conn.eventMask = ~0;
2036 conn.defaultMask = 0;
2040 r = Gpm_Open(&conn, 0);
2043 * If Gpm_Open() success, returns >= 0
2044 * Gpm_Open() returns -2 in case of xterm.
2045 * Gpm_Close() is necessary here. Otherwise,
2046 * xterm is being left in the mode where the mouse clicks are
2047 * passed through to the application.
2050 is_xterm = (NEED_XTERM_ON | NEED_XTERM_OFF);
2053 gpm_handler = gpm_process_mouse;
2065 if (mouseActive == 0)
2075 #elif defined(USE_SYSMOUSE)
2076 /* *BSD console with sysmouse support */
2081 extern int sysm_process_mouse();
2089 #if defined(FBIO_MODEINFO) || defined(CONS_MODEINFO) /* FreeBSD > 2.x */
2090 #ifndef FBIO_GETMODE /* FreeBSD 3.x */
2091 #define FBIO_GETMODE CONS_GET
2092 #define FBIO_MODEINFO CONS_MODEINFO
2093 #endif /* FBIO_GETMODE */
2096 if (ioctl(tty, FBIO_GETMODE, &vi.vi_mode) != -1 &&
2097 ioctl(tty, FBIO_MODEINFO, &vi) != -1) {
2098 cwidth = vi.vi_cwidth;
2099 cheight = vi.vi_cheight;
2101 #endif /* defined(FBIO_MODEINFO) ||
2102 * defined(CONS_MODEINFO) */
2103 mySignal(SIGUSR2, SIG_IGN);
2104 mi.operation = MOUSE_MODE;
2106 mi.u.mode.signal = SIGUSR2;
2107 sysm_handler = NULL;
2108 if (ioctl(tty, CONS_MOUSECTL, &mi) != -1) {
2109 mySignal(SIGUSR2, sysmouse);
2110 mi.operation = MOUSE_SHOW;
2111 ioctl(tty, CONS_MOUSECTL, &mi);
2112 sysm_handler = sysm_process_mouse;
2121 if (mouseActive == 0)
2128 mi.operation = MOUSE_MODE;
2130 mi.u.mode.signal = 0;
2131 ioctl(tty, CONS_MOUSECTL, &mi);
2137 /* not GPM nor SYSMOUSE, but use mouse with xterm */
2144 if (is_xterm & NEED_XTERM_ON) {
2148 else if (is_xterm & NEED_CYGWIN_ON) {
2158 if (mouseActive == 0)
2160 if (is_xterm & NEED_XTERM_OFF) {
2164 else if (is_xterm & NEED_CYGWIN_OFF) {
2171 #endif /* not USE_GPM nor USE_SYSMOUSE */
2184 if (mouseActive && is_xterm)
2188 #endif /* USE_MOUSE */
2206 for (i = CurColumn; i >= 0; i--) {
2208 if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2)
2211 for (i = CurColumn + 1; i < COLS; i++) {
2212 if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2)
2217 touch_column(CurColumn);
2222 #ifdef __MINGW32_VERSION
2224 int tgetent(char *bp, char *name)
2229 int tgetnum(char *id)
2234 int tgetflag(char *id)
2239 char *tgetstr(char *id, char **area)
2244 char *tgoto(char *cap, int col, int row)
2248 int tputs(char *str, int affcnt, int (*putc)(char))
2252 char *ttyname(int tty)
2257 #endif /* __MINGW32_VERSION */