1 /*
2  * console.c
3  *
4  * All rights reserved. Copyright (C) 1996 by NARITA Tomio.
5  * $Id: console.c,v 1.8 2004/01/05 07:27:46 nrt Exp $
6  */
7 /*
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <signal.h>
27 
28 #ifdef MSDOS
29 #include <dos.h>
30 #endif /* MSDOS */
31 
32 #ifdef UNIX
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #ifdef HAVE_TERMIOS_H
38 #include <termios.h>
39 #endif /* HAVE_TERMIOS_H */
40 
41 #ifdef HAVE_SYS_IOCTL_H
42 #include <sys/ioctl.h>
43 #endif /* HAVE_SYS_IOCTL_H */
44 #endif /* UNIX */
45 
46 #ifdef TERMINFO
47 #include <termio.h>
48 #include <curses.h>
49 #include <term.h>
50 #endif /* TERMINFO */
51 
52 #include <import.h>
53 #include <ascii.h>
54 #include <attr.h>
55 #include <begin.h>
56 #include <console.h>
57 
58 #define ANSI_ATTR_LENGTH	8
59 
60 #if defined( MSDOS ) || defined( WIN32 )
61 private char tbuf[ 16 ];
62 
63 private char *clear_screen		= "\x1b[2J";
64 private char *clr_eol			= "\x1b[K";
65 private char *delete_line		= "\x1b[M";
66 private char *insert_line		= "\x1b[L";
67 private char *enter_standout_mode	= "\x1b[7m";
68 private char *exit_standout_mode	= "\x1b[m";
69 private char *enter_underline_mode	= "\x1b[4m";
70 private char *exit_underline_mode	= "\x1b[m";
71 private char *enter_bold_mode		= "\x1b[1m";
72 private char *exit_attribute_mode	= "\x1b[m";
73 private char *cursor_visible		= NULL;
74 private char *cursor_invisible		= NULL;
75 private char *enter_ca_mode		= NULL;
76 private char *exit_ca_mode		= NULL;
77 private char *keypad_local		= NULL;
78 private char *keypad_xmit		= NULL;
79 
tputs(char * cp,int affcnt,int (* outc)(char))80 private void tputs( char *cp, int affcnt, int (*outc)(char) )
81 {
82   while( *cp )
83     outc( *cp++ );
84 }
85 
86 private int (*putfunc)(char) = ConsolePrint;
87 #endif /* MSDOS */
88 
89 #ifdef UNIX
90 
91 #ifdef HAVE_TERMIOS_H
92 private struct termios ttyOld, ttyNew;
93 #else
94 private struct sgttyb ttyOld, ttyNew;
95 #endif /* HAVE_TERMIOS_H */
96 
97 #ifdef putchar
putfunc(int ch)98 private int putfunc( int ch )
99 {
100   return putchar( ch );
101 }
102 #else
103 private int (*putfunc)(int) = putchar;
104 #endif
105 
106 #endif /* UNIX */
107 
108 #ifdef TERMCAP
109 private char entry[ 1024 ];
110 private char func[ 1024 ];
111 
112 extern char *tgetstr(), *tgoto();
113 extern int tgetent(), tgetflag(), tgetnum(), tputs();
114 
115 private char *cursor_address		= NULL;
116 private char *clear_screen		= NULL;
117 private char *clr_eol			= NULL;
118 private char *insert_line		= NULL;
119 private char *delete_line		= NULL;
120 private char *enter_standout_mode	= NULL;
121 private char *exit_standout_mode	= NULL;
122 private char *enter_underline_mode	= NULL;
123 private char *exit_underline_mode	= NULL;
124 private char *enter_bold_mode		= NULL;
125 private char *exit_attribute_mode	= NULL;
126 private char *cursor_visible		= NULL;
127 private char *cursor_invisible		= NULL;
128 private char *enter_ca_mode		= NULL;
129 private char *exit_ca_mode		= NULL;
130 private char *keypad_local		= NULL;
131 private char *keypad_xmit		= NULL;
132 #endif /* TERMCAP */
133 
ConsoleInit()134 public void ConsoleInit()
135 {
136   allow_interrupt	= FALSE;
137   kb_interrupted	= FALSE;
138   window_changed	= FALSE;
139 }
140 
ConsoleResetAnsiSequence()141 public void ConsoleResetAnsiSequence()
142 {
143   ansi_standout		= "7";
144   ansi_reverse		= "7";
145   ansi_blink		= "5";
146   ansi_underline	= "4";
147   ansi_hilight		= "1";
148 }
149 
150 #ifdef MSDOS
InterruptIgnoreHandler(int arg)151 private void InterruptIgnoreHandler( int arg )
152 {
153   signal( SIGINT, InterruptIgnoreHandler );
154 }
155 #endif /* MSDOS */
156 
InterruptHandler(int arg)157 private RETSIGTYPE InterruptHandler( int arg )
158 {
159   kb_interrupted = TRUE;
160 
161 #ifndef HAVE_SIGVEC
162   signal( SIGINT, InterruptHandler );
163 #endif /* HAVE_SIGVEC */
164 }
165 
ConsoleEnableInterrupt()166 public void ConsoleEnableInterrupt()
167 {
168 #ifdef MSDOS
169   allow_interrupt = TRUE;
170   signal( SIGINT, InterruptHandler );
171 #endif /* MSDOS */
172 
173 #ifdef UNIX
174   signal( SIGTSTP, SIG_IGN );
175 #ifdef HAVE_TERMIOS_H
176   ttyNew.c_lflag |= ISIG;
177   tcsetattr( 0, TCSADRAIN, &ttyNew );
178 #else /* HAVE_TERMIOS_H */
179   ttyNew.sg_flags &= ~RAW;
180   ioctl( 0, TIOCSETN, &ttyNew );
181 #endif /* HAVE_TERMIOS_H */
182 #endif /* UNIX */
183 }
184 
ConsoleDisableInterrupt()185 public void ConsoleDisableInterrupt()
186 {
187 #ifdef MSDOS
188   allow_interrupt = FALSE;
189   signal( SIGINT, InterruptIgnoreHandler );
190 #endif /* MSDOS */
191 
192 #ifdef UNIX
193 #ifdef HAVE_TERMIOS_H
194   ttyNew.c_lflag &= ~ISIG;
195   tcsetattr( 0, TCSADRAIN, &ttyNew );
196 #else /* HAVE_TERMIOS_H */
197   ttyNew.sg_flags |= RAW;
198   ioctl( 0, TIOCSETN, &ttyNew );
199 #endif /* HAVE_TERMIOS_H */
200   signal( SIGTSTP, SIG_DFL );
201 #endif /* UNIX */
202 }
203 
ConsoleGetWindowSize()204 public void ConsoleGetWindowSize()
205 {
206 #ifdef UNIX
207 #ifdef WIN32
208   WIDTH  = 80;
209   HEIGHT = 24;
210 #else /* WIN32 */
211   struct winsize winSize;
212 
213   ioctl( 0, TIOCGWINSZ, &winSize );
214   WIDTH = winSize.ws_col;
215   HEIGHT = winSize.ws_row;
216   if( 0 >= WIDTH || 0 >= HEIGHT ){
217 #ifdef HAVE_TGETNUM
218     WIDTH = tgetnum( "columns" );
219     HEIGHT = tgetnum( "lines" );
220 #else
221     WIDTH = tigetnum( "columns" );
222     HEIGHT = tigetnum( "lines" );
223 #endif /* HAVE_TGETNUM */
224     if( 0 >= WIDTH || 0 >= HEIGHT )
225       WIDTH = 80, HEIGHT = 24;
226   }
227 #endif /* WIN32 */
228 #endif /* UNIX */
229 }
230 
231 #ifdef UNIX
WindowChangeHandler(int arg)232 private RETSIGTYPE WindowChangeHandler( int arg )
233 {
234   window_changed = TRUE;
235 
236   ConsoleGetWindowSize();
237 
238 #ifndef HAVE_SIGVEC
239   signal( SIGWINCH, WindowChangeHandler );
240 #endif /* HAVE_SIGVEC */
241 }
242 #endif /* UNIX */
243 
ConsoleTermInit()244 public void ConsoleTermInit()
245 {
246   /*
247    * 1. setup terminal capability
248    * 2. retrieve window size
249    * 3. initialize terminal status
250    */
251 
252 #if defined( MSDOS ) || defined( WIN32 )
253   byte *ptr;
254 
255 #define ANSI		0
256 #define FMRCARD		1
257 
258   int term = ANSI;
259 
260   if( NULL != (ptr = getenv("TERM")) ){
261     if( !strcmp( ptr, "fmr4020" ) ){
262       term = FMRCARD;
263       WIDTH = 40;
264       HEIGHT = 19;
265     } else if( !strcmp( ptr, "fmr8025" ) ){
266       term = FMRCARD;
267       WIDTH = 80;
268       HEIGHT = 24;
269     }
270   }
271 
272   switch( term ){
273   case FMRCARD:
274     delete_line      = "\x1bR";
275     insert_line      = "\x1b" "E";
276     cursor_visible   = "\x1b[v";
277     cursor_invisible = "\x1b[1v";
278     break;
279   default:
280     WIDTH  = 80;
281     HEIGHT = 24;
282   }
283 
284   cur_left		= "\x1bK";
285   cur_right		= "\x1bM";
286   cur_up		= "\x1bH";
287   cur_down		= "\x1bP";
288   cur_ppage		= "\x1bI";
289   cur_npage		= "\x1bQ";
290 
291 #endif /* MSDOS */
292 
293 #ifdef TERMCAP
294   byte *term, *ptr;
295 #endif
296 #ifdef TERMINFO
297   byte *term;
298   int state;
299 #endif
300 
301 #ifdef UNIX
302   int fd = open("/dev/tty", O_RDONLY);
303   dup2(fd, 0);
304   close(fd);
305 #endif
306 
307 #ifdef TERMCAP
308   if( NULL == (term = getenv( "TERM" )) )
309     fprintf( stderr, "lv: environment variable TERM is required\n" );
310   if( 0 >= tgetent( entry, term ) )
311     fprintf( stderr, "lv: %s not found in termcap\n", term );
312 
313   ConsoleGetWindowSize();
314 
315   ptr = func;
316 
317   cursor_address	= tgetstr( "cm", &ptr );
318   clear_screen		= tgetstr( "cl", &ptr );
319   clr_eol		= tgetstr( "ce", &ptr );
320   insert_line		= tgetstr( "al", &ptr );
321   delete_line		= tgetstr( "dl", &ptr );
322   enter_standout_mode	= tgetstr( "so", &ptr );
323   exit_standout_mode	= tgetstr( "se", &ptr );
324   enter_underline_mode	= tgetstr( "us", &ptr );
325   exit_underline_mode	= tgetstr( "ue", &ptr );
326   enter_bold_mode	= tgetstr( "md", &ptr );
327   exit_attribute_mode	= tgetstr( "me", &ptr );
328   cursor_visible	= tgetstr( "ve", &ptr );
329   cursor_invisible	= tgetstr( "vi", &ptr );
330   enter_ca_mode		= tgetstr( "ti", &ptr );
331   exit_ca_mode		= tgetstr( "te", &ptr );
332 
333   keypad_local		= tgetstr( "ke", &ptr );
334   keypad_xmit		= tgetstr( "ks", &ptr );
335 
336   cur_left		= tgetstr( "kl", &ptr );
337   cur_right		= tgetstr( "kr", &ptr );
338   cur_up		= tgetstr( "ku", &ptr );
339   cur_down		= tgetstr( "kd", &ptr );
340   cur_ppage		= tgetstr( "kP", &ptr );
341   cur_npage		= tgetstr( "kN", &ptr );
342 
343   if( NULL == cursor_address || NULL == clear_screen || NULL == clr_eol )
344     fprintf( stderr, "lv: termcap cm, cl, ce are required\n" );
345 
346   if( NULL == insert_line || NULL == delete_line )
347     no_scroll = TRUE;
348   else
349     no_scroll = FALSE;
350 #endif /* TERMCAP */
351 
352 #ifdef TERMINFO
353 
354   if( NULL == (term = getenv( "TERM" )) )
355     fprintf( stderr, "lv: environment variable TERM is required\n" );
356 
357   setupterm( term, 1, &state );
358   if( 1 != state )
359     fprintf( stderr, "lv: cannot initialize terminal\n" );
360 
361   ConsoleGetWindowSize();
362 
363   cur_left		= key_left;
364   cur_right		= key_right;
365   cur_up		= key_up;
366   cur_down		= key_down;
367   cur_ppage		= key_ppage;
368   cur_npage		= key_npage;
369 
370   if( NULL == cursor_address || NULL == clear_screen || NULL == clr_eol )
371     fprintf( stderr, "lv: terminfo cursor_address, clr_eol are required\n" );
372 
373   if( NULL == insert_line || NULL == delete_line )
374     no_scroll = TRUE;
375   else
376     no_scroll = FALSE;
377 #endif /* TERMINFO */
378 
379   if( enter_ca_mode )
380     tputs( enter_ca_mode, 1, putfunc );
381   if( keypad_xmit )
382     tputs( keypad_xmit, 1, putfunc );
383 }
384 
ConsoleSetUp()385 public void ConsoleSetUp()
386 {
387 #ifdef MSDOS
388   signal( SIGINT, InterruptIgnoreHandler );
389 #endif /* MSDOS */
390 
391 #ifdef HAVE_SIGVEC
392   struct sigvec sigVec;
393 
394   sigVec.sv_handler = WindowChangeHandler;
395   sigVec.sv_mask = sigmask( SIGWINCH );
396   sigVec.sv_flags = SV_INTERRUPT;
397   sigvec( SIGWINCH, &sigVec, NULL );
398 
399   sigVec.sv_handler = InterruptHandler;
400   sigVec.sv_mask = sigmask( SIGINT );
401   sigVec.sv_flags = SV_INTERRUPT;
402   sigvec( SIGINT, &sigVec, NULL );
403 #else
404 # ifdef SIGWINCH
405   signal( SIGWINCH, WindowChangeHandler );
406 # endif
407   signal( SIGINT, InterruptHandler );
408 #endif /* HAVE_SIGVEC */
409 
410 #ifdef UNIX
411 #ifdef HAVE_TERMIOS_H
412   tcgetattr( 0, &ttyOld );
413   ttyNew = ttyOld;
414   ttyNew.c_iflag &= ~ISTRIP;
415   ttyNew.c_iflag &= ~INLCR;
416   ttyNew.c_iflag &= ~ICRNL;
417   ttyNew.c_iflag &= ~IGNCR;
418   ttyNew.c_lflag &= ~ISIG;
419   ttyNew.c_lflag &= ~ICANON;
420   ttyNew.c_lflag &= ~ECHO;
421   ttyNew.c_lflag &= ~IEXTEN;
422 #ifdef VDISCRD /* IBM AIX */
423 #define VDISCARD VDISCRD
424 #endif
425   ttyNew.c_cc[ VDISCARD ] = -1;
426   ttyNew.c_cc[ VMIN ] = 1;
427   ttyNew.c_cc[ VTIME ] = 0;
428   tcsetattr( 0, TCSADRAIN, &ttyNew );
429 #else
430   ioctl( 0, TIOCGETP, &ttyOld );
431   ttyNew = ttyOld;
432   ttyNew.sg_flags &= ~ECHO;
433   ttyNew.sg_flags |= RAW;
434   ttyNew.sg_flags |= CRMOD;
435   ioctl( 0, TIOCSETN, &ttyNew );
436 #endif /* HAVE_TERMIOS_H */
437 #endif /* UNIX */
438 }
439 
ConsoleSetDown()440 public void ConsoleSetDown()
441 {
442 #ifdef UNIX
443 #ifdef HAVE_TERMIOS_H
444   tcsetattr( 0, TCSADRAIN, &ttyOld );
445 #else
446   ioctl( 0, TIOCSETN, &ttyOld );
447 #endif /* HAVE_TERMIOS_H */
448 #endif /* UNIX */
449 
450   if( keypad_local )
451     tputs( keypad_local, 1, putfunc );
452   if( exit_ca_mode )
453     tputs( exit_ca_mode, 1, putfunc );
454   else {
455     ConsoleSetCur( 0, HEIGHT - 1 );
456     ConsolePrint( CR );
457     ConsolePrint( LF );
458   }
459 }
460 
ConsoleShellEscape()461 public void ConsoleShellEscape()
462 {
463 #ifdef UNIX
464 #ifdef HAVE_TERMIOS_H
465   tcsetattr( 0, TCSADRAIN, &ttyOld );
466 #else
467   ioctl( 0, TIOCSETN, &ttyOld );
468 #endif /* HAVE_TERMIOS_H */
469 #endif /* UNIX */
470 
471   if( keypad_local )
472     tputs( keypad_local, 1, putfunc );
473   if( exit_ca_mode )
474     tputs( exit_ca_mode, 1, putfunc );
475   else
476     ConsoleSetCur( 0, HEIGHT - 1 );
477 
478   ConsoleFlush();
479 }
480 
ConsoleReturnToProgram()481 public void ConsoleReturnToProgram()
482 {
483   if( keypad_xmit )
484     tputs( keypad_xmit, 1, putfunc );
485   if( enter_ca_mode )
486     tputs( enter_ca_mode, 1, putfunc );
487 
488 #ifdef UNIX
489 #ifdef HAVE_TERMIOS_H
490   tcsetattr( 0, TCSADRAIN, &ttyNew );
491 #else
492   ioctl( 0, TIOCSETN, &ttyNew );
493 #endif /* HAVE_TERMIOS_H */
494 #endif /* UNIX */
495 }
496 
ConsoleSuspend()497 public void ConsoleSuspend()
498 {
499 #ifndef MSDOS /* if NOT defind */
500   kill(0, SIGSTOP);	/*to pgrp*/
501 #endif
502 }
503 
ConsoleGetChar()504 public int ConsoleGetChar()
505 {
506 #ifdef MSDOS
507   return getch();
508 #endif /* MSDOS */
509 
510 #ifdef UNIX
511   byte buf;
512 
513   if( 0 > read( 0, &buf, 1 ) )
514     return EOF;
515   else
516     return (int)buf;
517 #endif /* UNIX */
518 }
519 
520 #ifdef MSDOS
521 union REGS regs;
522 #endif /* MSDOS */
523 
ConsolePrint(byte c)524 public int ConsolePrint( byte c )
525 {
526 #ifdef MSDOS
527   /*
528    * fast console output, but remember that you cannot use lv
529    * through remote terminals, for example AUX (RS232C).
530    * I changed this code for FreeDOS. Because function code No.6
531    * with Int 21h on FreeDOS (Alpha 5) doesn't seem to work correctly.
532    */
533   regs.h.al = c;
534   return int86( 0x29, &regs, &regs );
535 /*
536   return (int)bdos( 0x06, 0xff != c ? c : 0, 0 );
537 */
538 #endif /* MSDOS */
539 
540 #ifdef UNIX
541   return putchar( c );
542 #endif /* UNIX */
543 }
544 
ConsolePrints(byte * str)545 public void ConsolePrints( byte *str )
546 {
547   while( *str )
548     ConsolePrint( *str++ );
549 }
550 
ConsolePrintsStr(str_t * str,int length)551 public void ConsolePrintsStr( str_t *str, int length )
552 {
553   int i;
554   byte attr, lastAttr;
555 
556   attr = lastAttr = ATTR_NULL;
557   for( i = 0 ; i < length ; i++ ){
558     attr = ( 0xff00 & str[ i ] ) >> 8;
559     if( lastAttr != attr )
560       ConsoleSetAttribute( attr );
561     lastAttr = attr;
562     ConsolePrint( 0xff & str[ i ] );
563   }
564   if( 0 != attr )
565     ConsoleSetAttribute( 0 );
566 }
567 
ConsoleFlush()568 public void ConsoleFlush()
569 {
570 #ifdef UNIX
571   fflush( stdout );
572 #endif /* UNIX */
573 }
574 
ConsoleSetCur(int x,int y)575 public void ConsoleSetCur( int x, int y )
576 {
577 #if defined( MSDOS ) || defined( WIN32 )
578   sprintf( tbuf, "\x1b[%d;%dH", y + 1, x + 1 );
579   ConsolePrints( tbuf );
580 #endif /* MSDOS */
581 
582 #ifdef TERMCAP
583   tputs( tgoto( cursor_address, x, y ), 1, putfunc );
584 #endif /* TERMCAP */
585 
586 #ifdef TERMINFO
587   tputs( tparm( cursor_address, y, x ), 1, putfunc );
588 #endif /* TERMINFO */
589 }
590 
ConsoleOnCur()591 public void ConsoleOnCur()
592 {
593   if( cursor_visible )
594     tputs( cursor_visible, 1, putfunc );
595 }
596 
ConsoleOffCur()597 public void ConsoleOffCur()
598 {
599   if( cursor_invisible )
600     tputs( cursor_invisible, 1, putfunc );
601 }
602 
ConsoleClearScreen()603 public void ConsoleClearScreen()
604 {
605   tputs( clear_screen, 1, putfunc );
606 }
607 
ConsoleClearRight()608 public void ConsoleClearRight()
609 {
610   tputs( clr_eol, 1, putfunc );
611 }
612 
ConsoleGoAhead()613 public void ConsoleGoAhead()
614 {
615   ConsolePrint( 0x0d );
616 }
617 
ConsoleScrollUp()618 public void ConsoleScrollUp()
619 {
620   if( delete_line )
621     tputs( delete_line, 1, putfunc );
622 }
623 
ConsoleScrollDown()624 public void ConsoleScrollDown()
625 {
626   if( insert_line )
627     tputs( insert_line, 1, putfunc );
628 }
629 
630 private byte prevAttr = 0;
631 
ConsoleSetAttribute(byte attr)632 public void ConsoleSetAttribute( byte attr )
633 {
634 #ifndef MSDOS /* IF NOT DEFINED */
635   if( TRUE == allow_ansi_esc ){
636 #endif /* MSDOS */
637     ConsolePrints( "\x1b[0" );
638     if( 0 != attr ){
639       if( ATTR_STANDOUT & attr ){
640 	ConsolePrint( ';' );
641 	ConsolePrints( ansi_standout );
642       } else if( ATTR_COLOR & attr ){
643 	if( ATTR_REVERSE & attr ){
644 	  if( ATTR_COLOR_B & attr ){
645 	    ConsolePrints( ";30;4" );
646 	    ConsolePrint( ( ATTR_COLOR & attr ) + '0' );
647 	  } else {
648 	    ConsolePrints( ";37;4" );
649 	    ConsolePrint( ( ATTR_COLOR & attr ) + '0' );
650 	  }
651 	} else {
652 	  ConsolePrints( ";3" );
653 	  ConsolePrint( ( ATTR_COLOR & attr ) + '0' );
654 	}
655       } else if( ATTR_REVERSE & attr ){
656 	ConsolePrint( ';' );
657 	ConsolePrints( ansi_reverse );
658       }
659       if( ATTR_BLINK & attr ){
660 	ConsolePrint( ';' );
661 	ConsolePrints( ansi_blink );
662       }
663       if( ATTR_UNDERLINE & attr ){
664 	ConsolePrint( ';' );
665 	ConsolePrints( ansi_underline );
666       }
667       if( ATTR_HILIGHT & attr ){
668 	ConsolePrint( ';' );
669 	ConsolePrints( ansi_hilight );
670       }
671     }
672     ConsolePrint( 'm' );
673 #ifndef MSDOS /* IF NOT DEFINED */
674   } else {
675     /*
676      * non ansi sequence
677      */
678     if( ( ATTR_HILIGHT & prevAttr ) && 0 == ( ATTR_HILIGHT & attr ) )
679       if( exit_attribute_mode )
680 	tputs( exit_attribute_mode, 1, putfunc );
681     if( ( ATTR_UNDERLINE & prevAttr ) && 0 == ( ATTR_UNDERLINE & attr ) )
682       if( exit_underline_mode )
683 	tputs( exit_underline_mode, 1, putfunc );
684     if( ( ATTR_STANDOUT & prevAttr ) && 0 == ( ATTR_STANDOUT & attr ) )
685       if( exit_standout_mode )
686 	tputs( exit_standout_mode, 1, putfunc );
687 
688     if( ATTR_HILIGHT & attr )
689       if( enter_bold_mode )
690 	tputs( enter_bold_mode, 1, putfunc );
691     if( ATTR_UNDERLINE & attr )
692       if( enter_underline_mode )
693 	tputs( enter_underline_mode, 1, putfunc );
694     if( ATTR_STANDOUT & attr )
695       if( enter_standout_mode )
696 	tputs( enter_standout_mode, 1, putfunc );
697   }
698   prevAttr = attr;
699 #endif /* MSDOS */
700 }
701