w3m

Unnamed repository; edit this file to name it for gitweb.
git clone https://logand.com/git/w3m.git/
Log | Files | Refs | README

terms.c (45697B)


      1 /* $Id$ */
      2 /* 
      3  * An original curses library for EUC-kanji by Akinori ITO,     December 1989
      4  * revised by Akinori ITO, January 1995
      5  */
      6 #include <stdio.h>
      7 #include <signal.h>
      8 #include <sys/types.h>
      9 #include <fcntl.h>
     10 #include <errno.h>
     11 #include <sys/time.h>
     12 #include <unistd.h>
     13 #include "config.h"
     14 #include <string.h>
     15 #ifdef HAVE_SYS_SELECT_H
     16 #include <sys/select.h>
     17 #endif
     18 #ifndef __MINGW32_VERSION
     19 #include <sys/ioctl.h>
     20 #else
     21 #include <winsock.h>
     22 #endif /* __MINGW32_VERSION */
     23 #ifdef USE_MOUSE
     24 #ifdef USE_GPM
     25 #include <gpm.h>
     26 #endif				/* USE_GPM */
     27 #ifdef USE_SYSMOUSE
     28 #include <osreldate.h>
     29 #if (__FreeBSD_version >= 400017) || (__FreeBSD_kernel_version >= 400017)
     30 #include <sys/consio.h>
     31 #include <sys/fbio.h>
     32 #else
     33 #include <machine/console.h>
     34 #endif
     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 */
     39 
     40 static int is_xterm = 0;
     41 
     42 void mouse_init(), mouse_end();
     43 int mouseActive = 0;
     44 #endif				/* USE_MOUSE */
     45 
     46 static char *title_str = NULL;
     47 
     48 static int tty;
     49 
     50 #include "terms.h"
     51 #include "fm.h"
     52 #include "myctype.h"
     53 
     54 #ifdef __EMX__
     55 #define INCL_DOSNLS
     56 #include <os2.h>
     57 #endif				/* __EMX__ */
     58 
     59 #if defined(__CYGWIN__)
     60 #include <windows.h>
     61 #include <sys/cygwin.h>
     62 static int isWinConsole = 0;
     63 #define TERM_CYGWIN 1
     64 #define TERM_CYGWIN_RESERVE_IME 2
     65 static int isLocalConsole = 0;
     66 
     67 #if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE)
     68 int cygwin_mouse_btn_swapped = 0;
     69 #endif
     70 
     71 #if defined(SUPPORT_WIN9X_CONSOLE_MBCS)
     72 static HANDLE hConIn = INVALID_HANDLE_VALUE;
     73 static int isWin95 = 0;
     74 static char *ConInV;
     75 static int iConIn, nConIn, nConInMax;
     76 
     77 static void
     78 check_win9x(void)
     79 {
     80     OSVERSIONINFO winVersionInfo;
     81 
     82     winVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
     83     if (GetVersionEx(&winVersionInfo) == 0) {
     84 	fprintf(stderr, "can't get Windows version information.\n");
     85 	exit(1);
     86     }
     87     if (winVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
     88 	isWin95 = 1;
     89     }
     90     else {
     91 	isWin95 = 0;
     92     }
     93 }
     94 
     95 void
     96 enable_win9x_console_input(void)
     97 {
     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) {
    104 	    getch();
    105 	}
    106     }
    107 }
    108 
    109 void
    110 disable_win9x_console_input(void)
    111 {
    112     if (hConIn != INVALID_HANDLE_VALUE) {
    113 	CloseHandle(hConIn);
    114 	hConIn = INVALID_HANDLE_VALUE;
    115     }
    116 }
    117 
    118 static void
    119 expand_win32_console_input_buffer(int n)
    120 {
    121     if (nConIn + n >= nConInMax) {
    122 	char *oldv;
    123 
    124 	nConInMax = ((nConIn + n) / 2 + 1) * 3;
    125 	oldv = ConInV;
    126 	ConInV = GC_MALLOC_ATOMIC(nConInMax);
    127 	memcpy(ConInV, oldv, nConIn);
    128     }
    129 }
    130 
    131 static int
    132 read_win32_console_input(void)
    133 {
    134     INPUT_RECORD rec;
    135     DWORD nevents;
    136 
    137     if (PeekConsoleInput(hConIn, &rec, 1, &nevents) && nevents) {
    138 	switch (rec.EventType) {
    139 	case KEY_EVENT:
    140 	    expand_win32_console_input_buffer(3);
    141 
    142 	    if (ReadConsole(hConIn, &ConInV[nConIn], 1, &nevents, NULL)) {
    143 		nConIn += nevents;
    144 		return nevents;
    145 	    }
    146 
    147 	    break;
    148 	default:
    149 	    break;
    150 	}
    151 
    152 	ReadConsoleInput(hConIn, &rec, 1, &nevents);
    153     }
    154     return 0;
    155 }
    156 
    157 static int
    158 read_win32_console(char *s, int n)
    159 {
    160     KEY_EVENT_RECORD *ker;
    161 
    162     if (hConIn == INVALID_HANDLE_VALUE)
    163 	return read(tty, s, n);
    164 
    165     if (n > 0)
    166 	for (;;) {
    167 	    if (iConIn < nConIn) {
    168 		if (n > nConIn - iConIn)
    169 		    n = nConIn - iConIn;
    170 
    171 		memcpy(s, ConInV, n);
    172 
    173 		if ((iConIn += n) >= nConIn)
    174 		    iConIn = nConIn = 0;
    175 
    176 		break;
    177 	    }
    178 
    179 	    iConIn = nConIn = 0;
    180 
    181 	    while (!read_win32_console_input()) ;
    182 	}
    183 
    184     return n;
    185 }
    186 
    187 #endif				/* SUPPORT_WIN9X_CONSOLE_MBCS */
    188 
    189 static HWND
    190 GetConsoleHwnd(void)
    191 {
    192 #define MY_BUFSIZE 1024
    193     HWND hwndFound;
    194     char pszNewWindowTitle[MY_BUFSIZE];
    195     char pszOldWindowTitle[MY_BUFSIZE];
    196 
    197     GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
    198     wsprintf(pszNewWindowTitle, "%d/%d",
    199 	     GetTickCount(), GetCurrentProcessId());
    200     SetConsoleTitle(pszNewWindowTitle);
    201     Sleep(40);
    202     hwndFound = FindWindow(NULL, pszNewWindowTitle);
    203     SetConsoleTitle(pszOldWindowTitle);
    204     return (hwndFound);
    205 }
    206 
    207 #if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE)
    208 static unsigned long
    209 cygwin_version(void)
    210 {
    211     struct per_process *p;
    212 
    213     p = (struct per_process *)cygwin_internal(CW_USER_DATA);
    214     if (p != NULL) {
    215 	return (p->dll_major * 1000) + p->dll_minor;
    216     }
    217     return 0;
    218 }
    219 #endif
    220 
    221 static void
    222 check_cygwin_console(void)
    223 {
    224     char *term = getenv("TERM");
    225     HANDLE hWnd;
    226 
    227     if (term == NULL)
    228 	term = DEFAULT_TERM;
    229     if (term && strncmp(term, "cygwin", 6) == 0) {
    230 	isWinConsole = TERM_CYGWIN;
    231     }
    232     if (isWinConsole) {
    233 	hWnd = GetConsoleHwnd();
    234 	if (hWnd != INVALID_HANDLE_VALUE) {
    235 	    if (IsWindowVisible(hWnd)) {
    236 		isLocalConsole = 1;
    237 	    }
    238 	}
    239 	if (strncmp(getenv("LANG"), "ja", 2) == 0) {
    240 	    isWinConsole = TERM_CYGWIN_RESERVE_IME;
    241 	}
    242 #ifdef SUPPORT_WIN9X_CONSOLE_MBCS
    243 	check_win9x();
    244 	if (isWin95 && ttyslot() != -1) {
    245 	    isLocalConsole = 0;
    246 	}
    247 #endif
    248     }
    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;
    253     }
    254 #endif
    255 }
    256 #endif				/* __CYGWIN__ */
    257 
    258 char *getenv(const char *);
    259 MySignalHandler reset_exit(SIGNAL_ARG), reset_error_exit(SIGNAL_ARG), error_dump(SIGNAL_ARG);
    260 void setlinescols(void);
    261 void flush_tty();
    262 
    263 #ifndef SIGIOT
    264 #define SIGIOT SIGABRT
    265 #endif				/* not SIGIOT */
    266 
    267 #ifdef HAVE_TERMIO_H
    268 #include <termio.h>
    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 */
    275 
    276 #ifdef HAVE_TERMIOS_H
    277 #include <termios.h>
    278 #include <unistd.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 */
    285 
    286 #ifdef HAVE_SGTTY_H
    287 #include <sgtty.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 */
    293 
    294 #ifdef __MINGW32_VERSION
    295 /* dummy struct */
    296 typedef unsigned char   cc_t;
    297 typedef unsigned int    speed_t;
    298 typedef unsigned int    tcflag_t;
    299 
    300 #define NCCS 32
    301 struct termios
    302   {
    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 */
    311   };
    312 typedef struct termios TerminalMode;
    313 #define TerminalSet(fd,x)       (0)
    314 #define TerminalGet(fd,x)       (0)
    315 #define MODEFLAG(d)     (0)
    316 
    317 /* dummy defines */
    318 #define SIGHUP (0)
    319 #define SIGQUIT (0)
    320 #define ECHO (0)
    321 #define ISIG (0)
    322 #define VEOF (0)
    323 #define ICANON (0)
    324 #define IXON (0)
    325 #define IXOFF (0)
    326 
    327 char *ttyname(int);
    328 #endif /* __MINGW32_VERSION */
    329 
    330 #define MAX_LINE        200
    331 #define MAX_COLUMN      400
    332 
    333 /* Screen properties */
    334 #define S_SCREENPROP    0x0f
    335 #define S_NORMAL        0x00
    336 #define S_STANDOUT      0x01
    337 #define S_UNDERLINE     0x02
    338 #define S_BOLD          0x04
    339 #define S_EOL           0x08
    340 
    341 /* Sort of Character */
    342 #define C_WHICHCHAR     0xc0
    343 #define C_ASCII         0x00
    344 #ifdef USE_M17N
    345 #define C_WCHAR1        0x40
    346 #define C_WCHAR2        0x80
    347 #endif
    348 #define C_CTRL          0xc0
    349 
    350 #define CHMODE(c)       ((c)&C_WHICHCHAR)
    351 #define SETCHMODE(var,mode)	((var) = (((var)&~C_WHICHCHAR) | mode))
    352 #ifdef USE_M17N
    353 #define SETCH(var,ch,len)	((var) = New_Reuse(char, (var), (len) + 1), \
    354 				strncpy((var), (ch), (len)), (var)[len] = '\0')
    355 #else
    356 #define SETCH(var,ch,len)	((var) = (ch))
    357 #endif
    358 
    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
    370 
    371 #define S_COLORED       0xf00
    372 
    373 #ifdef USE_BG_COLOR
    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
    385 
    386 #define S_BCOLORED      0xf000
    387 #endif				/* USE_BG_COLOR */
    388 
    389 
    390 #define S_GRAPHICS      0x10
    391 
    392 #define S_DIRTY         0x20
    393 
    394 #define SETPROP(var,prop) (var = (((var)&S_DIRTY) | prop))
    395 
    396 /* Line status */
    397 #define L_DIRTY         0x01
    398 #define L_UNUSED        0x02
    399 #define L_NEED_CE       0x04
    400 #define L_CLRTOEOL      0x08
    401 
    402 #define ISDIRTY(d)      ((d) & L_DIRTY)
    403 #define ISUNUSED(d)     ((d) & L_UNUSED)
    404 #define NEED_CE(d)      ((d) & L_NEED_CE)
    405 
    406 typedef unsigned short l_prop;
    407 
    408 typedef struct scline {
    409 #ifdef USE_M17N
    410     char **lineimage;
    411 #else
    412     char *lineimage;
    413 #endif
    414     l_prop *lineprop;
    415     short isdirty;
    416     short eol;
    417 } Screen;
    418 
    419 static TerminalMode d_ioval;
    420 static int tty = -1;
    421 static FILE *ttyf = NULL;
    422 
    423 static
    424 char bp[1024], funcstr[256];
    425 
    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;
    429 
    430 int LINES, COLS;
    431 #if defined(__CYGWIN__)
    432 int LASTLINE;
    433 #endif				/* defined(__CYGWIN__) */
    434 
    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;
    441 
    442 static char gcmap[96];
    443 
    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);
    451 #if 0
    452 void need_clrtoeol(void);
    453 #endif
    454 void clrtoeol(void);		/* conflicts with curs_clear(3)? */
    455 
    456 static int write1(char);
    457 
    458 static void
    459 writestr(char *s)
    460 {
    461     tputs(s, 1, write1);
    462 }
    463 
    464 #define MOVE(line,column)       writestr(tgoto(T_cm,column,line));
    465 
    466 #ifdef USE_MOUSE
    467 #define W3M_TERM_INFO(name, title, mouse)	name, title, mouse
    468 #define NEED_XTERM_ON   (1)
    469 #define NEED_XTERM_OFF  (1<<1)
    470 #ifdef __CYGWIN__
    471 #define NEED_CYGWIN_ON  (1<<2)
    472 #define NEED_CYGWIN_OFF (1<<3)
    473 #endif
    474 #else
    475 #define W3M_TERM_INFO(name, title, mouse)	name, title
    476 #endif
    477 
    478 static char XTERM_TITLE[] = "\033]0;w3m: %s\007";
    479 static char SCREEN_TITLE[] = "\033k%s\033\134";
    480 #ifdef __CYGWIN__
    481 static char CYGWIN_TITLE[] = "w3m: %s";
    482 #endif
    483 
    484 /* *INDENT-OFF* */
    485 static struct w3m_term_info {
    486     char *term;
    487     char *title_str;
    488 #ifdef USE_MOUSE
    489     int mouse_flag;
    490 #endif
    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)},
    498 #ifdef __CYGWIN__
    499     {W3M_TERM_INFO("cygwin", CYGWIN_TITLE, (NEED_CYGWIN_ON|NEED_CYGWIN_OFF))},
    500 #endif
    501     {W3M_TERM_INFO(NULL, NULL, 0)}
    502 };
    503 #undef W3M_TERM_INFO
    504 /* *INDENT-ON * */
    505 
    506 int
    507 set_tty(void)
    508 {
    509     char *ttyn;
    510 
    511     if (isatty(0))		/* stdin */
    512 	ttyn = ttyname(0);
    513     else
    514 	ttyn = DEV_TTY_PATH;
    515     tty = open(ttyn, O_RDWR);
    516     if (tty < 0) {
    517 	/* use stderr instead of stdin... is it OK???? */
    518 	tty = 2;
    519     }
    520     ttyf = fdopen(tty, "w");
    521 #ifdef __CYGWIN__
    522     check_cygwin_console();
    523 #endif
    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;
    530 		break;
    531 	    }
    532 	}
    533     }
    534 #ifdef USE_MOUSE
    535     {
    536 	char *term = getenv("TERM");
    537 	if (term != NULL) {
    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;
    542 			break;
    543 		    }
    544 		}
    545 	}
    546     }
    547 #endif
    548     return 0;
    549 }
    550 
    551 void
    552 ttymode_set(int mode, int imode)
    553 {
    554 #ifndef __MINGW32_VERSION
    555     TerminalMode ioval;
    556 
    557     TerminalGet(tty, &ioval);
    558     MODEFLAG(ioval) |= mode;
    559 #ifndef HAVE_SGTTY_H
    560     IMODEFLAG(ioval) |= imode;
    561 #endif				/* not HAVE_SGTTY_H */
    562 
    563     while (TerminalSet(tty, &ioval) == -1) {
    564 	if (errno == EINTR || errno == EAGAIN)
    565 	    continue;
    566 	printf("Error occured while set %x: errno=%d\n", mode, errno);
    567 	reset_error_exit(SIGNAL_ARGLIST);
    568     }
    569 #endif
    570 }
    571 
    572 void
    573 ttymode_reset(int mode, int imode)
    574 {
    575 #ifndef __MINGW32_VERSION
    576     TerminalMode ioval;
    577 
    578     TerminalGet(tty, &ioval);
    579     MODEFLAG(ioval) &= ~mode;
    580 #ifndef HAVE_SGTTY_H
    581     IMODEFLAG(ioval) &= ~imode;
    582 #endif				/* not HAVE_SGTTY_H */
    583 
    584     while (TerminalSet(tty, &ioval) == -1) {
    585 	if (errno == EINTR || errno == EAGAIN)
    586 	    continue;
    587 	printf("Error occured while reset %x: errno=%d\n", mode, errno);
    588 	reset_error_exit(SIGNAL_ARGLIST);
    589     }
    590 #endif /* __MINGW32_VERSION */
    591 }
    592 
    593 #ifndef HAVE_SGTTY_H
    594 void
    595 set_cc(int spec, int val)
    596 {
    597     TerminalMode ioval;
    598 
    599     TerminalGet(tty, &ioval);
    600     ioval.c_cc[spec] = val;
    601     while (TerminalSet(tty, &ioval) == -1) {
    602 	if (errno == EINTR || errno == EAGAIN)
    603 	    continue;
    604 	printf("Error occured: errno=%d\n", errno);
    605 	reset_error_exit(SIGNAL_ARGLIST);
    606     }
    607 }
    608 #endif				/* not HAVE_SGTTY_H */
    609 
    610 void
    611 close_tty(void)
    612 {
    613     if (tty > 2)
    614 	close(tty);
    615 }
    616 
    617 char *
    618 ttyname_tty(void)
    619 {
    620     return ttyname(tty);
    621 }
    622 
    623 void
    624 reset_tty(void)
    625 {
    626     writestr(T_op);		/* turn off */
    627     writestr(T_me);
    628     if (!Do_not_use_ti_te) {
    629 	if (T_te && *T_te)
    630 	    writestr(T_te);
    631 	else
    632 	    writestr(T_cl);
    633     }
    634     writestr(T_se);		/* reset terminal */
    635     flush_tty();
    636     TerminalSet(tty, &d_ioval);
    637     close_tty();
    638 }
    639 
    640 static MySignalHandler
    641 reset_exit_with_value(SIGNAL_ARG, int rval)
    642 {
    643 #ifdef USE_MOUSE
    644     if (mouseActive)
    645 	mouse_end();
    646 #endif				/* USE_MOUSE */
    647     reset_tty();
    648     w3m_exit(rval);
    649     SIGNAL_RETURN;
    650 }
    651 
    652 MySignalHandler
    653 reset_error_exit(SIGNAL_ARG)
    654 {
    655   reset_exit_with_value(SIGNAL_ARGLIST, 1);
    656 }
    657 
    658 MySignalHandler
    659 reset_exit(SIGNAL_ARG)
    660 {
    661   reset_exit_with_value(SIGNAL_ARGLIST, 0);
    662 }
    663 
    664 MySignalHandler
    665 error_dump(SIGNAL_ARG)
    666 {
    667     mySignal(SIGIOT, SIG_DFL);
    668     reset_tty();
    669     abort();
    670     SIGNAL_RETURN;
    671 }
    672 
    673 void
    674 set_int(void)
    675 {
    676     mySignal(SIGHUP, reset_exit);
    677     mySignal(SIGINT, reset_exit);
    678     mySignal(SIGQUIT, reset_exit);
    679     mySignal(SIGTERM, reset_exit);
    680     mySignal(SIGILL, error_dump);
    681     mySignal(SIGIOT, error_dump);
    682     mySignal(SIGFPE, error_dump);
    683 #ifdef	SIGBUS
    684     mySignal(SIGBUS, error_dump);
    685 #endif				/* SIGBUS */
    686     /* mySignal(SIGSEGV, error_dump); */
    687 }
    688 
    689 
    690 static void
    691 setgraphchar(void)
    692 {
    693     int c, i, n;
    694 
    695     for (c = 0; c < 96; c++)
    696 	gcmap[c] = (char)(c + ' ');
    697 
    698     if (!T_ac)
    699 	return;
    700 
    701     n = strlen(T_ac);
    702     for (i = 0; i < n - 1; i += 2) {
    703 	c = (unsigned)T_ac[i] - ' ';
    704 	if (c >= 0 && c < 96)
    705 	    gcmap[c] = T_ac[i + 1];
    706     }
    707 }
    708 
    709 #define graphchar(c) (((unsigned)(c)>=' ' && (unsigned)(c)<128)? gcmap[(c)-' '] : (c))
    710 #define GETSTR(v,s) {v = pt; suc = tgetstr(s,&pt); if (!suc) v = ""; else v = allocStr(suc, -1); }
    711 
    712 void
    713 getTCstr(void)
    714 {
    715     char *ent;
    716     char *suc;
    717     char *pt = funcstr;
    718     int r;
    719 
    720     ent = getenv("TERM") ? getenv("TERM") : DEFAULT_TERM;
    721     if (ent == NULL) {
    722 	fprintf(stderr, "TERM is not set\n");
    723 	reset_error_exit(SIGNAL_ARGLIST);
    724     }
    725 
    726     r = tgetent(bp, ent);
    727     if (r != 1) {
    728 	/* Can't find termcap entry */
    729 	fprintf(stderr, "Can't find termcap entry %s\n", ent);
    730 	reset_error_exit(SIGNAL_ARGLIST);
    731     }
    732 
    733     GETSTR(T_ce, "ce");		/* clear to the end of line */
    734     GETSTR(T_cd, "cd");		/* clear to the end of display */
    735     GETSTR(T_kr, "nd");		/* cursor right */
    736     if (suc == NULL)
    737 	GETSTR(T_kr, "kr");
    738     if (tgetflag("bs"))
    739 	T_kl = "\b";		/* cursor left */
    740     else {
    741 	GETSTR(T_kl, "le");
    742 	if (suc == NULL)
    743 	    GETSTR(T_kl, "kb");
    744 	if (suc == NULL)
    745 	    GETSTR(T_kl, "kl");
    746     }
    747     GETSTR(T_cr, "cr");		/* carriage return */
    748     GETSTR(T_ta, "ta");		/* tab */
    749     GETSTR(T_sc, "sc");		/* save cursor */
    750     GETSTR(T_rc, "rc");		/* restore cursor */
    751     GETSTR(T_so, "so");		/* standout mode */
    752     GETSTR(T_se, "se");		/* standout mode end */
    753     GETSTR(T_us, "us");		/* underline mode */
    754     GETSTR(T_ue, "ue");		/* underline mode end */
    755     GETSTR(T_md, "md");		/* bold mode */
    756     GETSTR(T_me, "me");		/* bold mode end */
    757     GETSTR(T_cl, "cl");		/* clear screen */
    758     GETSTR(T_cm, "cm");		/* cursor move */
    759     GETSTR(T_al, "al");		/* append line */
    760     GETSTR(T_sr, "sr");		/* scroll reverse */
    761     GETSTR(T_ti, "ti");		/* terminal init */
    762     GETSTR(T_te, "te");		/* terminal end */
    763     GETSTR(T_nd, "nd");		/* move right one space */
    764     GETSTR(T_eA, "eA");		/* enable alternative charset */
    765     GETSTR(T_as, "as");		/* alternative (graphic) charset start */
    766     GETSTR(T_ae, "ae");		/* alternative (graphic) charset end */
    767     GETSTR(T_ac, "ac");		/* graphics charset pairs */
    768     GETSTR(T_op, "op");		/* set default color pair to its original value */
    769 #if defined( CYGWIN ) && CYGWIN < 1
    770     /* for TERM=pcansi on MS-DOS prompt. */
    771 #if 0
    772     T_eA = "";
    773     T_as = "\033[12m";
    774     T_ae = "\033[10m";
    775     T_ac = "l\001k\002m\003j\004x\005q\006n\020a\024v\025w\026u\027t\031";
    776 #endif
    777     T_eA = "";
    778     T_as = "";
    779     T_ae = "";
    780     T_ac = "";
    781 #endif				/* CYGWIN */
    782 
    783     LINES = COLS = 0;
    784     setlinescols();
    785     setgraphchar();
    786 }
    787 
    788 void
    789 setlinescols(void)
    790 {
    791     char *p;
    792     int i;
    793 #ifdef __EMX__
    794     {
    795 	int s[2];
    796 	_scrsize(s);
    797 	COLS = s[0];
    798 	LINES = s[1];
    799 
    800 	if (getenv("WINDOWID")) {
    801 	    FILE *fd = popen("scrsize", "rt");
    802 	    if (fd) {
    803 		fscanf(fd, "%i %i", &COLS, &LINES);
    804 		pclose(fd);
    805 	    }
    806 	}
    807     }
    808 #elif defined(HAVE_TERMIOS_H) && defined(TIOCGWINSZ)
    809     struct winsize wins;
    810 
    811     i = ioctl(tty, TIOCGWINSZ, &wins);
    812     if (i >= 0 && wins.ws_row != 0 && wins.ws_col != 0) {
    813 	LINES = wins.ws_row;
    814 	COLS = wins.ws_col;
    815     }
    816 #endif				/* defined(HAVE-TERMIOS_H) && defined(TIOCGWINSZ) */
    817     if (LINES <= 0 && (p = getenv("LINES")) != NULL && (i = atoi(p)) >= 0)
    818 	LINES = i;
    819     if (COLS <= 0 && (p = getenv("COLUMNS")) != NULL && (i = atoi(p)) >= 0)
    820 	COLS = i;
    821     if (LINES <= 0)
    822 	LINES = tgetnum("li");	/* number of line */
    823     if (COLS <= 0)
    824 	COLS = tgetnum("co");	/* number of column */
    825     if (COLS > MAX_COLUMN)
    826 	COLS = MAX_COLUMN;
    827     if (LINES > MAX_LINE)
    828 	LINES = MAX_LINE;
    829 #if defined(__CYGWIN__)
    830     LASTLINE = LINES - (isWinConsole == TERM_CYGWIN_RESERVE_IME ? 2 : 1);
    831 #endif				/* defined(__CYGWIN__) */
    832 }
    833 
    834 void
    835 setupscreen(void)
    836 {
    837     int i;
    838 
    839     if (LINES + 1 > max_LINES) {
    840 	max_LINES = LINES + 1;
    841 	max_COLS = 0;
    842 	ScreenElem = New_N(Screen, max_LINES);
    843 	ScreenImage = New_N(Screen *, max_LINES);
    844     }
    845     if (COLS + 1 > max_COLS) {
    846 	max_COLS = COLS + 1;
    847 	for (i = 0; i < max_LINES; i++) {
    848 #ifdef USE_M17N
    849 	    ScreenElem[i].lineimage = New_N(char *, max_COLS);
    850 	    bzero((void *)ScreenElem[i].lineimage, max_COLS * sizeof(char *));
    851 #else
    852 	    ScreenElem[i].lineimage = New_N(char, max_COLS);
    853 #endif
    854 	    ScreenElem[i].lineprop = New_N(l_prop, max_COLS);
    855 	}
    856     }
    857     for (i = 0; i < LINES; i++) {
    858 	ScreenImage[i] = &ScreenElem[i];
    859 	ScreenImage[i]->lineprop[0] = S_EOL;
    860 	ScreenImage[i]->isdirty = 0;
    861     }
    862     for (; i < max_LINES; i++) {
    863 	ScreenElem[i].isdirty = L_UNUSED;
    864     }
    865 
    866     clear();
    867 }
    868 
    869 /* 
    870  * Screen initialize
    871  */
    872 int
    873 initscr(void)
    874 {
    875     if (set_tty() < 0)
    876 	return -1;
    877     set_int();
    878     getTCstr();
    879     if (T_ti && !Do_not_use_ti_te)
    880 	writestr(T_ti);
    881     setupscreen();
    882     return 0;
    883 }
    884 
    885 static int
    886 write1(char c)
    887 {
    888     putc(c, ttyf);
    889 #ifdef SCREEN_DEBUG
    890     flush_tty();
    891 #endif				/* SCREEN_DEBUG */
    892     return 0;
    893 }
    894 
    895 void
    896 move(int line, int column)
    897 {
    898     if (line >= 0 && line < LINES)
    899 	CurLine = line;
    900     if (column >= 0 && column < COLS)
    901 	CurColumn = column;
    902 }
    903 
    904 #ifdef USE_BG_COLOR
    905 #define M_SPACE (S_SCREENPROP|S_COLORED|S_BCOLORED|S_GRAPHICS)
    906 #else				/* not USE_BG_COLOR */
    907 #define M_SPACE (S_SCREENPROP|S_COLORED|S_GRAPHICS)
    908 #endif				/* not USE_BG_COLOR */
    909 
    910 static int
    911 #ifdef USE_M17N
    912 need_redraw(char *c1, l_prop pr1, char *c2, l_prop pr2)
    913 {
    914     if (!c1 || !c2 || strcmp(c1, c2))
    915 	return 1;
    916     if (*c1 == ' ')
    917 #else
    918 need_redraw(char c1, l_prop pr1, char c2, l_prop pr2)
    919 {
    920     if (c1 != c2)
    921 	return 1;
    922     if (c1 == ' ')
    923 #endif
    924 	return (pr1 ^ pr2) & M_SPACE & ~S_DIRTY;
    925 
    926     if ((pr1 ^ pr2) & ~S_DIRTY)
    927 	return 1;
    928 
    929     return 0;
    930 }
    931 
    932 #define M_CEOL (~(M_SPACE|C_WHICHCHAR))
    933 
    934 #ifdef USE_M17N
    935 #define SPACE " "
    936 #else
    937 #define SPACE ' '
    938 #endif
    939 
    940 #ifdef USE_M17N
    941 void
    942 addch(char c)
    943 {
    944     addmch(&c, 1);
    945 }
    946 
    947 void
    948 addmch(char *pc, size_t len)
    949 #else
    950 void
    951 addch(char pc)
    952 #endif
    953 {
    954     l_prop *pr;
    955     int dest, i;
    956     short *dirty;
    957 #ifdef USE_M17N
    958     static Str tmp = NULL;
    959     char **p;
    960     char c = *pc;
    961     int width = wtf_width((wc_uchar *) pc);
    962 
    963     if (tmp == NULL)
    964 	tmp = Strnew();
    965     Strcopy_charp_n(tmp, pc, len);
    966     pc = tmp->ptr;
    967 #else
    968     char *p;
    969     char c = pc;
    970 #endif
    971 
    972     if (CurColumn == COLS)
    973 	wrap();
    974     if (CurColumn >= COLS)
    975 	return;
    976     p = ScreenImage[CurLine]->lineimage;
    977     pr = ScreenImage[CurLine]->lineprop;
    978     dirty = &ScreenImage[CurLine]->isdirty;
    979 
    980 #ifndef USE_M17N
    981     /* Eliminate unprintables according to * iso-8859-*.
    982      * Particularly 0x96 messes up T.Dickey's * (xfree-)xterm */
    983     if (IS_INTSPACE(c))
    984 	c = ' ';
    985 #endif
    986 
    987     if (pr[CurColumn] & S_EOL) {
    988 	if (c == ' ' && !(CurrentMode & M_SPACE)) {
    989 	    CurColumn++;
    990 	    return;
    991 	}
    992 	for (i = CurColumn; i >= 0 && (pr[i] & S_EOL); i--) {
    993 	    SETCH(p[i], SPACE, 1);
    994 	    SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII);
    995 	}
    996     }
    997 
    998     if (c == '\t' || c == '\n' || c == '\r' || c == '\b')
    999 	SETCHMODE(CurrentMode, C_CTRL);
   1000 #ifdef USE_M17N
   1001     else if (len > 1)
   1002 	SETCHMODE(CurrentMode, C_WCHAR1);
   1003 #endif
   1004     else if (!IS_CNTRL(c))
   1005 	SETCHMODE(CurrentMode, C_ASCII);
   1006     else
   1007 	return;
   1008 
   1009     /* Required to erase bold or underlined character for some * terminal
   1010      * emulators. */
   1011 #ifdef USE_M17N
   1012     i = CurColumn + width - 1;
   1013 #else
   1014     i = CurColumn;
   1015 #endif
   1016     if (i < COLS &&
   1017 	(((pr[i] & S_BOLD) && need_redraw(p[i], pr[i], pc, CurrentMode)) ||
   1018 	 ((pr[i] & S_UNDERLINE) && !(CurrentMode & S_UNDERLINE)))) {
   1019 	touch_line();
   1020 	i++;
   1021 	if (i < COLS) {
   1022 	    touch_column(i);
   1023 	    if (pr[i] & S_EOL) {
   1024 		SETCH(p[i], SPACE, 1);
   1025 		SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII);
   1026 	    }
   1027 #ifdef USE_M17N
   1028 	    else {
   1029 		for (i++; i < COLS && CHMODE(pr[i]) == C_WCHAR2; i++)
   1030 		    touch_column(i);
   1031 	    }
   1032 #endif
   1033 	}
   1034     }
   1035 
   1036 #ifdef USE_M17N
   1037     if (CurColumn + width > COLS) {
   1038 	touch_line();
   1039 	for (i = CurColumn; i < COLS; i++) {
   1040 	    SETCH(p[i], SPACE, 1);
   1041 	    SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII);
   1042 	    touch_column(i);
   1043 	}
   1044 	wrap();
   1045 	if (CurColumn + width > COLS)
   1046 	    return;
   1047 	p = ScreenImage[CurLine]->lineimage;
   1048 	pr = ScreenImage[CurLine]->lineprop;
   1049     }
   1050     if (CHMODE(pr[CurColumn]) == C_WCHAR2) {
   1051 	touch_line();
   1052 	for (i = CurColumn - 1; i >= 0; i--) {
   1053 	    l_prop l = CHMODE(pr[i]);
   1054 	    SETCH(p[i], SPACE, 1);
   1055 	    SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII);
   1056 	    touch_column(i);
   1057 	    if (l != C_WCHAR2)
   1058 		break;
   1059 	}
   1060     }
   1061 #endif
   1062     if (CHMODE(CurrentMode) != C_CTRL) {
   1063 	if (need_redraw(p[CurColumn], pr[CurColumn], pc, CurrentMode)) {
   1064 	    SETCH(p[CurColumn], pc, len);
   1065 	    SETPROP(pr[CurColumn], CurrentMode);
   1066 	    touch_line();
   1067 	    touch_column(CurColumn);
   1068 #ifdef USE_M17N
   1069 	    SETCHMODE(CurrentMode, C_WCHAR2);
   1070 	    for (i = CurColumn + 1; i < CurColumn + width; i++) {
   1071 		SETCH(p[i], SPACE, 1);
   1072 		SETPROP(pr[i], (pr[CurColumn] & ~C_WHICHCHAR) | C_WCHAR2);
   1073 		touch_column(i);
   1074 	    }
   1075 	    for (; i < COLS && CHMODE(pr[i]) == C_WCHAR2; i++) {
   1076 		SETCH(p[i], SPACE, 1);
   1077 		SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII);
   1078 		touch_column(i);
   1079 	    }
   1080 	}
   1081 	CurColumn += width;
   1082 #else
   1083 	}
   1084 	CurColumn++;
   1085 #endif
   1086     }
   1087     else if (c == '\t') {
   1088 	dest = (CurColumn + tab_step) / tab_step * tab_step;
   1089 	if (dest >= COLS) {
   1090 	    wrap();
   1091 	    touch_line();
   1092 	    dest = tab_step;
   1093 	    p = ScreenImage[CurLine]->lineimage;
   1094 	    pr = ScreenImage[CurLine]->lineprop;
   1095 	}
   1096 	for (i = CurColumn; i < dest; i++) {
   1097 	    if (need_redraw(p[i], pr[i], SPACE, CurrentMode)) {
   1098 		SETCH(p[i], SPACE, 1);
   1099 		SETPROP(pr[i], CurrentMode);
   1100 		touch_line();
   1101 		touch_column(i);
   1102 	    }
   1103 	}
   1104 	CurColumn = i;
   1105     }
   1106     else if (c == '\n') {
   1107 	wrap();
   1108     }
   1109     else if (c == '\r') {	/* Carriage return */
   1110 	CurColumn = 0;
   1111     }
   1112     else if (c == '\b' && CurColumn > 0) {	/* Backspace */
   1113 	CurColumn--;
   1114 #ifdef USE_M17N
   1115 	while (CurColumn > 0 && CHMODE(pr[CurColumn]) == C_WCHAR2)
   1116 	    CurColumn--;
   1117 #endif
   1118     }
   1119 }
   1120 
   1121 void
   1122 wrap(void)
   1123 {
   1124     if (CurLine == LASTLINE)
   1125 	return;
   1126     CurLine++;
   1127     CurColumn = 0;
   1128 }
   1129 
   1130 void
   1131 touch_column(int col)
   1132 {
   1133     if (col >= 0 && col < COLS)
   1134 	ScreenImage[CurLine]->lineprop[col] |= S_DIRTY;
   1135 }
   1136 
   1137 void
   1138 touch_line(void)
   1139 {
   1140     if (!(ScreenImage[CurLine]->isdirty & L_DIRTY)) {
   1141 	int i;
   1142 	for (i = 0; i < COLS; i++)
   1143 	    ScreenImage[CurLine]->lineprop[i] &= ~S_DIRTY;
   1144 	ScreenImage[CurLine]->isdirty |= L_DIRTY;
   1145     }
   1146 
   1147 }
   1148 
   1149 void
   1150 standout(void)
   1151 {
   1152     CurrentMode |= S_STANDOUT;
   1153 }
   1154 
   1155 void
   1156 standend(void)
   1157 {
   1158     CurrentMode &= ~S_STANDOUT;
   1159 }
   1160 
   1161 void
   1162 toggle_stand(void)
   1163 {
   1164 #ifdef USE_M17N
   1165     int i;
   1166 #endif
   1167     l_prop *pr = ScreenImage[CurLine]->lineprop;
   1168     pr[CurColumn] ^= S_STANDOUT;
   1169 #ifdef USE_M17N
   1170     if (CHMODE(pr[CurColumn]) != C_WCHAR2) {
   1171 	for (i = CurColumn + 1; CHMODE(pr[i]) == C_WCHAR2; i++)
   1172 	    pr[i] ^= S_STANDOUT;
   1173     }
   1174 #endif
   1175 }
   1176 
   1177 void
   1178 bold(void)
   1179 {
   1180     CurrentMode |= S_BOLD;
   1181 }
   1182 
   1183 void
   1184 boldend(void)
   1185 {
   1186     CurrentMode &= ~S_BOLD;
   1187 }
   1188 
   1189 void
   1190 underline(void)
   1191 {
   1192     CurrentMode |= S_UNDERLINE;
   1193 }
   1194 
   1195 void
   1196 underlineend(void)
   1197 {
   1198     CurrentMode &= ~S_UNDERLINE;
   1199 }
   1200 
   1201 void
   1202 graphstart(void)
   1203 {
   1204     CurrentMode |= S_GRAPHICS;
   1205 }
   1206 
   1207 void
   1208 graphend(void)
   1209 {
   1210     CurrentMode &= ~S_GRAPHICS;
   1211 }
   1212 
   1213 int
   1214 graph_ok(void)
   1215 {
   1216     if (UseGraphicChar != GRAPHIC_CHAR_DEC)
   1217 	return 0;
   1218     return T_as[0] != 0 && T_ae[0] != 0 && T_ac[0] != 0;
   1219 }
   1220 
   1221 void
   1222 setfcolor(int color)
   1223 {
   1224     CurrentMode &= ~COL_FCOLOR;
   1225     if ((color & 0xf) <= 7)
   1226 	CurrentMode |= (((color & 7) | 8) << 8);
   1227 }
   1228 
   1229 static char *
   1230 color_seq(int colmode)
   1231 {
   1232     static char seqbuf[32];
   1233     sprintf(seqbuf, "\033[%dm", ((colmode >> 8) & 7) + 30);
   1234     return seqbuf;
   1235 }
   1236 
   1237 #ifdef USE_BG_COLOR
   1238 void
   1239 setbcolor(int color)
   1240 {
   1241     CurrentMode &= ~COL_BCOLOR;
   1242     if ((color & 0xf) <= 7)
   1243 	CurrentMode |= (((color & 7) | 8) << 12);
   1244 }
   1245 
   1246 static char *
   1247 bcolor_seq(int colmode)
   1248 {
   1249     static char seqbuf[32];
   1250     sprintf(seqbuf, "\033[%dm", ((colmode >> 12) & 7) + 40);
   1251     return seqbuf;
   1252 }
   1253 #endif				/* USE_BG_COLOR */
   1254 
   1255 #define RF_NEED_TO_MOVE    0
   1256 #define RF_CR_OK           1
   1257 #define RF_NONEED_TO_MOVE  2
   1258 #ifdef USE_BG_COLOR
   1259 #define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_BCOLORED|S_GRAPHICS)
   1260 #else				/* not USE_BG_COLOR */
   1261 #define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_GRAPHICS)
   1262 #endif				/* not USE_BG_COLOR */
   1263 void
   1264 refresh(void)
   1265 {
   1266     int line, col, pcol;
   1267     int pline = CurLine;
   1268     int moved = RF_NEED_TO_MOVE;
   1269 #ifdef USE_M17N
   1270     char **pc;
   1271 #else
   1272     char *pc;
   1273 #endif
   1274     l_prop *pr, mode = 0;
   1275     l_prop color = COL_FTERM;
   1276 #ifdef USE_BG_COLOR
   1277     l_prop bcolor = COL_BTERM;
   1278 #endif				/* USE_BG_COLOR */
   1279     short *dirty;
   1280 
   1281 #ifdef USE_M17N
   1282     wc_putc_init(InnerCharset, DisplayCharset);
   1283 #endif
   1284     for (line = 0; line <= LASTLINE; line++) {
   1285 	dirty = &ScreenImage[line]->isdirty;
   1286 	if (*dirty & L_DIRTY) {
   1287 	    *dirty &= ~L_DIRTY;
   1288 	    pc = ScreenImage[line]->lineimage;
   1289 	    pr = ScreenImage[line]->lineprop;
   1290 	    for (col = 0; col < COLS && !(pr[col] & S_EOL); col++) {
   1291 		if (*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) {
   1292 		    if (need_redraw(pc[col], pr[col], SPACE, 0))
   1293 			break;
   1294 		}
   1295 		else {
   1296 		    if (pr[col] & S_DIRTY)
   1297 			break;
   1298 		}
   1299 	    }
   1300 	    if (*dirty & (L_NEED_CE | L_CLRTOEOL)) {
   1301 		pcol = ScreenImage[line]->eol;
   1302 		if (pcol >= COLS) {
   1303 		    *dirty &= ~(L_NEED_CE | L_CLRTOEOL);
   1304 		    pcol = col;
   1305 		}
   1306 	    }
   1307 	    else {
   1308 		pcol = col;
   1309 	    }
   1310 	    if (line < LINES - 2 && pline == line - 1 && pcol == 0) {
   1311 		switch (moved) {
   1312 		case RF_NEED_TO_MOVE:
   1313 		    MOVE(line, 0);
   1314 		    moved = RF_CR_OK;
   1315 		    break;
   1316 		case RF_CR_OK:
   1317 		    write1('\n');
   1318 		    write1('\r');
   1319 		    break;
   1320 		case RF_NONEED_TO_MOVE:
   1321 		    moved = RF_CR_OK;
   1322 		    break;
   1323 		}
   1324 	    }
   1325 	    else {
   1326 		MOVE(line, pcol);
   1327 		moved = RF_CR_OK;
   1328 	    }
   1329 	    if (*dirty & (L_NEED_CE | L_CLRTOEOL)) {
   1330 		writestr(T_ce);
   1331 		if (col != pcol)
   1332 		    MOVE(line, col);
   1333 	    }
   1334 	    pline = line;
   1335 	    pcol = col;
   1336 	    for (; col < COLS; col++) {
   1337 		if (pr[col] & S_EOL)
   1338 		    break;
   1339 
   1340 		/* 
   1341 		 * some terminal emulators do linefeed when a
   1342 		 * character is put on COLS-th column. this behavior
   1343 		 * is different from one of vt100, but such terminal
   1344 		 * emulators are used as vt100-compatible
   1345 		 * emulators. This behaviour causes scroll when a
   1346 		 * character is drawn on (COLS-1,LINES-1) point.  To
   1347 		 * avoid the scroll, I prohibit to draw character on
   1348 		 * (COLS-1,LINES-1).
   1349 		 */
   1350 #if !defined(USE_BG_COLOR) || defined(__CYGWIN__)
   1351 #ifdef __CYGWIN__
   1352 		if (isWinConsole)
   1353 #endif
   1354 		    if (line == LINES - 1 && col == COLS - 1)
   1355 			break;
   1356 #endif				/* !defined(USE_BG_COLOR) || defined(__CYGWIN__) */
   1357 		if ((!(pr[col] & S_STANDOUT) && (mode & S_STANDOUT)) ||
   1358 		    (!(pr[col] & S_UNDERLINE) && (mode & S_UNDERLINE)) ||
   1359 		    (!(pr[col] & S_BOLD) && (mode & S_BOLD)) ||
   1360 		    (!(pr[col] & S_COLORED) && (mode & S_COLORED))
   1361 #ifdef USE_BG_COLOR
   1362 		    || (!(pr[col] & S_BCOLORED) && (mode & S_BCOLORED))
   1363 #endif				/* USE_BG_COLOR */
   1364 		    || (!(pr[col] & S_GRAPHICS) && (mode & S_GRAPHICS))) {
   1365 		    if ((mode & S_COLORED)
   1366 #ifdef USE_BG_COLOR
   1367 			|| (mode & S_BCOLORED)
   1368 #endif				/* USE_BG_COLOR */
   1369 			)
   1370 			writestr(T_op);
   1371 		    if (mode & S_GRAPHICS)
   1372 			writestr(T_ae);
   1373 		    writestr(T_me);
   1374 		    mode &= ~M_MEND;
   1375 		}
   1376 		if ((*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) ?
   1377 		    need_redraw(pc[col], pr[col], SPACE,
   1378 				0) : (pr[col] & S_DIRTY)) {
   1379 		    if (pcol == col - 1)
   1380 			writestr(T_nd);
   1381 		    else if (pcol != col)
   1382 			MOVE(line, col);
   1383 
   1384 		    if ((pr[col] & S_STANDOUT) && !(mode & S_STANDOUT)) {
   1385 			writestr(T_so);
   1386 			mode |= S_STANDOUT;
   1387 		    }
   1388 		    if ((pr[col] & S_UNDERLINE) && !(mode & S_UNDERLINE)) {
   1389 			writestr(T_us);
   1390 			mode |= S_UNDERLINE;
   1391 		    }
   1392 		    if ((pr[col] & S_BOLD) && !(mode & S_BOLD)) {
   1393 			writestr(T_md);
   1394 			mode |= S_BOLD;
   1395 		    }
   1396 		    if ((pr[col] & S_COLORED) && (pr[col] ^ mode) & COL_FCOLOR) {
   1397 			color = (pr[col] & COL_FCOLOR);
   1398 			mode = ((mode & ~COL_FCOLOR) | color);
   1399 			writestr(color_seq(color));
   1400 		    }
   1401 #ifdef USE_BG_COLOR
   1402 		    if ((pr[col] & S_BCOLORED)
   1403 			&& (pr[col] ^ mode) & COL_BCOLOR) {
   1404 			bcolor = (pr[col] & COL_BCOLOR);
   1405 			mode = ((mode & ~COL_BCOLOR) | bcolor);
   1406 			writestr(bcolor_seq(bcolor));
   1407 		    }
   1408 #endif				/* USE_BG_COLOR */
   1409 		    if ((pr[col] & S_GRAPHICS) && !(mode & S_GRAPHICS)) {
   1410 #ifdef USE_M17N
   1411 			wc_putc_end(ttyf);
   1412 #endif
   1413 			if (!graph_enabled) {
   1414 			    graph_enabled = 1;
   1415 			    writestr(T_eA);
   1416 			}
   1417 			writestr(T_as);
   1418 			mode |= S_GRAPHICS;
   1419 		    }
   1420 #ifdef USE_M17N
   1421 		    if (pr[col] & S_GRAPHICS)
   1422 			write1(graphchar(*pc[col]));
   1423 		    else if (CHMODE(pr[col]) != C_WCHAR2)
   1424 			wc_putc(pc[col], ttyf);
   1425 #else
   1426 		    write1((pr[col] & S_GRAPHICS) ? graphchar(pc[col]) :
   1427 			   pc[col]);
   1428 #endif
   1429 		    pcol = col + 1;
   1430 		}
   1431 	    }
   1432 	    if (col == COLS)
   1433 		moved = RF_NEED_TO_MOVE;
   1434 	    for (; col < COLS && !(pr[col] & S_EOL); col++)
   1435 		pr[col] |= S_EOL;
   1436 	}
   1437 	*dirty &= ~(L_NEED_CE | L_CLRTOEOL);
   1438 	if (mode & M_MEND) {
   1439 	    if (mode & (S_COLORED
   1440 #ifdef USE_BG_COLOR
   1441 			| S_BCOLORED
   1442 #endif				/* USE_BG_COLOR */
   1443 		))
   1444 		writestr(T_op);
   1445 	    if (mode & S_GRAPHICS) {
   1446 		writestr(T_ae);
   1447 #ifdef USE_M17N
   1448 		wc_putc_clear_status();
   1449 #endif
   1450 	    }
   1451 	    writestr(T_me);
   1452 	    mode &= ~M_MEND;
   1453 	}
   1454     }
   1455 #ifdef USE_M17N
   1456     wc_putc_end(ttyf);
   1457 #endif
   1458     MOVE(CurLine, CurColumn);
   1459     flush_tty();
   1460 }
   1461 
   1462 void
   1463 clear(void)
   1464 {
   1465     int i, j;
   1466     l_prop *p;
   1467     writestr(T_cl);
   1468     move(0, 0);
   1469     for (i = 0; i < LINES; i++) {
   1470 	ScreenImage[i]->isdirty = 0;
   1471 	p = ScreenImage[i]->lineprop;
   1472 	for (j = 0; j < COLS; j++) {
   1473 	    p[j] = S_EOL;
   1474 	}
   1475     }
   1476     CurrentMode = C_ASCII;
   1477 }
   1478 
   1479 #ifdef USE_RAW_SCROLL
   1480 static void
   1481 scroll_raw(void)
   1482 {				/* raw scroll */
   1483     MOVE(LINES - 1, 0);
   1484     write1('\n');
   1485 }
   1486 
   1487 void
   1488 scroll(int n)
   1489 {				/* scroll up */
   1490     int cli = CurLine, cco = CurColumn;
   1491     Screen *t;
   1492     int i, j, k;
   1493 
   1494     i = LINES;
   1495     j = n;
   1496     do {
   1497 	k = j;
   1498 	j = i % k;
   1499 	i = k;
   1500     } while (j);
   1501     do {
   1502 	k--;
   1503 	i = k;
   1504 	j = (i + n) % LINES;
   1505 	t = ScreenImage[k];
   1506 	while (j != k) {
   1507 	    ScreenImage[i] = ScreenImage[j];
   1508 	    i = j;
   1509 	    j = (i + n) % LINES;
   1510 	}
   1511 	ScreenImage[i] = t;
   1512     } while (k);
   1513 
   1514     for (i = 0; i < n; i++) {
   1515 	t = ScreenImage[LINES - 1 - i];
   1516 	t->isdirty = 0;
   1517 	for (j = 0; j < COLS; j++)
   1518 	    t->lineprop[j] = S_EOL;
   1519 	scroll_raw();
   1520     }
   1521     move(cli, cco);
   1522 }
   1523 
   1524 void
   1525 rscroll(int n)
   1526 {				/* scroll down */
   1527     int cli = CurLine, cco = CurColumn;
   1528     Screen *t;
   1529     int i, j, k;
   1530 
   1531     i = LINES;
   1532     j = n;
   1533     do {
   1534 	k = j;
   1535 	j = i % k;
   1536 	i = k;
   1537     } while (j);
   1538     do {
   1539 	k--;
   1540 	i = k;
   1541 	j = (LINES + i - n) % LINES;
   1542 	t = ScreenImage[k];
   1543 	while (j != k) {
   1544 	    ScreenImage[i] = ScreenImage[j];
   1545 	    i = j;
   1546 	    j = (LINES + i - n) % LINES;
   1547 	}
   1548 	ScreenImage[i] = t;
   1549     } while (k);
   1550     if (T_sr && *T_sr) {
   1551 	MOVE(0, 0);
   1552 	for (i = 0; i < n; i++) {
   1553 	    t = ScreenImage[i];
   1554 	    t->isdirty = 0;
   1555 	    for (j = 0; j < COLS; j++)
   1556 		t->lineprop[j] = S_EOL;
   1557 	    writestr(T_sr);
   1558 	}
   1559 	move(cli, cco);
   1560     }
   1561     else {
   1562 	for (i = 0; i < LINES; i++) {
   1563 	    t = ScreenImage[i];
   1564 	    t->isdirty |= L_DIRTY | L_NEED_CE;
   1565 	    for (j = 0; j < COLS; j++) {
   1566 		t->lineprop[j] |= S_DIRTY;
   1567 	    }
   1568 	}
   1569     }
   1570 }
   1571 #endif
   1572 
   1573 #if 0
   1574 void
   1575 need_clrtoeol(void)
   1576 {
   1577     /* Clear to the end of line as the need arises */
   1578     l_prop *lprop = ScreenImage[CurLine]->lineprop;
   1579 
   1580     if (lprop[CurColumn] & S_EOL)
   1581 	return;
   1582 
   1583     if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) ||
   1584 	ScreenImage[CurLine]->eol > CurColumn)
   1585 	ScreenImage[CurLine]->eol = CurColumn;
   1586 
   1587     ScreenImage[CurLine]->isdirty |= L_NEED_CE;
   1588 }
   1589 #endif				/* 0 */
   1590 
   1591 /* XXX: conflicts with curses's clrtoeol(3) ? */
   1592 void
   1593 clrtoeol(void)
   1594 {				/* Clear to the end of line */
   1595     int i;
   1596     l_prop *lprop = ScreenImage[CurLine]->lineprop;
   1597 
   1598     if (lprop[CurColumn] & S_EOL)
   1599 	return;
   1600 
   1601     if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) ||
   1602 	ScreenImage[CurLine]->eol > CurColumn)
   1603 	ScreenImage[CurLine]->eol = CurColumn;
   1604 
   1605     ScreenImage[CurLine]->isdirty |= L_CLRTOEOL;
   1606     touch_line();
   1607     for (i = CurColumn; i < COLS && !(lprop[i] & S_EOL); i++) {
   1608 	lprop[i] = S_EOL | S_DIRTY;
   1609     }
   1610 }
   1611 
   1612 #ifdef USE_BG_COLOR
   1613 void
   1614 clrtoeol_with_bcolor(void)
   1615 {
   1616     int i, cli, cco;
   1617     l_prop pr;
   1618 
   1619     if (!(CurrentMode & S_BCOLORED)) {
   1620 	clrtoeol();
   1621 	return;
   1622     }
   1623     cli = CurLine;
   1624     cco = CurColumn;
   1625     pr = CurrentMode;
   1626     CurrentMode = (CurrentMode & (M_CEOL | S_BCOLORED)) | C_ASCII;
   1627     for (i = CurColumn; i < COLS; i++)
   1628 	addch(' ');
   1629     move(cli, cco);
   1630     CurrentMode = pr;
   1631 }
   1632 
   1633 void
   1634 clrtoeolx(void)
   1635 {
   1636     clrtoeol_with_bcolor();
   1637 }
   1638 #else				/* not USE_BG_COLOR */
   1639 
   1640 void
   1641 clrtoeolx(void)
   1642 {
   1643     clrtoeol();
   1644 }
   1645 #endif				/* not USE_BG_COLOR */
   1646 
   1647 void
   1648 clrtobot_eol(void (*clrtoeol) ())
   1649 {
   1650     int l, c;
   1651 
   1652     l = CurLine;
   1653     c = CurColumn;
   1654     (*clrtoeol) ();
   1655     CurColumn = 0;
   1656     CurLine++;
   1657     for (; CurLine < LINES; CurLine++)
   1658 	(*clrtoeol) ();
   1659     CurLine = l;
   1660     CurColumn = c;
   1661 }
   1662 
   1663 void
   1664 clrtobot(void)
   1665 {
   1666     clrtobot_eol(clrtoeol);
   1667 }
   1668 
   1669 void
   1670 clrtobotx(void)
   1671 {
   1672     clrtobot_eol(clrtoeolx);
   1673 }
   1674 
   1675 #if 0
   1676 void
   1677 no_clrtoeol(void)
   1678 {
   1679     int i;
   1680     l_prop *lprop = ScreenImage[CurLine]->lineprop;
   1681 
   1682     ScreenImage[CurLine]->isdirty &= ~L_CLRTOEOL;
   1683 }
   1684 #endif				/* 0 */
   1685 
   1686 void
   1687 addstr(char *s)
   1688 {
   1689 #ifdef USE_M17N
   1690     int len;
   1691 
   1692     while (*s != '\0') {
   1693 	len = wtf_len((wc_uchar *) s);
   1694 	addmch(s, len);
   1695 	s += len;
   1696     }
   1697 #else
   1698     while (*s != '\0')
   1699 	addch(*(s++));
   1700 #endif
   1701 }
   1702 
   1703 void
   1704 addnstr(char *s, int n)
   1705 {
   1706     int i;
   1707 #ifdef USE_M17N
   1708     int len, width;
   1709 
   1710     for (i = 0; *s != '\0';) {
   1711 	width = wtf_width((wc_uchar *) s);
   1712 	if (i + width > n)
   1713 	    break;
   1714 	len = wtf_len((wc_uchar *) s);
   1715 	addmch(s, len);
   1716 	s += len;
   1717 	i += width;
   1718     }
   1719 #else
   1720     for (i = 0; i < n && *s != '\0'; i++)
   1721 	addch(*(s++));
   1722 #endif
   1723 }
   1724 
   1725 void
   1726 addnstr_sup(char *s, int n)
   1727 {
   1728     int i;
   1729 #ifdef USE_M17N
   1730     int len, width;
   1731 
   1732     for (i = 0; *s != '\0';) {
   1733 	width = wtf_width((wc_uchar *) s);
   1734 	if (i + width > n)
   1735 	    break;
   1736 	len = wtf_len((wc_uchar *) s);
   1737 	addmch(s, len);
   1738 	s += len;
   1739 	i += width;
   1740     }
   1741 #else
   1742     for (i = 0; i < n && *s != '\0'; i++)
   1743 	addch(*(s++));
   1744 #endif
   1745     for (; i < n; i++)
   1746 	addch(' ');
   1747 }
   1748 
   1749 void
   1750 crmode(void)
   1751 #ifndef HAVE_SGTTY_H
   1752 {
   1753     ttymode_reset(ICANON, IXON);
   1754     ttymode_set(ISIG, 0);
   1755 #ifdef HAVE_TERMIOS_H
   1756     set_cc(VMIN, 1);
   1757 #else				/* not HAVE_TERMIOS_H */
   1758     set_cc(VEOF, 1);
   1759 #endif				/* not HAVE_TERMIOS_H */
   1760 }
   1761 #else				/* HAVE_SGTTY_H */
   1762 {
   1763     ttymode_set(CBREAK, 0);
   1764 }
   1765 #endif				/* HAVE_SGTTY_H */
   1766 
   1767 void
   1768 nocrmode(void)
   1769 #ifndef HAVE_SGTTY_H
   1770 {
   1771     ttymode_set(ICANON, 0);
   1772 #ifdef HAVE_TERMIOS_H
   1773     set_cc(VMIN, 4);
   1774 #else				/* not HAVE_TERMIOS_H */
   1775     set_cc(VEOF, 4);
   1776 #endif				/* not HAVE_TERMIOS_H */
   1777 }
   1778 #else				/* HAVE_SGTTY_H */
   1779 {
   1780     ttymode_reset(CBREAK, 0);
   1781 }
   1782 #endif				/* HAVE_SGTTY_H */
   1783 
   1784 void
   1785 term_echo(void)
   1786 {
   1787     ttymode_set(ECHO, 0);
   1788 }
   1789 
   1790 void
   1791 term_noecho(void)
   1792 {
   1793     ttymode_reset(ECHO, 0);
   1794 }
   1795 
   1796 void
   1797 term_raw(void)
   1798 #ifndef HAVE_SGTTY_H
   1799 #ifdef IEXTEN
   1800 #define TTY_MODE ISIG|ICANON|ECHO|IEXTEN
   1801 #else				/* not IEXTEN */
   1802 #define TTY_MODE ISIG|ICANON|ECHO
   1803 #endif				/* not IEXTEN */
   1804 {
   1805     ttymode_reset(TTY_MODE, IXON | IXOFF);
   1806 #ifdef HAVE_TERMIOS_H
   1807     set_cc(VMIN, 1);
   1808 #else				/* not HAVE_TERMIOS_H */
   1809     set_cc(VEOF, 1);
   1810 #endif				/* not HAVE_TERMIOS_H */
   1811 }
   1812 #else				/* HAVE_SGTTY_H */
   1813 {
   1814     ttymode_set(RAW, 0);
   1815 }
   1816 #endif				/* HAVE_SGTTY_H */
   1817 
   1818 void
   1819 term_cooked(void)
   1820 #ifndef HAVE_SGTTY_H
   1821 {
   1822 #ifdef __EMX__
   1823     /* On XFree86/OS2, some scrambled characters
   1824      * will appear when asserting IEXTEN flag.
   1825      */
   1826     ttymode_set((TTY_MODE) & ~IEXTEN, 0);
   1827 #else
   1828     ttymode_set(TTY_MODE, 0);
   1829 #endif
   1830 #ifdef HAVE_TERMIOS_H
   1831     set_cc(VMIN, 4);
   1832 #else				/* not HAVE_TERMIOS_H */
   1833     set_cc(VEOF, 4);
   1834 #endif				/* not HAVE_TERMIOS_H */
   1835 }
   1836 #else				/* HAVE_SGTTY_H */
   1837 {
   1838     ttymode_reset(RAW, 0);
   1839 }
   1840 #endif				/* HAVE_SGTTY_H */
   1841 
   1842 void
   1843 term_cbreak(void)
   1844 {
   1845     term_cooked();
   1846     term_noecho();
   1847 }
   1848 
   1849 void
   1850 term_title(char *s)
   1851 {
   1852     if (!fmInitialized)
   1853         return;
   1854     if (title_str != NULL) {
   1855 #ifdef __CYGWIN__
   1856 	if (isLocalConsole && title_str == CYGWIN_TITLE) {
   1857 	    Str buff;
   1858 	    buff = Sprintf(title_str, s);
   1859 	    if (buff->length > 1024) {
   1860 		Strtruncate(buff, 1024);
   1861 	    }
   1862 	    SetConsoleTitle(buff->ptr);
   1863 	}
   1864 	else if (isLocalConsole || !isWinConsole)
   1865 #endif
   1866         fprintf(ttyf, title_str, s);
   1867     }
   1868 }
   1869 
   1870 char
   1871 getch(void)
   1872 {
   1873     char c;
   1874 
   1875     while (
   1876 #ifdef SUPPORT_WIN9X_CONSOLE_MBCS
   1877 	      read_win32_console(&c, 1)
   1878 #else
   1879 	      read(tty, &c, 1)
   1880 #endif
   1881 	      < (int)1) {
   1882 	if (errno == EINTR || errno == EAGAIN)
   1883 	    continue;
   1884 	/* error happend on read(2) */
   1885 	quitfm();
   1886 	break;			/* unreachable */
   1887     }
   1888     return c;
   1889 }
   1890 
   1891 #ifdef USE_MOUSE
   1892 #ifdef USE_GPM
   1893 char
   1894 wgetch(void *p)
   1895 {
   1896     char c;
   1897 
   1898     /* read(tty, &c, 1); */
   1899     while (read(tty, &c, 1) < (ssize_t) 1) {
   1900 	if (errno == EINTR || errno == EAGAIN)
   1901 	    continue;
   1902 	/* error happend on read(2) */
   1903 	quitfm();
   1904 	break;			/* unreachable */
   1905     }
   1906     return c;
   1907 }
   1908 
   1909 int
   1910 do_getch()
   1911 {
   1912     if (is_xterm || !gpm_handler)
   1913 	return getch();
   1914     else
   1915 	return Gpm_Getch();
   1916 }
   1917 #endif				/* USE_GPM */
   1918 
   1919 #ifdef USE_SYSMOUSE
   1920 int
   1921 sysm_getch()
   1922 {
   1923     fd_set rfd;
   1924     int key, x, y;
   1925 
   1926     FD_ZERO(&rfd);
   1927     FD_SET(tty, &rfd);
   1928     while (select(tty + 1, &rfd, NULL, NULL, NULL) <= 0) {
   1929 	if (errno == EINTR) {
   1930 	    x = xpix / cwidth;
   1931 	    y = ypix / cheight;
   1932 	    key = (*sysm_handler) (x, y, nbs, obs);
   1933 	    if (key != 0)
   1934 		return key;
   1935 	}
   1936     }
   1937     return getch();
   1938 }
   1939 
   1940 int
   1941 do_getch()
   1942 {
   1943     if (is_xterm || !sysm_handler)
   1944 	return getch();
   1945     else
   1946 	return sysm_getch();
   1947 }
   1948 
   1949 MySignalHandler
   1950 sysmouse(SIGNAL_ARG)
   1951 {
   1952     struct mouse_info mi;
   1953 
   1954     mi.operation = MOUSE_GETINFO;
   1955     if (ioctl(tty, CONS_MOUSECTL, &mi) == -1)
   1956 	return;
   1957     xpix = mi.u.data.x;
   1958     ypix = mi.u.data.y;
   1959     obs = nbs;
   1960     nbs = mi.u.data.buttons & 0x7;
   1961     /* for cosmetic bug in syscons.c on FreeBSD 3.[34] */
   1962     mi.operation = MOUSE_HIDE;
   1963     ioctl(tty, CONS_MOUSECTL, &mi);
   1964     mi.operation = MOUSE_SHOW;
   1965     ioctl(tty, CONS_MOUSECTL, &mi);
   1966 }
   1967 #endif				/* USE_SYSMOUSE */
   1968 #endif				/* USE_MOUSE */
   1969 
   1970 void
   1971 bell(void)
   1972 {
   1973     write1(7);
   1974 }
   1975 
   1976 void
   1977 skip_escseq(void)
   1978 {
   1979     int c;
   1980 
   1981     c = getch();
   1982     if (c == '[' || c == 'O') {
   1983 	c = getch();
   1984 #ifdef USE_MOUSE
   1985 	if (is_xterm && c == 'M') {
   1986 	    getch();
   1987 	    getch();
   1988 	    getch();
   1989 	}
   1990 	else
   1991 #endif
   1992 	    while (IS_DIGIT(c))
   1993 		c = getch();
   1994     }
   1995 }
   1996 
   1997 int
   1998 sleep_till_anykey(int sec, int purge)
   1999 {
   2000     fd_set rfd;
   2001     struct timeval tim;
   2002     int er, c, ret;
   2003     TerminalMode ioval;
   2004 
   2005     TerminalGet(tty, &ioval);
   2006     term_raw();
   2007 
   2008     tim.tv_sec = sec;
   2009     tim.tv_usec = 0;
   2010 
   2011     FD_ZERO(&rfd);
   2012     FD_SET(tty, &rfd);
   2013 
   2014     ret = select(tty + 1, &rfd, 0, 0, &tim);
   2015     if (ret > 0 && purge) {
   2016 	c = getch();
   2017 	if (c == ESC_CODE)
   2018 	    skip_escseq();
   2019     }
   2020     er = TerminalSet(tty, &ioval);
   2021     if (er == -1) {
   2022 	printf("Error occured: errno=%d\n", errno);
   2023 	reset_error_exit(SIGNAL_ARGLIST);
   2024     }
   2025     return ret;
   2026 }
   2027 
   2028 #ifdef USE_MOUSE
   2029 
   2030 #define XTERM_ON   {fputs("\033[?1001s\033[?1000h",ttyf); flush_tty();}
   2031 #define XTERM_OFF  {fputs("\033[?1000l\033[?1001r",ttyf); flush_tty();}
   2032 #define CYGWIN_ON  {fputs("\033[?1000h",ttyf); flush_tty();}
   2033 #define CYGWIN_OFF {fputs("\033[?1000l",ttyf); flush_tty();}
   2034 
   2035 #ifdef USE_GPM
   2036 /* Linux console with GPM support */
   2037 
   2038 void
   2039 mouse_init()
   2040 {
   2041     Gpm_Connect conn;
   2042     extern int gpm_process_mouse(Gpm_Event *, void *);
   2043     int r;
   2044 
   2045     if (mouseActive)
   2046 	return;
   2047     conn.eventMask = ~0;
   2048     conn.defaultMask = 0;
   2049     conn.maxMod = 0;
   2050     conn.minMod = 0;
   2051 
   2052     gpm_handler = NULL;
   2053     r = Gpm_Open(&conn, 0);
   2054     if (r == -2) {
   2055 	/*
   2056 	 * If Gpm_Open() success, returns >= 0
   2057 	 * Gpm_Open() returns -2 in case of xterm.
   2058 	 * Gpm_Close() is necessary here. Otherwise,
   2059 	 * xterm is being left in the mode where the mouse clicks are
   2060 	 * passed through to the application.
   2061 	 */
   2062 	Gpm_Close();
   2063 	is_xterm = (NEED_XTERM_ON | NEED_XTERM_OFF);
   2064     }
   2065     else if (r >= 0) {
   2066 	gpm_handler = gpm_process_mouse;
   2067 	is_xterm = 0;
   2068     }
   2069     if (is_xterm) {
   2070 	XTERM_ON;
   2071     }
   2072     mouseActive = 1;
   2073 }
   2074 
   2075 void
   2076 mouse_end()
   2077 {
   2078     if (mouseActive == 0)
   2079 	return;
   2080     if (is_xterm) {
   2081 	XTERM_OFF;
   2082     }
   2083     else
   2084 	Gpm_Close();
   2085     mouseActive = 0;
   2086 }
   2087 
   2088 #elif	defined(USE_SYSMOUSE)
   2089 /* *BSD console with sysmouse support */
   2090 void
   2091 mouse_init()
   2092 {
   2093     mouse_info_t mi;
   2094     extern int sysm_process_mouse();
   2095 
   2096     if (mouseActive)
   2097 	return;
   2098     if (is_xterm) {
   2099 	XTERM_ON;
   2100     }
   2101     else {
   2102 #if defined(FBIO_MODEINFO) || defined(CONS_MODEINFO)	/* FreeBSD > 2.x */
   2103 #ifndef FBIO_GETMODE		/* FreeBSD 3.x */
   2104 #define FBIO_GETMODE    CONS_GET
   2105 #define FBIO_MODEINFO   CONS_MODEINFO
   2106 #endif				/* FBIO_GETMODE */
   2107 	video_info_t vi;
   2108 
   2109 	if (ioctl(tty, FBIO_GETMODE, &vi.vi_mode) != -1 &&
   2110 	    ioctl(tty, FBIO_MODEINFO, &vi) != -1) {
   2111 	    cwidth = vi.vi_cwidth;
   2112 	    cheight = vi.vi_cheight;
   2113 	}
   2114 #endif				/* defined(FBIO_MODEINFO) ||
   2115 				 * defined(CONS_MODEINFO) */
   2116 	mySignal(SIGUSR2, SIG_IGN);
   2117 	mi.operation = MOUSE_MODE;
   2118 	mi.u.mode.mode = 0;
   2119 	mi.u.mode.signal = SIGUSR2;
   2120 	sysm_handler = NULL;
   2121 	if (ioctl(tty, CONS_MOUSECTL, &mi) != -1) {
   2122 	    mySignal(SIGUSR2, sysmouse);
   2123 	    mi.operation = MOUSE_SHOW;
   2124 	    ioctl(tty, CONS_MOUSECTL, &mi);
   2125 	    sysm_handler = sysm_process_mouse;
   2126 	}
   2127     }
   2128     mouseActive = 1;
   2129 }
   2130 
   2131 void
   2132 mouse_end()
   2133 {
   2134     if (mouseActive == 0)
   2135 	return;
   2136     if (is_xterm) {
   2137 	XTERM_OFF;
   2138     }
   2139     else {
   2140 	mouse_info_t mi;
   2141 	mi.operation = MOUSE_MODE;
   2142 	mi.u.mode.mode = 0;
   2143 	mi.u.mode.signal = 0;
   2144 	ioctl(tty, CONS_MOUSECTL, &mi);
   2145     }
   2146     mouseActive = 0;
   2147 }
   2148 
   2149 #else
   2150 /* not GPM nor SYSMOUSE, but use mouse with xterm */
   2151 
   2152 void
   2153 mouse_init()
   2154 {
   2155     if (mouseActive)
   2156 	return;
   2157     if (is_xterm & NEED_XTERM_ON) {
   2158 	XTERM_ON;
   2159     }
   2160 #ifdef __CYGWIN__
   2161     else if (is_xterm & NEED_CYGWIN_ON) {
   2162 	CYGWIN_ON;
   2163     }
   2164 #endif
   2165     mouseActive = 1;
   2166 }
   2167 
   2168 void
   2169 mouse_end()
   2170 {
   2171     if (mouseActive == 0)
   2172 	return;
   2173     if (is_xterm & NEED_XTERM_OFF) {
   2174 	XTERM_OFF;
   2175     }
   2176 #ifdef __CYGWIN__
   2177     else if (is_xterm & NEED_CYGWIN_OFF) {
   2178 	CYGWIN_OFF;
   2179     }
   2180 #endif
   2181     mouseActive = 0;
   2182 }
   2183 
   2184 #endif				/* not USE_GPM nor USE_SYSMOUSE */
   2185 
   2186 
   2187 void
   2188 mouse_active()
   2189 {
   2190     if (!mouseActive)
   2191 	mouse_init();
   2192 }
   2193 
   2194 void
   2195 mouse_inactive()
   2196 {
   2197     if (mouseActive && is_xterm)
   2198 	mouse_end();
   2199 }
   2200 
   2201 #endif				/* USE_MOUSE */
   2202 
   2203 void
   2204 flush_tty()
   2205 {
   2206     if (ttyf)
   2207 	fflush(ttyf);
   2208 }
   2209 
   2210 #ifdef USE_IMAGE
   2211 void
   2212 touch_cursor()
   2213 {
   2214 #ifdef USE_M17N
   2215     int i;
   2216 #endif
   2217     touch_line();
   2218 #ifdef USE_M17N
   2219     for (i = CurColumn; i >= 0; i--) {
   2220 	touch_column(i);
   2221 	if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2) 
   2222 	    break;
   2223     }
   2224     for (i = CurColumn + 1; i < COLS; i++) {
   2225 	if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2) 
   2226 	    break;
   2227 	touch_column(i);
   2228     }
   2229 #else
   2230     touch_column(CurColumn);
   2231 #endif
   2232 }
   2233 #endif
   2234 
   2235 #ifdef __MINGW32_VERSION
   2236 
   2237 int tgetent(char *bp, char *name)
   2238 {
   2239   return 0;
   2240 }
   2241 
   2242 int tgetnum(char *id)
   2243 {
   2244   return -1;
   2245 }
   2246 
   2247 int tgetflag(char *id)
   2248 {
   2249   return 0;
   2250 }
   2251 
   2252 char *tgetstr(char *id, char **area)
   2253 {
   2254   id = "";
   2255 }
   2256 
   2257 char *tgoto(char *cap, int col, int row)
   2258 {
   2259 }
   2260 
   2261 int tputs(char *str, int affcnt, int (*putc)(char))
   2262 {
   2263 }
   2264 
   2265 char *ttyname(int tty)
   2266 {
   2267   return "CON";
   2268 }
   2269 
   2270 #endif /* __MINGW32_VERSION */