]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - win32/console.c
Import of tcsh-6.18.01
[FreeBSD/FreeBSD.git] / win32 / console.c
1 /*$Header: /p/tcsh/cvsroot/tcsh/win32/console.c,v 1.9 2006/08/27 01:13:28 amold Exp $*/
2 /*-
3  * Copyright (c) 1980, 1991 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 /*
32  * console.c: hacks to do various cursor movement/attribute things
33  * -amol
34  */
35 #define WIN32_LEAN_AND_MEAN
36 #include <windows.h>
37 #include <wincon.h>
38 #include <stdio.h>
39 #include "ntport.h"
40
41
42 // int to SHORT. caused by all the stupid functions that take WORDs
43 #pragma warning(disable:4244)
44
45 void ScrollBuf(HANDLE,CONSOLE_SCREEN_BUFFER_INFO*,int);
46 void NT_MoveToLineOrChar(int ,int ) ;
47 WORD get_attributes();
48
49
50 #define FSHIN   16              /* Preferred desc for shell input */
51 #define FSHOUT  17              /* Preferred desc for shell input */
52
53 #define FOREGROUND_BLACK (FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE)
54 #define FOREGROUND_WHITE 0
55 #define BACKGROUND_BLACK (BACKGROUND_RED |BACKGROUND_GREEN | BACKGROUND_BLUE)
56 #define BACKGROUND_WHITE 0
57
58 static WORD wNormalAttributes;
59
60
61 static int nt_is_raw;
62 //
63 // The following are used to optimize some console routines. It avoids having
64 // to call GetConsoleScreenBufferInfo.
65 // Seems to have helped the speed a bit. -amol
66 //
67 HANDLE ghstdout;
68 HANDLE ghReverse;
69
70 //
71 // This function is called to set the values for above variables.
72 //
73 void redo_console(void) {
74
75         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
76         HANDLE hTemp= GetStdHandle(STD_OUTPUT_HANDLE);
77         WORD dbga;
78         DWORD wrote;
79         COORD origin = {0,0};
80
81         if (!DuplicateHandle(GetCurrentProcess(),hTemp,GetCurrentProcess(),
82                                 &ghstdout,0,TRUE,DUPLICATE_SAME_ACCESS) ) {
83                 ;
84         }
85
86         if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) {
87                 wNormalAttributes = FOREGROUND_BLACK | BACKGROUND_WHITE;
88         }
89         else
90                 wNormalAttributes = scrbuf.wAttributes;
91
92         ghReverse = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,
93                         FILE_SHARE_READ | FILE_SHARE_WRITE,
94                         NULL,
95                         CONSOLE_TEXTMODE_BUFFER,
96                         NULL);
97
98         dbga = ((wNormalAttributes & 0x00f0) >> 4) |
99                 ((wNormalAttributes & 0x000f) << 4) ;
100
101         FillConsoleOutputAttribute(ghReverse,dbga,
102                         scrbuf.dwSize.X*scrbuf.dwSize.Y,
103                         origin,
104                         &wrote);
105 }
106 void nt_term_cleanup(void) {
107         CloseHandle(ghstdout);
108 }
109 void nt_term_init() {
110
111         DWORD dwmode;
112         HANDLE hinput =GetStdHandle(STD_INPUT_HANDLE);
113
114         if (!GetConsoleMode(hinput,&dwmode) ){
115                 ;
116         }
117         if(!SetConsoleMode(hinput,dwmode | ENABLE_WINDOW_INPUT) ){
118                 return;
119         }
120
121         redo_console();
122
123         return;
124 }
125 int do_nt_check_cooked_mode(void) {
126
127         return !nt_is_raw;
128 }
129 void do_nt_raw_mode() {
130
131         DWORD dwmode;
132         HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN);
133
134         if (hinput == INVALID_HANDLE_VALUE)
135                 return;
136         if (!GetConsoleMode(hinput,&dwmode) ){
137                 ;
138         }
139         if(!SetConsoleMode(hinput,dwmode & (~(
140                                                 ENABLE_LINE_INPUT |ENABLE_ECHO_INPUT 
141                                                 | ENABLE_PROCESSED_INPUT)| ENABLE_WINDOW_INPUT )
142                                 ) ){
143                 return;
144         }
145         nt_is_raw = 1;
146         return;
147 }
148 void do_nt_cooked_mode() {
149
150         DWORD dwmode;
151         HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN);
152
153         if (hinput == INVALID_HANDLE_VALUE)
154                 return;
155         if (!GetConsoleMode(hinput,&dwmode) ){
156                 ;
157         }
158         if(!SetConsoleMode(hinput,dwmode | ( (
159                                                 ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT |
160                                                 ENABLE_PROCESSED_INPUT) )
161                                 ) ){
162         }
163         nt_is_raw = 0;
164         return;
165 }
166 //
167 // this function is a bit ugly, but I don't know how to do it better
168 // -amol
169 //
170 int nt_ClearEOL( void) {
171
172         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
173         HANDLE hStdout =ghstdout ;
174         DWORD numwrote;
175         char errbuf[128];/*FIXME: uninitialized*/
176         int num=0;
177         COORD savepos;
178
179
180         if (hStdout == INVALID_HANDLE_VALUE){
181                 ExitProcess(0xFFFF);
182         }
183         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
184                 return 0 ;
185         }
186         num =2048;
187
188         savepos = scrbuf.dwCursorPosition;
189         if (!FillConsoleOutputCharacter(hStdout,' ',num,scrbuf.dwCursorPosition,
190                                 &numwrote) ){
191                 dprintf("error from FillCons %s",errbuf);
192         }
193         else if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, num,
194                                 scrbuf.dwCursorPosition,&numwrote)) {
195                 dprintf("error from FillConsAttr %s",errbuf);
196         }
197         return 0;
198 }
199 void nt_move_next_tab(void) {
200
201         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
202         HANDLE hStdout = ghstdout;
203         int where;
204
205         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
206                 ;
207         }
208         where = 8 - (scrbuf.dwCursorPosition.X+1)%8;
209         scrbuf.dwCursorPosition.X += where;
210         if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) {
211                 ;
212         }
213
214 }
215 void NT_VisibleBell(void) {
216
217         if(ghReverse != INVALID_HANDLE_VALUE) {
218                 SetConsoleActiveScreenBuffer(ghReverse);
219                 Sleep(100);
220                 SetConsoleActiveScreenBuffer(ghstdout);
221
222         }
223
224 }
225 void NT_WrapHorizontal(void) {
226         SMALL_RECT wnd;
227         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
228
229
230         if (ghstdout == INVALID_HANDLE_VALUE){
231                 return;
232         }
233         if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) {
234                 return;
235         }
236         //absolute movement
237         wnd.Left =  0;//scrbuf.srWindow.Left ;
238         wnd.Right = scrbuf.srWindow.Right- scrbuf.srWindow.Left + 1;
239         wnd.Top =  scrbuf.srWindow.Top;
240         wnd.Bottom = scrbuf.srWindow.Bottom;
241
242         SetConsoleWindowInfo(ghstdout,TRUE,&wnd);
243 }
244 void ScrollBufHorizontal(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf,
245                 int where) {
246         SMALL_RECT wnd;
247         int diff;
248         CHAR_INFO chr;
249
250
251         //absolute movement
252         wnd.Left = (where - scrbuf->srWindow.Right) + scrbuf->srWindow.Left ;
253         wnd.Right = where;
254         wnd.Top =  scrbuf->srWindow.Top;
255         wnd.Bottom = scrbuf->srWindow.Bottom;
256
257         //diff = scrbuf->srWindow.Right - where;
258         //dprintf("\tdiff1 %d\n",diff);
259
260         diff = scrbuf->dwSize.X - where -1;
261
262         if (diff < 0) { //would scroll past console buffer
263
264                 chr.Char.AsciiChar = ' ';
265                 chr.Attributes = scrbuf->wAttributes;
266
267                 scrbuf->dwCursorPosition.Y  = scrbuf->srWindow.Top ;
268                 scrbuf->dwCursorPosition.X = scrbuf->srWindow.Right+ diff;
269
270                 dprintf("scroll diff %d\n",diff);
271                 if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow),
272                                         NULL,
273                                         scrbuf->dwCursorPosition,&chr)) 
274                         ;
275
276                 return;
277         }
278
279         SetConsoleWindowInfo(hOut,TRUE,&wnd);
280 }
281 // relative movement of "where".  line is 1 if we want to move to a line,
282 // or 0 if the movement is horizontal
283 void NT_MoveToLineOrChar(int where,int line) {
284
285         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
286         HANDLE hStdout = ghstdout;
287
288
289         if (hStdout == INVALID_HANDLE_VALUE){
290                 return;
291         }
292         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
293                 return;
294         }
295
296         if (line){
297                 if ( ((scrbuf.dwCursorPosition.Y+where)> (scrbuf.srWindow.Bottom-1))
298                                 &&( where >0)){
299                         ScrollBuf(hStdout,&scrbuf,where);
300                         scrbuf.dwCursorPosition.Y += where;
301                 }
302                 else
303                         scrbuf.dwCursorPosition.Y += where;
304         }
305         else{
306                 if ( (where> (scrbuf.srWindow.Right)) &&( where >0)){
307                         ScrollBufHorizontal(hStdout,&scrbuf,where);
308                 }
309                 scrbuf.dwCursorPosition.X = where;
310         }
311         if (scrbuf.dwCursorPosition.X < 0 || scrbuf.dwCursorPosition.Y <0)
312                 return;
313         if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) {
314                 return;
315         }
316
317 }
318 void ScrollBuf(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf,int where) {
319         SMALL_RECT wnd;
320         int diff;
321         CHAR_INFO chr;
322         COORD newpos;
323
324
325         wnd.Left = 0;
326         wnd.Right = 0;
327         wnd.Top =  where;
328         wnd.Bottom = where;
329
330         //dwSize is not 0-based, so add 1 to proposed location
331         diff = scrbuf->srWindow.Bottom + where + 1; 
332
333         diff = scrbuf->dwSize.Y - diff;
334
335         if (diff < 0) { //would scroll past console buffer
336
337                 chr.Char.AsciiChar = ' ';
338                 chr.Attributes = scrbuf->wAttributes;
339
340                 newpos.Y  = scrbuf->srWindow.Top + diff;
341                 newpos.X = scrbuf->srWindow.Left;
342
343                 dprintf("scroll diff %d\n",diff);
344                 if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow),
345                                         NULL,
346                                         newpos,&chr)) 
347                         ;
348
349                 // need this to be in sync with tcsh
350                 scrbuf->dwCursorPosition.Y += diff; 
351                 return;
352         }
353
354         SetConsoleWindowInfo(hOut,FALSE,&wnd);
355 }
356 BOOL ConsolePageUpOrDown(BOOL Up) {
357
358         HANDLE hStdout = ghstdout;
359         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
360         SMALL_RECT srect;
361         short diff;
362
363         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
364                 return FALSE;
365         }
366         diff = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ;
367
368
369         if (Up)
370                 diff = -diff;
371
372         if ((scrbuf.srWindow.Top + diff > 0) &&
373                         (scrbuf.srWindow.Bottom + diff < scrbuf.dwSize.Y)) { 
374                 srect.Top = diff;  
375                 srect.Bottom = diff;
376                 srect.Left = 0;    
377                 srect.Right = 0;  
378
379                 if (! SetConsoleWindowInfo( hStdout, FALSE, &srect)) {
380                         return FALSE;
381                 }
382         } 
383
384         return TRUE;
385 }
386 int nt_getsize(int * lins, int * cols, int *visiblecols) {
387         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
388         HANDLE hStdout = ghstdout;
389
390         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
391                 ;
392         }
393         *lins = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ;
394
395         if(visiblecols)
396                 *visiblecols = scrbuf.srWindow.Right -scrbuf.srWindow.Left +1;
397
398         *cols = scrbuf.dwSize.X;
399         return 1;
400 }
401 void nt_set_size(int lins, int cols) {
402         SMALL_RECT srect;
403         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
404         int expand;
405
406         /* The screen buffer visible window is specified as co-ordinates
407          * not size. Therefore, it must be zero-based
408          */
409         cols--;
410         lins--;
411
412         srect.Left = srect.Top = 0;
413         srect.Right = cols;
414         srect.Bottom = lins;
415
416         if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) 
417                 return;
418
419         expand = 0;
420         if (scrbuf.dwSize.X < cols){
421                 expand = 1;
422                 scrbuf.dwSize.X = cols+1;
423         }
424         if (scrbuf.dwSize.Y < lins){
425                 expand = 1;
426                 scrbuf.dwSize.Y = lins+1;
427         }
428
429         if (expand && !SetConsoleScreenBufferSize(ghstdout,scrbuf.dwSize))
430                 return;
431
432         if(!SetConsoleWindowInfo(ghstdout,TRUE,&srect)){
433                 int err;
434                 err=GetLastError();
435                 dprintf("error %d\n",err);
436         }
437 }
438 void NT_ClearEOD(void) {
439         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
440         DWORD numwrote;
441         COORD origin;
442         int ht,wt;
443         HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE);
444
445         if (hStdout == INVALID_HANDLE_VALUE){
446                 return ;
447         }
448         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
449                 return ;
450         }
451         origin = scrbuf.dwCursorPosition;
452         ht = scrbuf.dwSize.Y - origin.Y;
453         wt = scrbuf.dwSize.X - origin.X;
454         if(!FillConsoleOutputCharacter(hStdout,' ',ht*wt,origin,&numwrote) ) {
455                 return ;
456         }
457         if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, ht*wt,
458                                 scrbuf.dwCursorPosition,&numwrote)) {
459                 return;
460         }
461         return;
462 }
463 void NT_ClearScreen(void) {
464         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
465         DWORD numwrote;
466         COORD origin={0,0};
467         HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE);
468
469         if (hStdout == INVALID_HANDLE_VALUE){
470                 ;
471         }
472         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
473                 ;
474         }
475         origin.X = scrbuf.srWindow.Left;
476         origin.Y = scrbuf.srWindow.Top;
477         if(!FillConsoleOutputCharacter(hStdout,' ',scrbuf.dwSize.X*scrbuf.dwSize.Y,
478                                 origin,&numwrote) ) {
479                 ;
480         }
481         if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes,
482                                 scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) {
483                 ;
484         }
485         if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor
486                 ;
487         }
488         return;
489 }
490 void NT_ClearScreen_WholeBuffer(void) {
491         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
492         DWORD numwrote;
493         COORD origin={0,0};
494         HANDLE hStdout = ghstdout;
495
496         if (hStdout == INVALID_HANDLE_VALUE){
497                 ;
498         }
499         if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
500                 ;
501         }
502         if(!FillConsoleOutputCharacter(hStdout,' ',scrbuf.dwSize.X*scrbuf.dwSize.Y,
503                                 origin,&numwrote) ) {
504                 ;
505         }
506         if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes,
507                                 scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) {
508                 ;
509         }
510         if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor
511                 ;
512         }
513         return;
514 }
515
516 #ifndef COLOR_LS_F
517 void set_cons_attr(char *attr2) {
518         char cp[3];
519         USHORT attr;
520         HANDLE outhandle = (HANDLE)_get_osfhandle(FSHOUT);
521         static WORD old_attribs;
522         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
523
524         if (!old_attribs) {
525                 if(!GetConsoleScreenBufferInfo(outhandle, &scrbuf) ) {
526                         return;
527                 }
528                 old_attribs = scrbuf.wAttributes;
529         }
530         cp[0] = (unsigned char)(attr2[0]);
531         cp[1] = (unsigned char)(attr2[1]);
532         cp[2] = 0;
533         if (cp[0] != 'g' || cp[1] != 'g')
534                 attr = (USHORT)strtol(cp,NULL,16);
535         else{
536                 attr = old_attribs;
537                 old_attribs=0;
538         }
539
540         SetConsoleTextAttribute(outhandle, attr );
541 }
542 #endif /* !COLOR_LS_F */
543
544
545 /*
546    color escape sequences (ISO 6429, aixterm)
547    - nayuta
548  */
549
550
551 WORD get_attributes() {
552         CONSOLE_SCREEN_BUFFER_INFO scrbuf;
553         if (!GetConsoleScreenBufferInfo(ghstdout, &scrbuf))
554                 return 0x70; // ERROR: return white background, black text
555         return scrbuf.wAttributes;
556 }
557
558
559 #ifndef COMMON_LVB_REVERSE_VIDEO
560 #define COMMON_LVB_REVERSE_VIDEO   0x4000
561 #define COMMON_LVB_UNDERSCORE      0x8000
562 #endif
563
564
565 void set_attributes(const unsigned char *color) {
566
567         static const int colors[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
568         WORD wAttributes;
569         const char *t;
570
571         if (color[0] == '\x1b' && color[1] == '[')
572                 color += 2;
573
574         if (!('0' <= color[0] && color[0] <= '9')) {
575                 SetConsoleTextAttribute(ghstdout, wNormalAttributes);
576                 return;
577         }
578
579         wAttributes = get_attributes();
580         t = (char*)color;
581
582         while (t) {
583                 int n = atoi(t);
584
585                 if ((t = strchr(t, ';')) != NULL)
586                         t++;
587
588                 if      (n == 0)                                // Normal (default)
589                         wAttributes = wNormalAttributes;
590                 else if (n == 1)                                // Bold
591                         wAttributes |= FOREGROUND_INTENSITY;
592                 else if (n == 4)                                // Underlined
593                         wAttributes |= COMMON_LVB_UNDERSCORE;
594                 else if (n == 5)                                // Blink (appears as BACKGROUND_INTENSITY)
595                         wAttributes |= BACKGROUND_INTENSITY;
596                 else if (n == 7)                                // Inverse
597                         wAttributes |= COMMON_LVB_REVERSE_VIDEO;
598                 else if (n == 21)                               // Not bold
599                         wAttributes &= ~FOREGROUND_INTENSITY;
600                 else if (n == 24)                               // Not underlined
601                         wAttributes &= ~COMMON_LVB_UNDERSCORE;
602                 else if (n == 25)                               // Steady (not blinking)
603                         wAttributes &= ~BACKGROUND_INTENSITY;
604                 else if (n == 27)                               // Positive (not inverse)
605                         wAttributes &= ~COMMON_LVB_REVERSE_VIDEO;
606                 else if (30 <= n && n <= 37)    // Set foreground color
607                         wAttributes = (wAttributes & ~0x0007) | colors[n - 30];
608                 else if (n == 39)                               // Set foreground color to default
609                         wAttributes = (wAttributes & ~0x0007) | (wNormalAttributes & 0x0007);
610                 else if (40 <= n && n <= 47)    // Set background color
611                         wAttributes = (wAttributes & ~0x0070) | (colors[n - 40] << 4);
612                 else if (n == 49)                               // Set background color to default
613                         wAttributes = (wAttributes & ~0x0070) | (wNormalAttributes & 0x0070);
614                 else if (90 <= n && n <= 97)    // Set foreground color (bright)
615                         wAttributes = (wAttributes & ~0x0007) | colors[n - 90]
616                                 | FOREGROUND_INTENSITY;
617                 else if (100 <= n && n <= 107)  // Set background color (bright)
618                         wAttributes = (wAttributes & ~0x0070) | (colors[n - 100] << 4)
619                                 | BACKGROUND_INTENSITY;
620                 else                                                    // (default)
621                         wAttributes = wNormalAttributes;
622         }
623
624         // Though Windows' console supports COMMON_LVB_REVERSE_VIDEO,
625         // it seems to be buggy.  So we must simulate it.
626         if (wAttributes & COMMON_LVB_REVERSE_VIDEO)
627                 wAttributes = (wAttributes & COMMON_LVB_UNDERSCORE)
628                         | ((wAttributes & 0x00f0) >> 4) | ((wAttributes & 0x000f) << 4);
629         SetConsoleTextAttribute(ghstdout, wAttributes);
630 }
631 void StartHighlight(void)
632 {
633 }
634 void StopHighlight(void)
635 {
636 }