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, ®s, ®s );
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