summaryrefslogtreecommitdiff
path: root/win32/console.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/console.c')
-rw-r--r--win32/console.c636
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)
+{
+}