Intial commit
[profile/ivi/w3m.git] / terms.c
1 /* $Id: terms.c,v 1.57 2007/05/30 04:44:00 inu Exp $ */
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)
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), 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_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_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_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 MySignalHandler
641 reset_exit(SIGNAL_ARG)
642 {
643 #ifdef USE_MOUSE
644     if (mouseActive)
645         mouse_end();
646 #endif                          /* USE_MOUSE */
647     reset_tty();
648     w3m_exit(0);
649     SIGNAL_RETURN;
650 }
651
652 MySignalHandler
653 error_dump(SIGNAL_ARG)
654 {
655     mySignal(SIGIOT, SIG_DFL);
656     reset_tty();
657     abort();
658     SIGNAL_RETURN;
659 }
660
661 void
662 set_int(void)
663 {
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);
671 #ifdef  SIGBUS
672     mySignal(SIGBUS, error_dump);
673 #endif                          /* SIGBUS */
674     /* mySignal(SIGSEGV, error_dump); */
675 }
676
677
678 static void
679 setgraphchar(void)
680 {
681     int c, i, n;
682
683     for (c = 0; c < 96; c++)
684         gcmap[c] = (char)(c + ' ');
685
686     if (!T_ac)
687         return;
688
689     n = strlen(T_ac);
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];
694     }
695 }
696
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); }
699
700 void
701 getTCstr(void)
702 {
703     char *ent;
704     char *suc;
705     char *pt = funcstr;
706     int r;
707
708     ent = getenv("TERM") ? getenv("TERM") : DEFAULT_TERM;
709     if (ent == NULL) {
710         fprintf(stderr, "TERM is not set\n");
711         reset_exit(SIGNAL_ARGLIST);
712     }
713
714     r = tgetent(bp, ent);
715     if (r != 1) {
716         /* Can't find termcap entry */
717         fprintf(stderr, "Can't find termcap entry %s\n", ent);
718         reset_exit(SIGNAL_ARGLIST);
719     }
720
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 */
724     if (suc == NULL)
725         GETSTR(T_kr, "kr");
726     if (tgetflag("bs"))
727         T_kl = "\b";            /* cursor left */
728     else {
729         GETSTR(T_kl, "le");
730         if (suc == NULL)
731             GETSTR(T_kl, "kb");
732         if (suc == NULL)
733             GETSTR(T_kl, "kl");
734     }
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. */
759 #if 0
760     T_eA = "";
761     T_as = "\033[12m";
762     T_ae = "\033[10m";
763     T_ac = "l\001k\002m\003j\004x\005q\006n\020a\024v\025w\026u\027t\031";
764 #endif
765     T_eA = "";
766     T_as = "";
767     T_ae = "";
768     T_ac = "";
769 #endif                          /* CYGWIN */
770
771     LINES = COLS = 0;
772     setlinescols();
773     setgraphchar();
774 }
775
776 void
777 setlinescols(void)
778 {
779     char *p;
780     int i;
781 #ifdef __EMX__
782     {
783         int s[2];
784         _scrsize(s);
785         COLS = s[0];
786         LINES = s[1];
787
788         if (getenv("WINDOWID")) {
789             FILE *fd = popen("scrsize", "rt");
790             if (fd) {
791                 fscanf(fd, "%i %i", &COLS, &LINES);
792                 pclose(fd);
793             }
794         }
795     }
796 #elif defined(HAVE_TERMIOS_H) && defined(TIOCGWINSZ)
797     struct winsize wins;
798
799     i = ioctl(tty, TIOCGWINSZ, &wins);
800     if (i >= 0 && wins.ws_row != 0 && wins.ws_col != 0) {
801         LINES = wins.ws_row;
802         COLS = wins.ws_col;
803     }
804 #endif                          /* defined(HAVE-TERMIOS_H) && defined(TIOCGWINSZ) */
805     if (LINES <= 0 && (p = getenv("LINES")) != NULL && (i = atoi(p)) >= 0)
806         LINES = i;
807     if (COLS <= 0 && (p = getenv("COLUMNS")) != NULL && (i = atoi(p)) >= 0)
808         COLS = i;
809     if (LINES <= 0)
810         LINES = tgetnum("li");  /* number of line */
811     if (COLS <= 0)
812         COLS = tgetnum("co");   /* number of column */
813     if (COLS > MAX_COLUMN)
814         COLS = MAX_COLUMN;
815     if (LINES > MAX_LINE)
816         LINES = MAX_LINE;
817 #if defined(__CYGWIN__)
818     LASTLINE = LINES - (isWinConsole == TERM_CYGWIN_RESERVE_IME ? 2 : 1);
819 #endif                          /* defined(__CYGWIN__) */
820 }
821
822 void
823 setupscreen(void)
824 {
825     int i;
826
827     if (LINES + 1 > max_LINES) {
828         max_LINES = LINES + 1;
829         max_COLS = 0;
830         ScreenElem = New_N(Screen, max_LINES);
831         ScreenImage = New_N(Screen *, max_LINES);
832     }
833     if (COLS + 1 > max_COLS) {
834         max_COLS = COLS + 1;
835         for (i = 0; i < max_LINES; i++) {
836 #ifdef USE_M17N
837             ScreenElem[i].lineimage = New_N(char *, max_COLS);
838             bzero((void *)ScreenElem[i].lineimage, max_COLS * sizeof(char *));
839 #else
840             ScreenElem[i].lineimage = New_N(char, max_COLS);
841 #endif
842             ScreenElem[i].lineprop = New_N(l_prop, max_COLS);
843         }
844     }
845     for (i = 0; i < LINES; i++) {
846         ScreenImage[i] = &ScreenElem[i];
847         ScreenImage[i]->lineprop[0] = S_EOL;
848         ScreenImage[i]->isdirty = 0;
849     }
850     for (; i < max_LINES; i++) {
851         ScreenElem[i].isdirty = L_UNUSED;
852     }
853
854     clear();
855 }
856
857 /* 
858  * Screen initialize
859  */
860 int
861 initscr(void)
862 {
863     if (set_tty() < 0)
864         return -1;
865     set_int();
866     getTCstr();
867     if (T_ti && !Do_not_use_ti_te)
868         writestr(T_ti);
869     setupscreen();
870     return 0;
871 }
872
873 static int
874 write1(char c)
875 {
876     putc(c, ttyf);
877 #ifdef SCREEN_DEBUG
878     flush_tty();
879 #endif                          /* SCREEN_DEBUG */
880     return 0;
881 }
882
883 void
884 move(int line, int column)
885 {
886     if (line >= 0 && line < LINES)
887         CurLine = line;
888     if (column >= 0 && column < COLS)
889         CurColumn = column;
890 }
891
892 #ifdef USE_BG_COLOR
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 */
897
898 static int
899 #ifdef USE_M17N
900 need_redraw(char *c1, l_prop pr1, char *c2, l_prop pr2)
901 {
902     if (!c1 || !c2 || strcmp(c1, c2))
903         return 1;
904     if (*c1 == ' ')
905 #else
906 need_redraw(char c1, l_prop pr1, char c2, l_prop pr2)
907 {
908     if (c1 != c2)
909         return 1;
910     if (c1 == ' ')
911 #endif
912         return (pr1 ^ pr2) & M_SPACE & ~S_DIRTY;
913
914     if ((pr1 ^ pr2) & ~S_DIRTY)
915         return 1;
916
917     return 0;
918 }
919
920 #define M_CEOL (~(M_SPACE|C_WHICHCHAR))
921
922 #ifdef USE_M17N
923 #define SPACE " "
924 #else
925 #define SPACE ' '
926 #endif
927
928 #ifdef USE_M17N
929 void
930 addch(char c)
931 {
932     addmch(&c, 1);
933 }
934
935 void
936 addmch(char *pc, size_t len)
937 #else
938 void
939 addch(char pc)
940 #endif
941 {
942     l_prop *pr;
943     int dest, i;
944     short *dirty;
945 #ifdef USE_M17N
946     static Str tmp = NULL;
947     char **p;
948     char c = *pc;
949     int width = wtf_width((wc_uchar *) pc);
950
951     if (tmp == NULL)
952         tmp = Strnew();
953     Strcopy_charp_n(tmp, pc, len);
954     pc = tmp->ptr;
955 #else
956     char *p;
957     char c = pc;
958 #endif
959
960     if (CurColumn == COLS)
961         wrap();
962     if (CurColumn >= COLS)
963         return;
964     p = ScreenImage[CurLine]->lineimage;
965     pr = ScreenImage[CurLine]->lineprop;
966     dirty = &ScreenImage[CurLine]->isdirty;
967
968 #ifndef USE_M17N
969     /* Eliminate unprintables according to * iso-8859-*.
970      * Particularly 0x96 messes up T.Dickey's * (xfree-)xterm */
971     if (IS_INTSPACE(c))
972         c = ' ';
973 #endif
974
975     if (pr[CurColumn] & S_EOL) {
976         if (c == ' ' && !(CurrentMode & M_SPACE)) {
977             CurColumn++;
978             return;
979         }
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);
983         }
984     }
985
986     if (c == '\t' || c == '\n' || c == '\r' || c == '\b')
987         SETCHMODE(CurrentMode, C_CTRL);
988 #ifdef USE_M17N
989     else if (len > 1)
990         SETCHMODE(CurrentMode, C_WCHAR1);
991 #endif
992     else if (!IS_CNTRL(c))
993         SETCHMODE(CurrentMode, C_ASCII);
994     else
995         return;
996
997     /* Required to erase bold or underlined character for some * terminal
998      * emulators. */
999 #ifdef USE_M17N
1000     i = CurColumn + width - 1;
1001 #else
1002     i = CurColumn;
1003 #endif
1004     if (i < COLS &&
1005         (((pr[i] & S_BOLD) && need_redraw(p[i], pr[i], pc, CurrentMode)) ||
1006          ((pr[i] & S_UNDERLINE) && !(CurrentMode & S_UNDERLINE)))) {
1007         touch_line();
1008         i++;
1009         if (i < COLS) {
1010             touch_column(i);
1011             if (pr[i] & S_EOL) {
1012                 SETCH(p[i], SPACE, 1);
1013                 SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII);
1014             }
1015 #ifdef USE_M17N
1016             else {
1017                 for (i++; i < COLS && CHMODE(pr[i]) == C_WCHAR2; i++)
1018                     touch_column(i);
1019             }
1020 #endif
1021         }
1022     }
1023
1024 #ifdef USE_M17N
1025     if (CurColumn + width > COLS) {
1026         touch_line();
1027         for (i = CurColumn; i < COLS; i++) {
1028             SETCH(p[i], SPACE, 1);
1029             SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII);
1030             touch_column(i);
1031         }
1032         wrap();
1033         if (CurColumn + width > COLS)
1034             return;
1035         p = ScreenImage[CurLine]->lineimage;
1036         pr = ScreenImage[CurLine]->lineprop;
1037     }
1038     if (CHMODE(pr[CurColumn]) == C_WCHAR2) {
1039         touch_line();
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);
1044             touch_column(i);
1045             if (l != C_WCHAR2)
1046                 break;
1047         }
1048     }
1049 #endif
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);
1054             touch_line();
1055             touch_column(CurColumn);
1056 #ifdef USE_M17N
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);
1061                 touch_column(i);
1062             }
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);
1066                 touch_column(i);
1067             }
1068         }
1069         CurColumn += width;
1070 #else
1071         }
1072         CurColumn++;
1073 #endif
1074     }
1075     else if (c == '\t') {
1076         dest = (CurColumn + tab_step) / tab_step * tab_step;
1077         if (dest >= COLS) {
1078             wrap();
1079             touch_line();
1080             dest = tab_step;
1081             p = ScreenImage[CurLine]->lineimage;
1082             pr = ScreenImage[CurLine]->lineprop;
1083         }
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);
1088                 touch_line();
1089                 touch_column(i);
1090             }
1091         }
1092         CurColumn = i;
1093     }
1094     else if (c == '\n') {
1095         wrap();
1096     }
1097     else if (c == '\r') {       /* Carriage return */
1098         CurColumn = 0;
1099     }
1100     else if (c == '\b' && CurColumn > 0) {      /* Backspace */
1101         CurColumn--;
1102 #ifdef USE_M17N
1103         while (CurColumn > 0 && CHMODE(pr[CurColumn]) == C_WCHAR2)
1104             CurColumn--;
1105 #endif
1106     }
1107 }
1108
1109 void
1110 wrap(void)
1111 {
1112     if (CurLine == LASTLINE)
1113         return;
1114     CurLine++;
1115     CurColumn = 0;
1116 }
1117
1118 void
1119 touch_column(int col)
1120 {
1121     if (col >= 0 && col < COLS)
1122         ScreenImage[CurLine]->lineprop[col] |= S_DIRTY;
1123 }
1124
1125 void
1126 touch_line(void)
1127 {
1128     if (!(ScreenImage[CurLine]->isdirty & L_DIRTY)) {
1129         int i;
1130         for (i = 0; i < COLS; i++)
1131             ScreenImage[CurLine]->lineprop[i] &= ~S_DIRTY;
1132         ScreenImage[CurLine]->isdirty |= L_DIRTY;
1133     }
1134
1135 }
1136
1137 void
1138 standout(void)
1139 {
1140     CurrentMode |= S_STANDOUT;
1141 }
1142
1143 void
1144 standend(void)
1145 {
1146     CurrentMode &= ~S_STANDOUT;
1147 }
1148
1149 void
1150 toggle_stand(void)
1151 {
1152 #ifdef USE_M17N
1153     int i;
1154 #endif
1155     l_prop *pr = ScreenImage[CurLine]->lineprop;
1156     pr[CurColumn] ^= S_STANDOUT;
1157 #ifdef USE_M17N
1158     if (CHMODE(pr[CurColumn]) != C_WCHAR2) {
1159         for (i = CurColumn + 1; CHMODE(pr[i]) == C_WCHAR2; i++)
1160             pr[i] ^= S_STANDOUT;
1161     }
1162 #endif
1163 }
1164
1165 void
1166 bold(void)
1167 {
1168     CurrentMode |= S_BOLD;
1169 }
1170
1171 void
1172 boldend(void)
1173 {
1174     CurrentMode &= ~S_BOLD;
1175 }
1176
1177 void
1178 underline(void)
1179 {
1180     CurrentMode |= S_UNDERLINE;
1181 }
1182
1183 void
1184 underlineend(void)
1185 {
1186     CurrentMode &= ~S_UNDERLINE;
1187 }
1188
1189 void
1190 graphstart(void)
1191 {
1192     CurrentMode |= S_GRAPHICS;
1193 }
1194
1195 void
1196 graphend(void)
1197 {
1198     CurrentMode &= ~S_GRAPHICS;
1199 }
1200
1201 int
1202 graph_ok(void)
1203 {
1204     if (!UseGraphicChar)
1205         return 0;
1206     return T_as[0] != 0 && T_ae[0] != 0 && T_ac[0] != 0;
1207 }
1208
1209 void
1210 setfcolor(int color)
1211 {
1212     CurrentMode &= ~COL_FCOLOR;
1213     if ((color & 0xf) <= 7)
1214         CurrentMode |= (((color & 7) | 8) << 8);
1215 }
1216
1217 static char *
1218 color_seq(int colmode)
1219 {
1220     static char seqbuf[32];
1221     sprintf(seqbuf, "\033[%dm", ((colmode >> 8) & 7) + 30);
1222     return seqbuf;
1223 }
1224
1225 #ifdef USE_BG_COLOR
1226 void
1227 setbcolor(int color)
1228 {
1229     CurrentMode &= ~COL_BCOLOR;
1230     if ((color & 0xf) <= 7)
1231         CurrentMode |= (((color & 7) | 8) << 12);
1232 }
1233
1234 static char *
1235 bcolor_seq(int colmode)
1236 {
1237     static char seqbuf[32];
1238     sprintf(seqbuf, "\033[%dm", ((colmode >> 12) & 7) + 40);
1239     return seqbuf;
1240 }
1241 #endif                          /* USE_BG_COLOR */
1242
1243 #define RF_NEED_TO_MOVE    0
1244 #define RF_CR_OK           1
1245 #define RF_NONEED_TO_MOVE  2
1246 #ifdef USE_BG_COLOR
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 */
1251 void
1252 refresh(void)
1253 {
1254     int line, col, pcol;
1255     int pline = CurLine;
1256     int moved = RF_NEED_TO_MOVE;
1257 #ifdef USE_M17N
1258     char **pc;
1259 #else
1260     char *pc;
1261 #endif
1262     l_prop *pr, mode = 0;
1263     l_prop color = COL_FTERM;
1264 #ifdef USE_BG_COLOR
1265     l_prop bcolor = COL_BTERM;
1266 #endif                          /* USE_BG_COLOR */
1267     short *dirty;
1268
1269 #ifdef USE_M17N
1270     wc_putc_init(InnerCharset, DisplayCharset);
1271 #endif
1272     for (line = 0; line <= LASTLINE; line++) {
1273         dirty = &ScreenImage[line]->isdirty;
1274         if (*dirty & L_DIRTY) {
1275             *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))
1281                         break;
1282                 }
1283                 else {
1284                     if (pr[col] & S_DIRTY)
1285                         break;
1286                 }
1287             }
1288             if (*dirty & (L_NEED_CE | L_CLRTOEOL)) {
1289                 pcol = ScreenImage[line]->eol;
1290                 if (pcol >= COLS) {
1291                     *dirty &= ~(L_NEED_CE | L_CLRTOEOL);
1292                     pcol = col;
1293                 }
1294             }
1295             else {
1296                 pcol = col;
1297             }
1298             if (line < LINES - 2 && pline == line - 1 && pcol == 0) {
1299                 switch (moved) {
1300                 case RF_NEED_TO_MOVE:
1301                     MOVE(line, 0);
1302                     moved = RF_CR_OK;
1303                     break;
1304                 case RF_CR_OK:
1305                     write1('\n');
1306                     write1('\r');
1307                     break;
1308                 case RF_NONEED_TO_MOVE:
1309                     moved = RF_CR_OK;
1310                     break;
1311                 }
1312             }
1313             else {
1314                 MOVE(line, pcol);
1315                 moved = RF_CR_OK;
1316             }
1317             if (*dirty & (L_NEED_CE | L_CLRTOEOL)) {
1318                 writestr(T_ce);
1319                 if (col != pcol)
1320                     MOVE(line, col);
1321             }
1322             pline = line;
1323             pcol = col;
1324             for (; col < COLS; col++) {
1325                 if (pr[col] & S_EOL)
1326                     break;
1327
1328                 /* 
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
1336                  * (COLS-1,LINES-1).
1337                  */
1338 #if !defined(USE_BG_COLOR) || defined(__CYGWIN__)
1339 #ifdef __CYGWIN__
1340                 if (isWinConsole)
1341 #endif
1342                     if (line == LINES - 1 && col == COLS - 1)
1343                         break;
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))
1349 #ifdef USE_BG_COLOR
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)
1354 #ifdef USE_BG_COLOR
1355                         || (mode & S_BCOLORED)
1356 #endif                          /* USE_BG_COLOR */
1357                         )
1358                         writestr(T_op);
1359                     if (mode & S_GRAPHICS)
1360                         writestr(T_ae);
1361                     writestr(T_me);
1362                     mode &= ~M_MEND;
1363                 }
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)
1368                         writestr(T_nd);
1369                     else if (pcol != col)
1370                         MOVE(line, col);
1371
1372                     if ((pr[col] & S_STANDOUT) && !(mode & S_STANDOUT)) {
1373                         writestr(T_so);
1374                         mode |= S_STANDOUT;
1375                     }
1376                     if ((pr[col] & S_UNDERLINE) && !(mode & S_UNDERLINE)) {
1377                         writestr(T_us);
1378                         mode |= S_UNDERLINE;
1379                     }
1380                     if ((pr[col] & S_BOLD) && !(mode & S_BOLD)) {
1381                         writestr(T_md);
1382                         mode |= S_BOLD;
1383                     }
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));
1388                     }
1389 #ifdef USE_BG_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));
1395                     }
1396 #endif                          /* USE_BG_COLOR */
1397                     if ((pr[col] & S_GRAPHICS) && !(mode & S_GRAPHICS)) {
1398 #ifdef USE_M17N
1399                         wc_putc_end(ttyf);
1400 #endif
1401                         if (!graph_enabled) {
1402                             graph_enabled = 1;
1403                             writestr(T_eA);
1404                         }
1405                         writestr(T_as);
1406                         mode |= S_GRAPHICS;
1407                     }
1408 #ifdef USE_M17N
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);
1413 #else
1414                     write1((pr[col] & S_GRAPHICS) ? graphchar(pc[col]) :
1415                            pc[col]);
1416 #endif
1417                     pcol = col + 1;
1418                 }
1419             }
1420             if (col == COLS)
1421                 moved = RF_NEED_TO_MOVE;
1422             for (; col < COLS && !(pr[col] & S_EOL); col++)
1423                 pr[col] |= S_EOL;
1424         }
1425         *dirty &= ~(L_NEED_CE | L_CLRTOEOL);
1426         if (mode & M_MEND) {
1427             if (mode & (S_COLORED
1428 #ifdef USE_BG_COLOR
1429                         | S_BCOLORED
1430 #endif                          /* USE_BG_COLOR */
1431                 ))
1432                 writestr(T_op);
1433             if (mode & S_GRAPHICS) {
1434                 writestr(T_ae);
1435 #ifdef USE_M17N
1436                 wc_putc_clear_status();
1437 #endif
1438             }
1439             writestr(T_me);
1440             mode &= ~M_MEND;
1441         }
1442     }
1443 #ifdef USE_M17N
1444     wc_putc_end(ttyf);
1445 #endif
1446     MOVE(CurLine, CurColumn);
1447     flush_tty();
1448 }
1449
1450 void
1451 clear(void)
1452 {
1453     int i, j;
1454     l_prop *p;
1455     writestr(T_cl);
1456     move(0, 0);
1457     for (i = 0; i < LINES; i++) {
1458         ScreenImage[i]->isdirty = 0;
1459         p = ScreenImage[i]->lineprop;
1460         for (j = 0; j < COLS; j++) {
1461             p[j] = S_EOL;
1462         }
1463     }
1464     CurrentMode = C_ASCII;
1465 }
1466
1467 #ifdef USE_RAW_SCROLL
1468 static void
1469 scroll_raw(void)
1470 {                               /* raw scroll */
1471     MOVE(LINES - 1, 0);
1472     write1('\n');
1473 }
1474
1475 void
1476 scroll(int n)
1477 {                               /* scroll up */
1478     int cli = CurLine, cco = CurColumn;
1479     Screen *t;
1480     int i, j, k;
1481
1482     i = LINES;
1483     j = n;
1484     do {
1485         k = j;
1486         j = i % k;
1487         i = k;
1488     } while (j);
1489     do {
1490         k--;
1491         i = k;
1492         j = (i + n) % LINES;
1493         t = ScreenImage[k];
1494         while (j != k) {
1495             ScreenImage[i] = ScreenImage[j];
1496             i = j;
1497             j = (i + n) % LINES;
1498         }
1499         ScreenImage[i] = t;
1500     } while (k);
1501
1502     for (i = 0; i < n; i++) {
1503         t = ScreenImage[LINES - 1 - i];
1504         t->isdirty = 0;
1505         for (j = 0; j < COLS; j++)
1506             t->lineprop[j] = S_EOL;
1507         scroll_raw();
1508     }
1509     move(cli, cco);
1510 }
1511
1512 void
1513 rscroll(int n)
1514 {                               /* scroll down */
1515     int cli = CurLine, cco = CurColumn;
1516     Screen *t;
1517     int i, j, k;
1518
1519     i = LINES;
1520     j = n;
1521     do {
1522         k = j;
1523         j = i % k;
1524         i = k;
1525     } while (j);
1526     do {
1527         k--;
1528         i = k;
1529         j = (LINES + i - n) % LINES;
1530         t = ScreenImage[k];
1531         while (j != k) {
1532             ScreenImage[i] = ScreenImage[j];
1533             i = j;
1534             j = (LINES + i - n) % LINES;
1535         }
1536         ScreenImage[i] = t;
1537     } while (k);
1538     if (T_sr && *T_sr) {
1539         MOVE(0, 0);
1540         for (i = 0; i < n; i++) {
1541             t = ScreenImage[i];
1542             t->isdirty = 0;
1543             for (j = 0; j < COLS; j++)
1544                 t->lineprop[j] = S_EOL;
1545             writestr(T_sr);
1546         }
1547         move(cli, cco);
1548     }
1549     else {
1550         for (i = 0; i < LINES; i++) {
1551             t = ScreenImage[i];
1552             t->isdirty |= L_DIRTY | L_NEED_CE;
1553             for (j = 0; j < COLS; j++) {
1554                 t->lineprop[j] |= S_DIRTY;
1555             }
1556         }
1557     }
1558 }
1559 #endif
1560
1561 #if 0
1562 void
1563 need_clrtoeol(void)
1564 {
1565     /* Clear to the end of line as the need arises */
1566     l_prop *lprop = ScreenImage[CurLine]->lineprop;
1567
1568     if (lprop[CurColumn] & S_EOL)
1569         return;
1570
1571     if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) ||
1572         ScreenImage[CurLine]->eol > CurColumn)
1573         ScreenImage[CurLine]->eol = CurColumn;
1574
1575     ScreenImage[CurLine]->isdirty |= L_NEED_CE;
1576 }
1577 #endif                          /* 0 */
1578
1579 /* XXX: conflicts with curses's clrtoeol(3) ? */
1580 void
1581 clrtoeol(void)
1582 {                               /* Clear to the end of line */
1583     int i;
1584     l_prop *lprop = ScreenImage[CurLine]->lineprop;
1585
1586     if (lprop[CurColumn] & S_EOL)
1587         return;
1588
1589     if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) ||
1590         ScreenImage[CurLine]->eol > CurColumn)
1591         ScreenImage[CurLine]->eol = CurColumn;
1592
1593     ScreenImage[CurLine]->isdirty |= L_CLRTOEOL;
1594     touch_line();
1595     for (i = CurColumn; i < COLS && !(lprop[i] & S_EOL); i++) {
1596         lprop[i] = S_EOL | S_DIRTY;
1597     }
1598 }
1599
1600 #ifdef USE_BG_COLOR
1601 void
1602 clrtoeol_with_bcolor(void)
1603 {
1604     int i, cli, cco;
1605     l_prop pr;
1606
1607     if (!(CurrentMode & S_BCOLORED)) {
1608         clrtoeol();
1609         return;
1610     }
1611     cli = CurLine;
1612     cco = CurColumn;
1613     pr = CurrentMode;
1614     CurrentMode = (CurrentMode & (M_CEOL | S_BCOLORED)) | C_ASCII;
1615     for (i = CurColumn; i < COLS; i++)
1616         addch(' ');
1617     move(cli, cco);
1618     CurrentMode = pr;
1619 }
1620
1621 void
1622 clrtoeolx(void)
1623 {
1624     clrtoeol_with_bcolor();
1625 }
1626 #else                           /* not USE_BG_COLOR */
1627
1628 void
1629 clrtoeolx(void)
1630 {
1631     clrtoeol();
1632 }
1633 #endif                          /* not USE_BG_COLOR */
1634
1635 void
1636 clrtobot_eol(void (*clrtoeol) ())
1637 {
1638     int l, c;
1639
1640     l = CurLine;
1641     c = CurColumn;
1642     (*clrtoeol) ();
1643     CurColumn = 0;
1644     CurLine++;
1645     for (; CurLine < LINES; CurLine++)
1646         (*clrtoeol) ();
1647     CurLine = l;
1648     CurColumn = c;
1649 }
1650
1651 void
1652 clrtobot(void)
1653 {
1654     clrtobot_eol(clrtoeol);
1655 }
1656
1657 void
1658 clrtobotx(void)
1659 {
1660     clrtobot_eol(clrtoeolx);
1661 }
1662
1663 #if 0
1664 void
1665 no_clrtoeol(void)
1666 {
1667     int i;
1668     l_prop *lprop = ScreenImage[CurLine]->lineprop;
1669
1670     ScreenImage[CurLine]->isdirty &= ~L_CLRTOEOL;
1671 }
1672 #endif                          /* 0 */
1673
1674 void
1675 addstr(char *s)
1676 {
1677 #ifdef USE_M17N
1678     int len;
1679
1680     while (*s != '\0') {
1681         len = wtf_len((wc_uchar *) s);
1682         addmch(s, len);
1683         s += len;
1684     }
1685 #else
1686     while (*s != '\0')
1687         addch(*(s++));
1688 #endif
1689 }
1690
1691 void
1692 addnstr(char *s, int n)
1693 {
1694     int i;
1695 #ifdef USE_M17N
1696     int len, width;
1697
1698     for (i = 0; *s != '\0';) {
1699         width = wtf_width((wc_uchar *) s);
1700         if (i + width > n)
1701             break;
1702         len = wtf_len((wc_uchar *) s);
1703         addmch(s, len);
1704         s += len;
1705         i += width;
1706     }
1707 #else
1708     for (i = 0; i < n && *s != '\0'; i++)
1709         addch(*(s++));
1710 #endif
1711 }
1712
1713 void
1714 addnstr_sup(char *s, int n)
1715 {
1716     int i;
1717 #ifdef USE_M17N
1718     int len, width;
1719
1720     for (i = 0; *s != '\0';) {
1721         width = wtf_width((wc_uchar *) s);
1722         if (i + width > n)
1723             break;
1724         len = wtf_len((wc_uchar *) s);
1725         addmch(s, len);
1726         s += len;
1727         i += width;
1728     }
1729 #else
1730     for (i = 0; i < n && *s != '\0'; i++)
1731         addch(*(s++));
1732 #endif
1733     for (; i < n; i++)
1734         addch(' ');
1735 }
1736
1737 void
1738 crmode(void)
1739 #ifndef HAVE_SGTTY_H
1740 {
1741     ttymode_reset(ICANON, IXON);
1742     ttymode_set(ISIG, 0);
1743 #ifdef HAVE_TERMIOS_H
1744     set_cc(VMIN, 1);
1745 #else                           /* not HAVE_TERMIOS_H */
1746     set_cc(VEOF, 1);
1747 #endif                          /* not HAVE_TERMIOS_H */
1748 }
1749 #else                           /* HAVE_SGTTY_H */
1750 {
1751     ttymode_set(CBREAK, 0);
1752 }
1753 #endif                          /* HAVE_SGTTY_H */
1754
1755 void
1756 nocrmode(void)
1757 #ifndef HAVE_SGTTY_H
1758 {
1759     ttymode_set(ICANON, 0);
1760 #ifdef HAVE_TERMIOS_H
1761     set_cc(VMIN, 4);
1762 #else                           /* not HAVE_TERMIOS_H */
1763     set_cc(VEOF, 4);
1764 #endif                          /* not HAVE_TERMIOS_H */
1765 }
1766 #else                           /* HAVE_SGTTY_H */
1767 {
1768     ttymode_reset(CBREAK, 0);
1769 }
1770 #endif                          /* HAVE_SGTTY_H */
1771
1772 void
1773 term_echo(void)
1774 {
1775     ttymode_set(ECHO, 0);
1776 }
1777
1778 void
1779 term_noecho(void)
1780 {
1781     ttymode_reset(ECHO, 0);
1782 }
1783
1784 void
1785 term_raw(void)
1786 #ifndef HAVE_SGTTY_H
1787 #ifdef IEXTEN
1788 #define TTY_MODE ISIG|ICANON|ECHO|IEXTEN
1789 #else                           /* not IEXTEN */
1790 #define TTY_MODE ISIG|ICANON|ECHO
1791 #endif                          /* not IEXTEN */
1792 {
1793     ttymode_reset(TTY_MODE, IXON | IXOFF);
1794 #ifdef HAVE_TERMIOS_H
1795     set_cc(VMIN, 1);
1796 #else                           /* not HAVE_TERMIOS_H */
1797     set_cc(VEOF, 1);
1798 #endif                          /* not HAVE_TERMIOS_H */
1799 }
1800 #else                           /* HAVE_SGTTY_H */
1801 {
1802     ttymode_set(RAW, 0);
1803 }
1804 #endif                          /* HAVE_SGTTY_H */
1805
1806 void
1807 term_cooked(void)
1808 #ifndef HAVE_SGTTY_H
1809 {
1810 #ifdef __EMX__
1811     /* On XFree86/OS2, some scrambled characters
1812      * will appear when asserting IEXTEN flag.
1813      */
1814     ttymode_set((TTY_MODE) & ~IEXTEN, 0);
1815 #else
1816     ttymode_set(TTY_MODE, 0);
1817 #endif
1818 #ifdef HAVE_TERMIOS_H
1819     set_cc(VMIN, 4);
1820 #else                           /* not HAVE_TERMIOS_H */
1821     set_cc(VEOF, 4);
1822 #endif                          /* not HAVE_TERMIOS_H */
1823 }
1824 #else                           /* HAVE_SGTTY_H */
1825 {
1826     ttymode_reset(RAW, 0);
1827 }
1828 #endif                          /* HAVE_SGTTY_H */
1829
1830 void
1831 term_cbreak(void)
1832 {
1833     term_cooked();
1834     term_noecho();
1835 }
1836
1837 void
1838 term_title(char *s)
1839 {
1840     if (!fmInitialized)
1841         return;
1842     if (title_str != NULL) {
1843 #ifdef __CYGWIN__
1844         if (isLocalConsole && title_str == CYGWIN_TITLE) {
1845             Str buff;
1846             buff = Sprintf(title_str, s);
1847             if (buff->length > 1024) {
1848                 Strtruncate(buff, 1024);
1849             }
1850             SetConsoleTitle(buff->ptr);
1851         }
1852         else if (isLocalConsole || !isWinConsole)
1853 #endif
1854         fprintf(ttyf, title_str, s);
1855     }
1856 }
1857
1858 char
1859 getch(void)
1860 {
1861     char c;
1862
1863     while (
1864 #ifdef SUPPORT_WIN9X_CONSOLE_MBCS
1865               read_win32_console(&c, 1)
1866 #else
1867               read(tty, &c, 1)
1868 #endif
1869               < (int)1) {
1870         if (errno == EINTR || errno == EAGAIN)
1871             continue;
1872         /* error happend on read(2) */
1873         quitfm();
1874         break;                  /* unreachable */
1875     }
1876     return c;
1877 }
1878
1879 #ifdef USE_MOUSE
1880 #ifdef USE_GPM
1881 char
1882 wgetch(void *p)
1883 {
1884     char c;
1885
1886     /* read(tty, &c, 1); */
1887     while (read(tty, &c, 1) < (ssize_t) 1) {
1888         if (errno == EINTR || errno == EAGAIN)
1889             continue;
1890         /* error happend on read(2) */
1891         quitfm();
1892         break;                  /* unreachable */
1893     }
1894     return c;
1895 }
1896
1897 int
1898 do_getch()
1899 {
1900     if (is_xterm)
1901         return getch();
1902     else
1903         return Gpm_Getch();
1904 }
1905 #endif                          /* USE_GPM */
1906
1907 #ifdef USE_SYSMOUSE
1908 int
1909 sysm_getch()
1910 {
1911     fd_set rfd;
1912     int key, x, y;
1913
1914     FD_ZERO(&rfd);
1915     FD_SET(tty, &rfd);
1916     while (select(tty + 1, &rfd, NULL, NULL, NULL) <= 0) {
1917         if (errno == EINTR) {
1918             x = xpix / cwidth;
1919             y = ypix / cheight;
1920             key = (*sysm_handler) (x, y, nbs, obs);
1921             if (key != 0)
1922                 return key;
1923         }
1924     }
1925     return getch();
1926 }
1927
1928 int
1929 do_getch()
1930 {
1931     if (is_xterm || !sysm_handler)
1932         return getch();
1933     else
1934         return sysm_getch();
1935 }
1936
1937 MySignalHandler
1938 sysmouse(SIGNAL_ARG)
1939 {
1940     struct mouse_info mi;
1941
1942     mi.operation = MOUSE_GETINFO;
1943     if (ioctl(tty, CONS_MOUSECTL, &mi) == -1)
1944         return;
1945     xpix = mi.u.data.x;
1946     ypix = mi.u.data.y;
1947     obs = nbs;
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);
1954 }
1955 #endif                          /* USE_SYSMOUSE */
1956 #endif                          /* USE_MOUSE */
1957
1958 void
1959 bell(void)
1960 {
1961     write1(7);
1962 }
1963
1964 void
1965 skip_escseq(void)
1966 {
1967     int c;
1968
1969     c = getch();
1970     if (c == '[' || c == 'O') {
1971         c = getch();
1972 #ifdef USE_MOUSE
1973         if (is_xterm && c == 'M') {
1974             getch();
1975             getch();
1976             getch();
1977         }
1978         else
1979 #endif
1980             while (IS_DIGIT(c))
1981                 c = getch();
1982     }
1983 }
1984
1985 int
1986 sleep_till_anykey(int sec, int purge)
1987 {
1988     fd_set rfd;
1989     struct timeval tim;
1990     int er, c, ret;
1991     TerminalMode ioval;
1992
1993     TerminalGet(tty, &ioval);
1994     term_raw();
1995
1996     tim.tv_sec = sec;
1997     tim.tv_usec = 0;
1998
1999     FD_ZERO(&rfd);
2000     FD_SET(tty, &rfd);
2001
2002     ret = select(tty + 1, &rfd, 0, 0, &tim);
2003     if (ret > 0 && purge) {
2004         c = getch();
2005         if (c == ESC_CODE)
2006             skip_escseq();
2007     }
2008     er = TerminalSet(tty, &ioval);
2009     if (er == -1) {
2010         printf("Error occured: errno=%d\n", errno);
2011         reset_exit(SIGNAL_ARGLIST);
2012     }
2013     return ret;
2014 }
2015
2016 #ifdef USE_MOUSE
2017
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();}
2022
2023 #ifdef USE_GPM
2024 /* Linux console with GPM support */
2025
2026 void
2027 mouse_init()
2028 {
2029     Gpm_Connect conn;
2030     extern int gpm_process_mouse(Gpm_Event *, void *);
2031     int r;
2032
2033     if (mouseActive)
2034         return;
2035     conn.eventMask = ~0;
2036     conn.defaultMask = 0;
2037     conn.maxMod = 0;
2038     conn.minMod = 0;
2039
2040     r = Gpm_Open(&conn, 0);
2041     if (r == -2) {
2042         /*
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.
2048          */
2049         Gpm_Close();
2050         is_xterm = (NEED_XTERM_ON | NEED_XTERM_OFF);
2051     }
2052     else if (r >= 0) {
2053         gpm_handler = gpm_process_mouse;
2054         is_xterm = 0;
2055     }
2056     if (is_xterm) {
2057         XTERM_ON;
2058     }
2059     mouseActive = 1;
2060 }
2061
2062 void
2063 mouse_end()
2064 {
2065     if (mouseActive == 0)
2066         return;
2067     if (is_xterm) {
2068         XTERM_OFF;
2069     }
2070     else
2071         Gpm_Close();
2072     mouseActive = 0;
2073 }
2074
2075 #elif   defined(USE_SYSMOUSE)
2076 /* *BSD console with sysmouse support */
2077 void
2078 mouse_init()
2079 {
2080     mouse_info_t mi;
2081     extern int sysm_process_mouse();
2082
2083     if (mouseActive)
2084         return;
2085     if (is_xterm) {
2086         XTERM_ON;
2087     }
2088     else {
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 */
2094         video_info_t vi;
2095
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;
2100         }
2101 #endif                          /* defined(FBIO_MODEINFO) ||
2102                                  * defined(CONS_MODEINFO) */
2103         mySignal(SIGUSR2, SIG_IGN);
2104         mi.operation = MOUSE_MODE;
2105         mi.u.mode.mode = 0;
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;
2113         }
2114     }
2115     mouseActive = 1;
2116 }
2117
2118 void
2119 mouse_end()
2120 {
2121     if (mouseActive == 0)
2122         return;
2123     if (is_xterm) {
2124         XTERM_OFF;
2125     }
2126     else {
2127         mouse_info_t mi;
2128         mi.operation = MOUSE_MODE;
2129         mi.u.mode.mode = 0;
2130         mi.u.mode.signal = 0;
2131         ioctl(tty, CONS_MOUSECTL, &mi);
2132     }
2133     mouseActive = 0;
2134 }
2135
2136 #else
2137 /* not GPM nor SYSMOUSE, but use mouse with xterm */
2138
2139 void
2140 mouse_init()
2141 {
2142     if (mouseActive)
2143         return;
2144     if (is_xterm & NEED_XTERM_ON) {
2145         XTERM_ON;
2146     }
2147 #ifdef __CYGWIN__
2148     else if (is_xterm & NEED_CYGWIN_ON) {
2149         CYGWIN_ON;
2150     }
2151 #endif
2152     mouseActive = 1;
2153 }
2154
2155 void
2156 mouse_end()
2157 {
2158     if (mouseActive == 0)
2159         return;
2160     if (is_xterm & NEED_XTERM_OFF) {
2161         XTERM_OFF;
2162     }
2163 #ifdef __CYGWIN__
2164     else if (is_xterm & NEED_CYGWIN_OFF) {
2165         CYGWIN_OFF;
2166     }
2167 #endif
2168     mouseActive = 0;
2169 }
2170
2171 #endif                          /* not USE_GPM nor USE_SYSMOUSE */
2172
2173
2174 void
2175 mouse_active()
2176 {
2177     if (!mouseActive)
2178         mouse_init();
2179 }
2180
2181 void
2182 mouse_inactive()
2183 {
2184     if (mouseActive && is_xterm)
2185         mouse_end();
2186 }
2187
2188 #endif                          /* USE_MOUSE */
2189
2190 void
2191 flush_tty()
2192 {
2193     if (ttyf)
2194         fflush(ttyf);
2195 }
2196
2197 #ifdef USE_IMAGE
2198 void
2199 touch_cursor()
2200 {
2201 #ifdef USE_M17N
2202     int i;
2203 #endif
2204     touch_line();
2205 #ifdef USE_M17N
2206     for (i = CurColumn; i >= 0; i--) {
2207         touch_column(i);
2208         if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2) 
2209             break;
2210     }
2211     for (i = CurColumn + 1; i < COLS; i++) {
2212         if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2) 
2213             break;
2214         touch_column(i);
2215     }
2216 #else
2217     touch_column(CurColumn);
2218 #endif
2219 }
2220 #endif
2221
2222 #ifdef __MINGW32_VERSION
2223
2224 int tgetent(char *bp, char *name)
2225 {
2226   return 0;
2227 }
2228
2229 int tgetnum(char *id)
2230 {
2231   return -1;
2232 }
2233
2234 int tgetflag(char *id)
2235 {
2236   return 0;
2237 }
2238
2239 char *tgetstr(char *id, char **area)
2240 {
2241   id = "";
2242 }
2243
2244 char *tgoto(char *cap, int col, int row)
2245 {
2246 }
2247
2248 int tputs(char *str, int affcnt, int (*putc)(char))
2249 {
2250 }
2251
2252 char *ttyname(int tty)
2253 {
2254   return "CON";
2255 }
2256
2257 #endif /* __MINGW32_VERSION */