1 /*$Header: /p/tcsh/cvsroot/tcsh/win32/console.c,v 1.9 2006/08/27 01:13:28 amold Exp $*/
3 * Copyright (c) 1980, 1991 The Regents of the University of California.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
32 * console.c: hacks to do various cursor movement/attribute things
35 #define WIN32_LEAN_AND_MEAN
42 // int to SHORT. caused by all the stupid functions that take WORDs
43 #pragma warning(disable:4244)
45 void ScrollBuf(HANDLE,CONSOLE_SCREEN_BUFFER_INFO*,int);
46 void NT_MoveToLineOrChar(int ,int ) ;
47 WORD get_attributes();
50 #define FSHIN 16 /* Preferred desc for shell input */
51 #define FSHOUT 17 /* Preferred desc for shell input */
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
58 static WORD wNormalAttributes;
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
71 // This function is called to set the values for above variables.
73 void redo_console(void) {
75 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
76 HANDLE hTemp= GetStdHandle(STD_OUTPUT_HANDLE);
81 if (!DuplicateHandle(GetCurrentProcess(),hTemp,GetCurrentProcess(),
82 &ghstdout,0,TRUE,DUPLICATE_SAME_ACCESS) ) {
86 if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) {
87 wNormalAttributes = FOREGROUND_BLACK | BACKGROUND_WHITE;
90 wNormalAttributes = scrbuf.wAttributes;
92 ghReverse = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,
93 FILE_SHARE_READ | FILE_SHARE_WRITE,
95 CONSOLE_TEXTMODE_BUFFER,
98 dbga = ((wNormalAttributes & 0x00f0) >> 4) |
99 ((wNormalAttributes & 0x000f) << 4) ;
101 FillConsoleOutputAttribute(ghReverse,dbga,
102 scrbuf.dwSize.X*scrbuf.dwSize.Y,
106 void nt_term_cleanup(void) {
107 CloseHandle(ghstdout);
109 void nt_term_init() {
112 HANDLE hinput =GetStdHandle(STD_INPUT_HANDLE);
114 if (!GetConsoleMode(hinput,&dwmode) ){
117 if(!SetConsoleMode(hinput,dwmode | ENABLE_WINDOW_INPUT) ){
125 int do_nt_check_cooked_mode(void) {
129 void do_nt_raw_mode() {
132 HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN);
134 if (hinput == INVALID_HANDLE_VALUE)
136 if (!GetConsoleMode(hinput,&dwmode) ){
139 if(!SetConsoleMode(hinput,dwmode & (~(
140 ENABLE_LINE_INPUT |ENABLE_ECHO_INPUT
141 | ENABLE_PROCESSED_INPUT)| ENABLE_WINDOW_INPUT )
148 void do_nt_cooked_mode() {
151 HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN);
153 if (hinput == INVALID_HANDLE_VALUE)
155 if (!GetConsoleMode(hinput,&dwmode) ){
158 if(!SetConsoleMode(hinput,dwmode | ( (
159 ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT |
160 ENABLE_PROCESSED_INPUT) )
167 // this function is a bit ugly, but I don't know how to do it better
170 int nt_ClearEOL( void) {
172 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
173 HANDLE hStdout =ghstdout ;
175 char errbuf[128];/*FIXME: uninitialized*/
180 if (hStdout == INVALID_HANDLE_VALUE){
183 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
188 savepos = scrbuf.dwCursorPosition;
189 if (!FillConsoleOutputCharacter(hStdout,' ',num,scrbuf.dwCursorPosition,
191 dprintf("error from FillCons %s",errbuf);
193 else if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, num,
194 scrbuf.dwCursorPosition,&numwrote)) {
195 dprintf("error from FillConsAttr %s",errbuf);
199 void nt_move_next_tab(void) {
201 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
202 HANDLE hStdout = ghstdout;
205 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
208 where = 8 - (scrbuf.dwCursorPosition.X+1)%8;
209 scrbuf.dwCursorPosition.X += where;
210 if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) {
215 void NT_VisibleBell(void) {
217 if(ghReverse != INVALID_HANDLE_VALUE) {
218 SetConsoleActiveScreenBuffer(ghReverse);
220 SetConsoleActiveScreenBuffer(ghstdout);
225 void NT_WrapHorizontal(void) {
227 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
230 if (ghstdout == INVALID_HANDLE_VALUE){
233 if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) {
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;
242 SetConsoleWindowInfo(ghstdout,TRUE,&wnd);
244 void ScrollBufHorizontal(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf,
252 wnd.Left = (where - scrbuf->srWindow.Right) + scrbuf->srWindow.Left ;
254 wnd.Top = scrbuf->srWindow.Top;
255 wnd.Bottom = scrbuf->srWindow.Bottom;
257 //diff = scrbuf->srWindow.Right - where;
258 //dprintf("\tdiff1 %d\n",diff);
260 diff = scrbuf->dwSize.X - where -1;
262 if (diff < 0) { //would scroll past console buffer
264 chr.Char.AsciiChar = ' ';
265 chr.Attributes = scrbuf->wAttributes;
267 scrbuf->dwCursorPosition.Y = scrbuf->srWindow.Top ;
268 scrbuf->dwCursorPosition.X = scrbuf->srWindow.Right+ diff;
270 dprintf("scroll diff %d\n",diff);
271 if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow),
273 scrbuf->dwCursorPosition,&chr))
279 SetConsoleWindowInfo(hOut,TRUE,&wnd);
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) {
285 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
286 HANDLE hStdout = ghstdout;
289 if (hStdout == INVALID_HANDLE_VALUE){
292 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
297 if ( ((scrbuf.dwCursorPosition.Y+where)> (scrbuf.srWindow.Bottom-1))
299 ScrollBuf(hStdout,&scrbuf,where);
300 scrbuf.dwCursorPosition.Y += where;
303 scrbuf.dwCursorPosition.Y += where;
306 if ( (where> (scrbuf.srWindow.Right)) &&( where >0)){
307 ScrollBufHorizontal(hStdout,&scrbuf,where);
309 scrbuf.dwCursorPosition.X = where;
311 if (scrbuf.dwCursorPosition.X < 0 || scrbuf.dwCursorPosition.Y <0)
313 if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) {
318 void ScrollBuf(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf,int where) {
330 //dwSize is not 0-based, so add 1 to proposed location
331 diff = scrbuf->srWindow.Bottom + where + 1;
333 diff = scrbuf->dwSize.Y - diff;
335 if (diff < 0) { //would scroll past console buffer
337 chr.Char.AsciiChar = ' ';
338 chr.Attributes = scrbuf->wAttributes;
340 newpos.Y = scrbuf->srWindow.Top + diff;
341 newpos.X = scrbuf->srWindow.Left;
343 dprintf("scroll diff %d\n",diff);
344 if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow),
349 // need this to be in sync with tcsh
350 scrbuf->dwCursorPosition.Y += diff;
354 SetConsoleWindowInfo(hOut,FALSE,&wnd);
356 BOOL ConsolePageUpOrDown(BOOL Up) {
358 HANDLE hStdout = ghstdout;
359 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
363 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
366 diff = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ;
372 if ((scrbuf.srWindow.Top + diff > 0) &&
373 (scrbuf.srWindow.Bottom + diff < scrbuf.dwSize.Y)) {
379 if (! SetConsoleWindowInfo( hStdout, FALSE, &srect)) {
386 int nt_getsize(int * lins, int * cols, int *visiblecols) {
387 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
388 HANDLE hStdout = ghstdout;
390 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
393 *lins = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ;
396 *visiblecols = scrbuf.srWindow.Right -scrbuf.srWindow.Left +1;
398 *cols = scrbuf.dwSize.X;
401 void nt_set_size(int lins, int cols) {
403 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
406 /* The screen buffer visible window is specified as co-ordinates
407 * not size. Therefore, it must be zero-based
412 srect.Left = srect.Top = 0;
416 if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) )
420 if (scrbuf.dwSize.X < cols){
422 scrbuf.dwSize.X = cols+1;
424 if (scrbuf.dwSize.Y < lins){
426 scrbuf.dwSize.Y = lins+1;
429 if (expand && !SetConsoleScreenBufferSize(ghstdout,scrbuf.dwSize))
432 if(!SetConsoleWindowInfo(ghstdout,TRUE,&srect)){
435 dprintf("error %d\n",err);
438 void NT_ClearEOD(void) {
439 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
443 HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE);
445 if (hStdout == INVALID_HANDLE_VALUE){
448 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
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) ) {
457 if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, ht*wt,
458 scrbuf.dwCursorPosition,&numwrote)) {
463 void NT_ClearScreen(void) {
464 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
467 HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE);
469 if (hStdout == INVALID_HANDLE_VALUE){
472 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
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) ) {
481 if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes,
482 scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) {
485 if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor
490 void NT_ClearScreen_WholeBuffer(void) {
491 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
494 HANDLE hStdout = ghstdout;
496 if (hStdout == INVALID_HANDLE_VALUE){
499 if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) {
502 if(!FillConsoleOutputCharacter(hStdout,' ',scrbuf.dwSize.X*scrbuf.dwSize.Y,
503 origin,&numwrote) ) {
506 if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes,
507 scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) {
510 if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor
517 void set_cons_attr(char *attr2) {
520 HANDLE outhandle = (HANDLE)_get_osfhandle(FSHOUT);
521 static WORD old_attribs;
522 CONSOLE_SCREEN_BUFFER_INFO scrbuf;
525 if(!GetConsoleScreenBufferInfo(outhandle, &scrbuf) ) {
528 old_attribs = scrbuf.wAttributes;
530 cp[0] = (unsigned char)(attr2[0]);
531 cp[1] = (unsigned char)(attr2[1]);
533 if (cp[0] != 'g' || cp[1] != 'g')
534 attr = (USHORT)strtol(cp,NULL,16);
540 SetConsoleTextAttribute(outhandle, attr );
542 #endif /* !COLOR_LS_F */
546 color escape sequences (ISO 6429, aixterm)
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;
559 #ifndef COMMON_LVB_REVERSE_VIDEO
560 #define COMMON_LVB_REVERSE_VIDEO 0x4000
561 #define COMMON_LVB_UNDERSCORE 0x8000
565 void set_attributes(const unsigned char *color) {
567 static const int colors[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
571 if (color[0] == '\x1b' && color[1] == '[')
574 if (!('0' <= color[0] && color[0] <= '9')) {
575 SetConsoleTextAttribute(ghstdout, wNormalAttributes);
579 wAttributes = get_attributes();
585 if ((t = strchr(t, ';')) != NULL)
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;
621 wAttributes = wNormalAttributes;
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);
631 void StartHighlight(void)
634 void StopHighlight(void)