diff options
Diffstat (limited to 'win32/console.c')
-rw-r--r-- | win32/console.c | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/win32/console.c b/win32/console.c new file mode 100644 index 0000000000000..220d56eaea947 --- /dev/null +++ b/win32/console.c @@ -0,0 +1,636 @@ +/*$Header: /p/tcsh/cvsroot/tcsh/win32/console.c,v 1.9 2006/08/27 01:13:28 amold Exp $*/ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * console.c: hacks to do various cursor movement/attribute things + * -amol + */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <wincon.h> +#include <stdio.h> +#include "ntport.h" + + +// int to SHORT. caused by all the stupid functions that take WORDs +#pragma warning(disable:4244) + +void ScrollBuf(HANDLE,CONSOLE_SCREEN_BUFFER_INFO*,int); +void NT_MoveToLineOrChar(int ,int ) ; +WORD get_attributes(); + + +#define FSHIN 16 /* Preferred desc for shell input */ +#define FSHOUT 17 /* Preferred desc for shell input */ + +#define FOREGROUND_BLACK (FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FOREGROUND_WHITE 0 +#define BACKGROUND_BLACK (BACKGROUND_RED |BACKGROUND_GREEN | BACKGROUND_BLUE) +#define BACKGROUND_WHITE 0 + +static WORD wNormalAttributes; + + +static int nt_is_raw; +// +// The following are used to optimize some console routines. It avoids having +// to call GetConsoleScreenBufferInfo. +// Seems to have helped the speed a bit. -amol +// +HANDLE ghstdout; +HANDLE ghReverse; + +// +// This function is called to set the values for above variables. +// +void redo_console(void) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hTemp= GetStdHandle(STD_OUTPUT_HANDLE); + WORD dbga; + DWORD wrote; + COORD origin = {0,0}; + + if (!DuplicateHandle(GetCurrentProcess(),hTemp,GetCurrentProcess(), + &ghstdout,0,TRUE,DUPLICATE_SAME_ACCESS) ) { + ; + } + + if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) { + wNormalAttributes = FOREGROUND_BLACK | BACKGROUND_WHITE; + } + else + wNormalAttributes = scrbuf.wAttributes; + + ghReverse = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CONSOLE_TEXTMODE_BUFFER, + NULL); + + dbga = ((wNormalAttributes & 0x00f0) >> 4) | + ((wNormalAttributes & 0x000f) << 4) ; + + FillConsoleOutputAttribute(ghReverse,dbga, + scrbuf.dwSize.X*scrbuf.dwSize.Y, + origin, + &wrote); +} +void nt_term_cleanup(void) { + CloseHandle(ghstdout); +} +void nt_term_init() { + + DWORD dwmode; + HANDLE hinput =GetStdHandle(STD_INPUT_HANDLE); + + if (!GetConsoleMode(hinput,&dwmode) ){ + ; + } + if(!SetConsoleMode(hinput,dwmode | ENABLE_WINDOW_INPUT) ){ + return; + } + + redo_console(); + + return; +} +int do_nt_check_cooked_mode(void) { + + return !nt_is_raw; +} +void do_nt_raw_mode() { + + DWORD dwmode; + HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN); + + if (hinput == INVALID_HANDLE_VALUE) + return; + if (!GetConsoleMode(hinput,&dwmode) ){ + ; + } + if(!SetConsoleMode(hinput,dwmode & (~( + ENABLE_LINE_INPUT |ENABLE_ECHO_INPUT + | ENABLE_PROCESSED_INPUT)| ENABLE_WINDOW_INPUT ) + ) ){ + return; + } + nt_is_raw = 1; + return; +} +void do_nt_cooked_mode() { + + DWORD dwmode; + HANDLE hinput =(HANDLE)_get_osfhandle(FSHIN); + + if (hinput == INVALID_HANDLE_VALUE) + return; + if (!GetConsoleMode(hinput,&dwmode) ){ + ; + } + if(!SetConsoleMode(hinput,dwmode | ( ( + ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT | + ENABLE_PROCESSED_INPUT) ) + ) ){ + } + nt_is_raw = 0; + return; +} +// +// this function is a bit ugly, but I don't know how to do it better +// -amol +// +int nt_ClearEOL( void) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout =ghstdout ; + DWORD numwrote; + char errbuf[128];/*FIXME: uninitialized*/ + int num=0; + COORD savepos; + + + if (hStdout == INVALID_HANDLE_VALUE){ + ExitProcess(0xFFFF); + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return 0 ; + } + num =2048; + + savepos = scrbuf.dwCursorPosition; + if (!FillConsoleOutputCharacter(hStdout,' ',num,scrbuf.dwCursorPosition, + &numwrote) ){ + dprintf("error from FillCons %s",errbuf); + } + else if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, num, + scrbuf.dwCursorPosition,&numwrote)) { + dprintf("error from FillConsAttr %s",errbuf); + } + return 0; +} +void nt_move_next_tab(void) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout = ghstdout; + int where; + + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + where = 8 - (scrbuf.dwCursorPosition.X+1)%8; + scrbuf.dwCursorPosition.X += where; + if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) { + ; + } + +} +void NT_VisibleBell(void) { + + if(ghReverse != INVALID_HANDLE_VALUE) { + SetConsoleActiveScreenBuffer(ghReverse); + Sleep(100); + SetConsoleActiveScreenBuffer(ghstdout); + + } + +} +void NT_WrapHorizontal(void) { + SMALL_RECT wnd; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + + + if (ghstdout == INVALID_HANDLE_VALUE){ + return; + } + if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) { + return; + } + //absolute movement + wnd.Left = 0;//scrbuf.srWindow.Left ; + wnd.Right = scrbuf.srWindow.Right- scrbuf.srWindow.Left + 1; + wnd.Top = scrbuf.srWindow.Top; + wnd.Bottom = scrbuf.srWindow.Bottom; + + SetConsoleWindowInfo(ghstdout,TRUE,&wnd); +} +void ScrollBufHorizontal(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf, + int where) { + SMALL_RECT wnd; + int diff; + CHAR_INFO chr; + + + //absolute movement + wnd.Left = (where - scrbuf->srWindow.Right) + scrbuf->srWindow.Left ; + wnd.Right = where; + wnd.Top = scrbuf->srWindow.Top; + wnd.Bottom = scrbuf->srWindow.Bottom; + + //diff = scrbuf->srWindow.Right - where; + //dprintf("\tdiff1 %d\n",diff); + + diff = scrbuf->dwSize.X - where -1; + + if (diff < 0) { //would scroll past console buffer + + chr.Char.AsciiChar = ' '; + chr.Attributes = scrbuf->wAttributes; + + scrbuf->dwCursorPosition.Y = scrbuf->srWindow.Top ; + scrbuf->dwCursorPosition.X = scrbuf->srWindow.Right+ diff; + + dprintf("scroll diff %d\n",diff); + if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow), + NULL, + scrbuf->dwCursorPosition,&chr)) + ; + + return; + } + + SetConsoleWindowInfo(hOut,TRUE,&wnd); +} +// relative movement of "where". line is 1 if we want to move to a line, +// or 0 if the movement is horizontal +void NT_MoveToLineOrChar(int where,int line) { + + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout = ghstdout; + + + if (hStdout == INVALID_HANDLE_VALUE){ + return; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return; + } + + if (line){ + if ( ((scrbuf.dwCursorPosition.Y+where)> (scrbuf.srWindow.Bottom-1)) + &&( where >0)){ + ScrollBuf(hStdout,&scrbuf,where); + scrbuf.dwCursorPosition.Y += where; + } + else + scrbuf.dwCursorPosition.Y += where; + } + else{ + if ( (where> (scrbuf.srWindow.Right)) &&( where >0)){ + ScrollBufHorizontal(hStdout,&scrbuf,where); + } + scrbuf.dwCursorPosition.X = where; + } + if (scrbuf.dwCursorPosition.X < 0 || scrbuf.dwCursorPosition.Y <0) + return; + if (!SetConsoleCursorPosition(hStdout, scrbuf.dwCursorPosition) ) { + return; + } + +} +void ScrollBuf(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFO *scrbuf,int where) { + SMALL_RECT wnd; + int diff; + CHAR_INFO chr; + COORD newpos; + + + wnd.Left = 0; + wnd.Right = 0; + wnd.Top = where; + wnd.Bottom = where; + + //dwSize is not 0-based, so add 1 to proposed location + diff = scrbuf->srWindow.Bottom + where + 1; + + diff = scrbuf->dwSize.Y - diff; + + if (diff < 0) { //would scroll past console buffer + + chr.Char.AsciiChar = ' '; + chr.Attributes = scrbuf->wAttributes; + + newpos.Y = scrbuf->srWindow.Top + diff; + newpos.X = scrbuf->srWindow.Left; + + dprintf("scroll diff %d\n",diff); + if (!ScrollConsoleScreenBuffer(hOut,&(scrbuf->srWindow), + NULL, + newpos,&chr)) + ; + + // need this to be in sync with tcsh + scrbuf->dwCursorPosition.Y += diff; + return; + } + + SetConsoleWindowInfo(hOut,FALSE,&wnd); +} +BOOL ConsolePageUpOrDown(BOOL Up) { + + HANDLE hStdout = ghstdout; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + SMALL_RECT srect; + short diff; + + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return FALSE; + } + diff = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ; + + + if (Up) + diff = -diff; + + if ((scrbuf.srWindow.Top + diff > 0) && + (scrbuf.srWindow.Bottom + diff < scrbuf.dwSize.Y)) { + srect.Top = diff; + srect.Bottom = diff; + srect.Left = 0; + srect.Right = 0; + + if (! SetConsoleWindowInfo( hStdout, FALSE, &srect)) { + return FALSE; + } + } + + return TRUE; +} +int nt_getsize(int * lins, int * cols, int *visiblecols) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + HANDLE hStdout = ghstdout; + + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + *lins = scrbuf.srWindow.Bottom -scrbuf.srWindow.Top+1 ; + + if(visiblecols) + *visiblecols = scrbuf.srWindow.Right -scrbuf.srWindow.Left +1; + + *cols = scrbuf.dwSize.X; + return 1; +} +void nt_set_size(int lins, int cols) { + SMALL_RECT srect; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + int expand; + + /* The screen buffer visible window is specified as co-ordinates + * not size. Therefore, it must be zero-based + */ + cols--; + lins--; + + srect.Left = srect.Top = 0; + srect.Right = cols; + srect.Bottom = lins; + + if(!GetConsoleScreenBufferInfo(ghstdout, &scrbuf) ) + return; + + expand = 0; + if (scrbuf.dwSize.X < cols){ + expand = 1; + scrbuf.dwSize.X = cols+1; + } + if (scrbuf.dwSize.Y < lins){ + expand = 1; + scrbuf.dwSize.Y = lins+1; + } + + if (expand && !SetConsoleScreenBufferSize(ghstdout,scrbuf.dwSize)) + return; + + if(!SetConsoleWindowInfo(ghstdout,TRUE,&srect)){ + int err; + err=GetLastError(); + dprintf("error %d\n",err); + } +} +void NT_ClearEOD(void) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + DWORD numwrote; + COORD origin; + int ht,wt; + HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE); + + if (hStdout == INVALID_HANDLE_VALUE){ + return ; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + return ; + } + origin = scrbuf.dwCursorPosition; + ht = scrbuf.dwSize.Y - origin.Y; + wt = scrbuf.dwSize.X - origin.X; + if(!FillConsoleOutputCharacter(hStdout,' ',ht*wt,origin,&numwrote) ) { + return ; + } + if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, ht*wt, + scrbuf.dwCursorPosition,&numwrote)) { + return; + } + return; +} +void NT_ClearScreen(void) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + DWORD numwrote; + COORD origin={0,0}; + HANDLE hStdout = ghstdout;//GetStdHandle(STD_OUTPUT_HANDLE); + + if (hStdout == INVALID_HANDLE_VALUE){ + ; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + origin.X = scrbuf.srWindow.Left; + origin.Y = scrbuf.srWindow.Top; + if(!FillConsoleOutputCharacter(hStdout,' ',scrbuf.dwSize.X*scrbuf.dwSize.Y, + origin,&numwrote) ) { + ; + } + if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, + scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) { + ; + } + if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor + ; + } + return; +} +void NT_ClearScreen_WholeBuffer(void) { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + DWORD numwrote; + COORD origin={0,0}; + HANDLE hStdout = ghstdout; + + if (hStdout == INVALID_HANDLE_VALUE){ + ; + } + if(!GetConsoleScreenBufferInfo(hStdout, &scrbuf) ) { + ; + } + if(!FillConsoleOutputCharacter(hStdout,' ',scrbuf.dwSize.X*scrbuf.dwSize.Y, + origin,&numwrote) ) { + ; + } + if (!FillConsoleOutputAttribute(hStdout,scrbuf.wAttributes, + scrbuf.dwSize.X*scrbuf.dwSize.Y,origin,&numwrote)) { + ; + } + if (!SetConsoleCursorPosition(hStdout, origin) ) { // home cursor + ; + } + return; +} + +#ifndef COLOR_LS_F +void set_cons_attr(char *attr2) { + char cp[3]; + USHORT attr; + HANDLE outhandle = (HANDLE)_get_osfhandle(FSHOUT); + static WORD old_attribs; + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + + if (!old_attribs) { + if(!GetConsoleScreenBufferInfo(outhandle, &scrbuf) ) { + return; + } + old_attribs = scrbuf.wAttributes; + } + cp[0] = (unsigned char)(attr2[0]); + cp[1] = (unsigned char)(attr2[1]); + cp[2] = 0; + if (cp[0] != 'g' || cp[1] != 'g') + attr = (USHORT)strtol(cp,NULL,16); + else{ + attr = old_attribs; + old_attribs=0; + } + + SetConsoleTextAttribute(outhandle, attr ); +} +#endif /* !COLOR_LS_F */ + + +/* + color escape sequences (ISO 6429, aixterm) + - nayuta + */ + + +WORD get_attributes() { + CONSOLE_SCREEN_BUFFER_INFO scrbuf; + if (!GetConsoleScreenBufferInfo(ghstdout, &scrbuf)) + return 0x70; // ERROR: return white background, black text + return scrbuf.wAttributes; +} + + +#ifndef COMMON_LVB_REVERSE_VIDEO +#define COMMON_LVB_REVERSE_VIDEO 0x4000 +#define COMMON_LVB_UNDERSCORE 0x8000 +#endif + + +void set_attributes(const unsigned char *color) { + + static const int colors[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + WORD wAttributes; + const char *t; + + if (color[0] == '\x1b' && color[1] == '[') + color += 2; + + if (!('0' <= color[0] && color[0] <= '9')) { + SetConsoleTextAttribute(ghstdout, wNormalAttributes); + return; + } + + wAttributes = get_attributes(); + t = (char*)color; + + while (t) { + int n = atoi(t); + + if ((t = strchr(t, ';')) != NULL) + t++; + + if (n == 0) // Normal (default) + wAttributes = wNormalAttributes; + else if (n == 1) // Bold + wAttributes |= FOREGROUND_INTENSITY; + else if (n == 4) // Underlined + wAttributes |= COMMON_LVB_UNDERSCORE; + else if (n == 5) // Blink (appears as BACKGROUND_INTENSITY) + wAttributes |= BACKGROUND_INTENSITY; + else if (n == 7) // Inverse + wAttributes |= COMMON_LVB_REVERSE_VIDEO; + else if (n == 21) // Not bold + wAttributes &= ~FOREGROUND_INTENSITY; + else if (n == 24) // Not underlined + wAttributes &= ~COMMON_LVB_UNDERSCORE; + else if (n == 25) // Steady (not blinking) + wAttributes &= ~BACKGROUND_INTENSITY; + else if (n == 27) // Positive (not inverse) + wAttributes &= ~COMMON_LVB_REVERSE_VIDEO; + else if (30 <= n && n <= 37) // Set foreground color + wAttributes = (wAttributes & ~0x0007) | colors[n - 30]; + else if (n == 39) // Set foreground color to default + wAttributes = (wAttributes & ~0x0007) | (wNormalAttributes & 0x0007); + else if (40 <= n && n <= 47) // Set background color + wAttributes = (wAttributes & ~0x0070) | (colors[n - 40] << 4); + else if (n == 49) // Set background color to default + wAttributes = (wAttributes & ~0x0070) | (wNormalAttributes & 0x0070); + else if (90 <= n && n <= 97) // Set foreground color (bright) + wAttributes = (wAttributes & ~0x0007) | colors[n - 90] + | FOREGROUND_INTENSITY; + else if (100 <= n && n <= 107) // Set background color (bright) + wAttributes = (wAttributes & ~0x0070) | (colors[n - 100] << 4) + | BACKGROUND_INTENSITY; + else // (default) + wAttributes = wNormalAttributes; + } + + // Though Windows' console supports COMMON_LVB_REVERSE_VIDEO, + // it seems to be buggy. So we must simulate it. + if (wAttributes & COMMON_LVB_REVERSE_VIDEO) + wAttributes = (wAttributes & COMMON_LVB_UNDERSCORE) + | ((wAttributes & 0x00f0) >> 4) | ((wAttributes & 0x000f) << 4); + SetConsoleTextAttribute(ghstdout, wAttributes); +} +void StartHighlight(void) +{ +} +void StopHighlight(void) +{ +} |