diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index 71c9e7a7e..cff5e2d59 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -204,6 +204,8 @@ + + diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index eefef7c86..77a05a3d6 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -139,6 +139,8 @@ inc + + diff --git a/contrib/win32/win32compat/ansiprsr.c b/contrib/win32/win32compat/ansiprsr.c index f2e99bc66..e5344e8c1 100644 --- a/contrib/win32/win32compat/ansiprsr.c +++ b/contrib/win32/win32compat/ansiprsr.c @@ -48,14 +48,12 @@ extern int ScreenX; extern int ScreenY; extern int ScrollTop; extern int ScrollBottom; -extern BOOL bAnsiParsing; bool gbVTAppMode = false; /* private message for port printing to */ unsigned char VT_ST[] = { 0x1b, '/', '\0' }; static int AutoWrap = 1; BOOL bAtEOLN = FALSE; -static int term_mode = TERM_ANSI; /* * ParseANSI globals - these need to be here, because sometimes blocks are sent @@ -142,12 +140,24 @@ BufConvertToG2(char * pszBuffer, int length) void GoToNextLine() { - if (ConGetCursorY() >= (ConWindowSizeY() - 1)) { - ConScrollDown(ScrollTop, ScrollBottom); - ConMoveCursorPosition(-ConGetCursorX(), 0); - } - else - ConMoveCursorPosition(-ConGetCursorX(), 1); + int currentX = 0; + int currentY = 0; + + ConGetCursorPosition(¤tX, ¤tY); + + /* If the cursor is the last line of the visible window */ + if (is_cursor_at_lastline_of_visible_window()) { + if (currentY >= ConGetBufferHeight()) { + /* handle the max window buffer size */ + ConScrollDown(0, currentY); + ConMoveCursorPosition(-currentX, 0); + } else { + /* max window buffer is not breached */ + ConMoveVisibleWindow(1); + ConMoveCursorPosition(-currentX, 1); + } + } else /* If the cursor is NOT the last line of the visible window */ + ConMoveCursorPosition(-currentX, 1); bAtEOLN = FALSE; } @@ -155,8 +165,8 @@ GoToNextLine() unsigned char* ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char **respbuf, size_t *resplen) { - int CurrentX; - int CurrentY; + int currentX; + int currentY; int bufLen, cmpLen, i; if (!fcompletion) { @@ -164,8 +174,7 @@ ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char unsigned char * pszCurrent = pszBuffer + 1; unsigned char * pszNewCurrent = pszCurrent; - if (term_mode == TERM_ANSI && bAnsiParsing) - pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd, respbuf, resplen); + pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd, respbuf, resplen); /* Pointer didn't move inside Parse function */ if (pszCurrent == pszNewCurrent) { @@ -200,8 +209,8 @@ ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char case 8: pszBuffer++; if (!bAtEOLN) { - CurrentX = ConGetCursorX(); - if (CurrentX == 0) { + currentX = ConGetCursorX(); + if (currentX == 0) { ConMoveCursorPosition(ScreenX - 1, -1); ConWriteString(" ", 1); } else { @@ -263,10 +272,8 @@ ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char if (*pszCurrent == 27) { pszNewCurrent += ConWriteString((char *)pszCurrent, 1); return pszBuffer + 1; - } else { - if (term_mode == TERM_ANSI) - pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd, respbuf, resplen); - } + } else + pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd, respbuf, resplen); if (pszNewCurrent > pszCurrent) pszBuffer = pszNewCurrent; @@ -278,12 +285,12 @@ ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char if (bAtEOLN) GoToNextLine(); unsigned char* pszCurrent = pszBuffer; - CurrentX = ConGetCursorX(); + currentX = ConGetCursorX(); int nCharCount = 0; while ((pszCurrent < pszBufferEnd) && (*pszCurrent != (unsigned char)27) && (*pszCurrent > (unsigned char)15) && (*pszCurrent != (unsigned char)255) - && (CurrentX++ < ScreenX)) { + && (currentX++ < ScreenX)) { if (*pszCurrent > 127) { unsigned char nLead = *pszCurrent; nCharCount++; @@ -305,7 +312,7 @@ ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char pszBuffer += ConWriteString((char *)pszBuffer, (int)(pszCurrent - pszBuffer)); - if ((CurrentX >= ScreenX) && AutoWrap && !(VTMode & MODE_CURSORAPP)) + if ((currentX >= ScreenX) && AutoWrap && !(VTMode & MODE_CURSORAPP)) bAtEOLN = TRUE; } break; @@ -561,10 +568,10 @@ ParseANSI(unsigned char * pszBuffer, unsigned char * pszBufferEnd, unsigned char if (iParam[0]) { int i; for (i = 0; i < iParam[0]; i++) - ConScrollUp(ConGetCursorY() - 1, ScrollTop + ConWindowSizeY() - 2); + ConScrollUp(ConGetCursorY() - 1, ScrollTop + ConVisibleWindowHeight() - 2); } else { - if (ConGetCursorY() <= ScrollTop + ConWindowSizeY() - 2) - ConScrollUp(ConGetCursorY() - 1, ScrollTop + ConWindowSizeY() - 2); + if (ConGetCursorY() <= ScrollTop + ConVisibleWindowHeight() - 2) + ConScrollUp(ConGetCursorY() - 1, ScrollTop + ConVisibleWindowHeight() - 2); } fcompletion = 1; bAtEOLN = FALSE; @@ -600,7 +607,7 @@ ParseANSI(unsigned char * pszBuffer, unsigned char * pszBufferEnd, unsigned char for (i = 0; i < iParam[0]; i++) ConScrollUp(ConGetCursorY(), ScrollTop - ConGetCursorY()); } else { - if (ConGetCursorY() <= ScrollTop + ConWindowSizeY() - 2) + if (ConGetCursorY() <= ScrollTop + ConVisibleWindowHeight() - 2) ConScrollUp(ConGetCursorY(), ScrollTop - ConGetCursorY()); } fcompletion = 1; diff --git a/contrib/win32/win32compat/console.c b/contrib/win32/win32compat/console.c index eb6b717d7..7ec2eeb43 100644 --- a/contrib/win32/win32compat/console.c +++ b/contrib/win32/win32compat/console.c @@ -52,13 +52,14 @@ int ScrollTop; int ScrollBottom; int LastCursorX; int LastCursorY; -BOOL bAnsiParsing = FALSE; +BOOL isAnsiParsingRequired = FALSE; char *pSavedScreen = NULL; static COORD ZeroCoord = { 0,0 }; COORD SavedScreenSize = { 0,0 }; COORD SavedScreenCursor = { 0, 0 }; SMALL_RECT SavedViewRect = { 0,0,0,0 }; CONSOLE_SCREEN_BUFFER_INFOEX SavedWindowState; +BOOL isConHostParserEnabled = TRUE; typedef struct _SCREEN_RECORD { PCHAR_INFO pScreenBuf; @@ -69,10 +70,11 @@ typedef struct _SCREEN_RECORD { PSCREEN_RECORD pSavedScreenRec = NULL; int in_raw_mode = 0; +char *consoleTitle = "Microsoft openSSH client"; -/* Used to Initialize the Console for output */ +/* Used to enter the raw mode */ int -ConInit(DWORD OutputHandle, BOOL fSmartInit) +ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit) { OSVERSIONINFO os; DWORD dwAttributes = 0; @@ -87,16 +89,18 @@ ConInit(DWORD OutputHandle, BOOL fSmartInit) hOutputConsole = GetStdHandle(OutputHandle); if (hOutputConsole == INVALID_HANDLE_VALUE) { dwRet = GetLastError(); - printf("GetStdHandle on OutputHandle failed with %d\n", dwRet); + error("GetStdHandle on OutputHandle failed with %d\n", dwRet); return dwRet; } if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwSavedAttributes)) { dwRet = GetLastError(); - printf("GetConsoleMode on STD_INPUT_HANDLE failed with %d\n", dwRet); + error("GetConsoleMode on STD_INPUT_HANDLE failed with %d\n", dwRet); return dwRet; } + SetConsoleTitle(consoleTitle); + dwAttributes = dwSavedAttributes; dwAttributes &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); @@ -104,53 +108,69 @@ ConInit(DWORD OutputHandle, BOOL fSmartInit) if (!SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), dwAttributes)) { /* Windows NT */ dwRet = GetLastError(); - printf("SetConsoleMode on STD_INPUT_HANDLE failed with %d\n", dwRet); + error("SetConsoleMode on STD_INPUT_HANDLE failed with %d\n", dwRet); return dwRet; } if (!GetConsoleMode(hOutputConsole, &dwAttributes)) { dwRet = GetLastError(); - printf("GetConsoleMode on hOutputConsole failed with %d\n", dwRet); + error("GetConsoleMode on hOutputConsole failed with %d\n", dwRet); return dwRet; + } dwAttributes |= (DWORD)ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if (!SetConsoleMode(hOutputConsole, dwAttributes)) /* Windows NT */ - bAnsiParsing = TRUE; + if (NULL != getenv("SSH_TERM_CONHOST_PARSER")) + isConHostParserEnabled = atoi(getenv("SSH_TERM_CONHOST_PARSER")); + + /* We use our custom ANSI parser when + * a) User sets the environment variable "SSH_TERM_CONHOST_PARSER" to 0 + * b) or when the console doesn't have the inbuilt capability to parse the ANSI/Xterm raw buffer. + */ + if (FALSE == isConHostParserEnabled || !SetConsoleMode(hOutputConsole, dwAttributes)) /* Windows NT */ + isAnsiParsingRequired = TRUE; + + GetConsoleScreenBufferInfo(hOutputConsole, &csbi); + + /* if we are passing rawbuffer to console then we need to move the cursor to top + * so that the clearscreen will not erase any lines. + */ + if (TRUE == isAnsiParsingRequired) { + SavedViewRect = csbi.srWindow; + debug("console doesn't support the ansi parsing"); + } else { + ConMoveCurosorTop(csbi); + debug("console supports the ansi parsing"); + } ConSetScreenX(); ConSetScreenY(); ScrollTop = 0; - ScrollBottom = ConWindowSizeY(); - - if (GetConsoleScreenBufferInfo(hOutputConsole, &csbi)) - SavedViewRect = csbi.srWindow; - + ScrollBottom = ConVisibleWindowHeight(); + in_raw_mode = 1; + return 0; } /* Used to Uninitialize the Console */ int -ConUnInit(void) +ConExitRawMode() { CONSOLE_SCREEN_BUFFER_INFO consoleInfo; in_raw_mode = 0; - if (hOutputConsole == NULL) + if (hOutputConsole == NULL || !GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) return 0; - - if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) - return 0; - + SetConsoleMode(hOutputConsole, dwSavedAttributes); return 0; } -/* Used to Uninitialize the Console */ +/* Used to exit the raw mode */ int -ConUnInitWithRestore(void) +ConUnInitWithRestore() { DWORD dwWritten; COORD Coord; @@ -446,9 +466,9 @@ ConScreenSizeY() return (consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1); } -/* returns visible size of screen window */ +/* returns width of visible window */ int -ConWindowSizeX() +ConVisibleWindowWidth() { CONSOLE_SCREEN_BUFFER_INFO consoleInfo; @@ -458,9 +478,9 @@ ConWindowSizeX() return (consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1); } -/* returns visible size of screen window */ +/* returns height of visible window */ int -ConWindowSizeY() +ConVisibleWindowHeight() { CONSOLE_SCREEN_BUFFER_INFO consoleInfo; @@ -837,7 +857,7 @@ ConDisplayCursor(BOOL bVisible) } void -ConClearScreen(void) +ConClearScreen() { DWORD dwWritten; COORD Coord; @@ -850,7 +870,7 @@ ConClearScreen(void) Coord.X = 0; Coord.Y = 0; - DWORD dwNumChar = (consoleInfo.srWindow.Bottom + 1) * (consoleInfo.srWindow.Right + 1); + DWORD dwNumChar = (consoleInfo.dwSize.Y) * (consoleInfo.dwSize.X); FillConsoleOutputCharacter(hOutputConsole, ' ', dwNumChar, Coord, &dwWritten); FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes, dwNumChar, Coord, &dwWritten); srcWindow = consoleInfo.srWindow; @@ -1055,11 +1075,25 @@ ConScrollUp(int topline, int botline) ); } +void +ConMoveVisibleWindow(int offset) +{ + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + SMALL_RECT visibleWindowRect; + + if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) { + memcpy(&visibleWindowRect, &consoleInfo.srWindow, sizeof(visibleWindowRect)); + visibleWindowRect.Top += offset; + visibleWindowRect.Bottom += offset; + + SetConsoleWindowInfo(hOutputConsole, TRUE, &visibleWindowRect); + } +} + void ConScrollDown(int topline, int botline) { - SMALL_RECT ScrollRect; - SMALL_RECT ClipRect; + SMALL_RECT ScrollRect; COORD destination; CHAR_INFO Fill; CONSOLE_SCREEN_BUFFER_INFO consoleInfo; @@ -1078,11 +1112,6 @@ ConScrollDown(int topline, int botline) ScrollRect.Left = 0; ScrollRect.Right = ConScreenSizeX() - 1; - ClipRect.Top = ScrollRect.Top; - ClipRect.Bottom = ScrollRect.Bottom; - ClipRect.Left = ScrollRect.Left; - ClipRect.Right = ScrollRect.Right; - destination.X = 0; destination.Y = ScrollRect.Top - 1; @@ -1152,6 +1181,17 @@ ConChangeCursor(CONSOLE_CURSOR_INFO *pCursorInfo) return SetConsoleCursorInfo(hOutputConsole, pCursorInfo); } +void +ConGetCursorPosition(int *x, int *y) +{ + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + + if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) { + *x = consoleInfo.dwCursorPosition.X; + *y = consoleInfo.dwCursorPosition.Y; + } +} + int ConGetCursorX() { @@ -1163,6 +1203,21 @@ ConGetCursorX() return consoleInfo.dwCursorPosition.X; } +int +is_cursor_at_lastline_of_visible_window() +{ + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + int return_val = 0; + + if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) { + int cursor_linenum_in_visible_window = consoleInfo.dwCursorPosition.Y - consoleInfo.srWindow.Top; + if (cursor_linenum_in_visible_window >= ConVisibleWindowHeight() - 1) + return_val = 1; + } + + return return_val; +} + int ConGetCursorY() { @@ -1175,14 +1230,14 @@ ConGetCursorY() } int -ConGetCursorInBufferY() +ConGetBufferHeight() { CONSOLE_SCREEN_BUFFER_INFO consoleInfo; if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) return 0; - return (consoleInfo.dwCursorPosition.Y); + return (consoleInfo.dwSize.Y - 1); } void @@ -1390,28 +1445,53 @@ ConDeleteScreenHandle(SCREEN_HANDLE hScreen) /* Restores Previous Saved screen info and buffer */ BOOL -ConRestoreScreen(void) +ConRestoreScreen() { return ConRestoreScreenHandle(pSavedScreenRec); } /* Saves current screen info and buffer */ -BOOL -ConSaveScreen(void) +void +ConSaveScreen() { - pSavedScreenRec = (PSCREEN_RECORD)ConSaveScreenHandle(pSavedScreenRec); - return TRUE; + pSavedScreenRec = (PSCREEN_RECORD)ConSaveScreenHandle(pSavedScreenRec); } void -ConSaveViewRect(void) +ConSaveViewRect() { CONSOLE_SCREEN_BUFFER_INFO csbi; - if (!GetConsoleScreenBufferInfo(hOutputConsole, &csbi)) - return; + if (GetConsoleScreenBufferInfo(hOutputConsole, &csbi)) + SavedViewRect = csbi.srWindow; +} - SavedViewRect = csbi.srWindow; +void +ConRestoreViewRect() +{ + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + HWND hwnd = FindWindow(NULL, consoleTitle); + + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hwnd, &wp); + + if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo) && + ((consoleInfo.srWindow.Top != SavedViewRect.Top || + consoleInfo.srWindow.Bottom != SavedViewRect.Bottom))) { + if ((SavedViewRect.Right - SavedViewRect.Left > consoleInfo.dwSize.X) || + (wp.showCmd == SW_SHOWMAXIMIZED)) { + COORD coordScreen; + coordScreen.X = SavedViewRect.Right - SavedViewRect.Left; + coordScreen.Y = consoleInfo.dwSize.Y; + SetConsoleScreenBufferSize(hOutputConsole, coordScreen); + + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + } else + ShowWindow(hwnd, SW_RESTORE); + + SetConsoleWindowInfo(hOutputConsole, TRUE, &SavedViewRect); + } } BOOL @@ -1460,7 +1540,7 @@ GetConsoleInputHandle() } void -ConSaveWindowsState(void) +ConSaveWindowsState() { CONSOLE_SCREEN_BUFFER_INFOEX csbiex; csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); @@ -1470,3 +1550,12 @@ ConSaveWindowsState(void) SavedWindowState = csbiex; } + +void +ConMoveCurosorTop(CONSOLE_SCREEN_BUFFER_INFO csbi) +{ + int offset = csbi.dwCursorPosition.Y - csbi.srWindow.Top; + ConMoveVisibleWindow(offset); + + ConSaveViewRect(); +} diff --git a/contrib/win32/win32compat/console.h b/contrib/win32/win32compat/console.h index f06143e26..c98386d3a 100644 --- a/contrib/win32/win32compat/console.h +++ b/contrib/win32/win32compat/console.h @@ -42,38 +42,38 @@ #define __PRAGMA_CONSOLE_h #define ANSI_ATTR_RESET 0 -#define ANSI_BRIGHT 1 -#define ANSI_DIM 2 +#define ANSI_BRIGHT 1 +#define ANSI_DIM 2 #define ANSI_UNDERSCORE 4 -#define ANSI_BLINK 5 +#define ANSI_BLINK 5 #define ANSI_REVERSE 7 -#define ANSI_HIDDEN 8 -#define ANSI_NOUNDERSCORE 24 +#define ANSI_HIDDEN 8 +#define ANSI_NOUNDERSCORE 24 #define ANSI_NOREVERSE 27 -#define ANSI_FOREGROUND_BLACK 30 +#define ANSI_FOREGROUND_BLACK 30 #define ANSI_FOREGROUND_RED 31 -#define ANSI_FOREGROUND_GREEN 32 -#define ANSI_FOREGROUND_YELLOW 33 -#define ANSI_FOREGROUND_BLUE 34 -#define ANSI_FOREGROUND_MAGENTA 35 -#define ANSI_FOREGROUND_CYAN 36 -#define ANSI_FOREGROUND_WHITE 37 -#define ANSI_DEFAULT_FOREGROUND 39 -#define ANSI_BACKGROUND_BLACK 40 +#define ANSI_FOREGROUND_GREEN 32 +#define ANSI_FOREGROUND_YELLOW 33 +#define ANSI_FOREGROUND_BLUE 34 +#define ANSI_FOREGROUND_MAGENTA 35 +#define ANSI_FOREGROUND_CYAN 36 +#define ANSI_FOREGROUND_WHITE 37 +#define ANSI_DEFAULT_FOREGROUND 39 +#define ANSI_BACKGROUND_BLACK 40 #define ANSI_BACKGROUND_RED 41 -#define ANSI_BACKGROUND_GREEN 42 -#define ANSI_BACKGROUND_YELLOW 43 -#define ANSI_BACKGROUND_BLUE 44 -#define ANSI_BACKGROUND_MAGENTA 45 -#define ANSI_BACKGROUND_CYAN 46 -#define ANSI_BACKGROUND_WHITE 47 -#define ANSI_DEFAULT_BACKGROUND 49 -#define ANSI_BACKGROUND_BRIGHT 128 +#define ANSI_BACKGROUND_GREEN 42 +#define ANSI_BACKGROUND_YELLOW 43 +#define ANSI_BACKGROUND_BLUE 44 +#define ANSI_BACKGROUND_MAGENTA 45 +#define ANSI_BACKGROUND_CYAN 46 +#define ANSI_BACKGROUND_WHITE 47 +#define ANSI_DEFAULT_BACKGROUND 49 +#define ANSI_BACKGROUND_BRIGHT 128 -#define TAB_LENGTH 4 -#define TAB_CHAR '\t' -#define TAB_SPACE " " +#define TAB_LENGTH 4 +#define TAB_CHAR '\t' +#define TAB_SPACE " " #define true TRUE #define false FALSE @@ -81,30 +81,30 @@ typedef void * SCREEN_HANDLE; -int ConInit( DWORD OutputHandle, BOOL fSmartInit); -int ConUnInitWithRestore( void ); -int ConUnInit( void ); +int ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit); +int ConUnInitWithRestore(); +int ConExitRawMode(); BOOL ConIsRedirected(HANDLE hInput); HANDLE GetConsoleOutputHandle(); HANDLE GetConsoleInputHandle(); -BOOL ConSetScreenRect( int xSize, int ySize ); -BOOL ConSetScreenSize( int X, int Y ); -BOOL ConRestoreScreen( void ); -BOOL ConSaveScreen( void ); -void ConSetAttribute( int *iParam, int iParamCount ); -int ConScreenSizeX(); -int ConSetScreenX(); +BOOL ConSetScreenRect(int xSize, int ySize); +BOOL ConSetScreenSize(int X, int Y); +BOOL ConRestoreScreen(); +void ConSaveScreen(); +void ConSetAttribute(int *iParam, int iParamCount); +int ConScreenSizeX(); +int ConSetScreenX(); int ConScreenSizeY(); -int ConWindowSizeX(); -int ConWindowSizeY(); +int ConVisibleWindowWidth(); +int ConVisibleWindowHeight(); int ConSetScreenY(); void ConFillToEndOfLine(); int ConWriteString(char* pszString, int cbString); -BOOL ConWriteChar( CHAR ch ); -int ConWriteConsole( char *pData, int NumChars ); +BOOL ConWriteChar(CHAR ch); +int ConWriteConsole(char *pData, int NumChars); PCHAR ConDisplayData(char* pData, int NumLines); PCHAR ConWriteLine(char* pData); -int Con_printf( const char *Format, ... ); +int Con_printf(const char *Format, ...); void ConClearScrollRegion(); void ConClearScreen(); void ConClearEOScreen(); @@ -115,25 +115,27 @@ void ConClearNFromCursorRight(int n); void ConClearNFromCursorLeft(int n); void ConScrollUpEntireBuffer(); void ConScrollDownEntireBuffer(); -void ConScrollUp(int topline,int botline); -void ConScrollDown(int topline,int botline); +void ConScrollUp(int topline,int botline); +void ConScrollDown(int topline,int botline); void ConClearBOLine(); -BOOL ConChangeCursor( CONSOLE_CURSOR_INFO *pCursorInfo ); +BOOL ConChangeCursor(CONSOLE_CURSOR_INFO *pCursorInfo); void ConSetCursorPosition(int x, int y); int ConGetCursorX(); int ConGetCursorY(); -int ConGetCursorInBufferY(void); -BOOL ConDisplayCursor( BOOL bVisible ); +int ConGetBufferHeight(); +BOOL ConDisplayCursor(BOOL bVisible); void ConMoveCursorPosition(int x, int y); void ConGetRelativeCursorPosition(int *x, int *y); -BOOL ConRestoreScreenHandle( SCREEN_HANDLE hScreen ); -BOOL ConRestoreScreenColors( void ); -SCREEN_HANDLE ConSaveScreenHandle( SCREEN_HANDLE); -void ConDeleteScreenHandle( SCREEN_HANDLE hScreen ); -void ConSaveViewRect( void ); -void ConRestoreViewRect( void ); +BOOL ConRestoreScreenHandle(SCREEN_HANDLE hScreen); +BOOL ConRestoreScreenColors(); +SCREEN_HANDLE ConSaveScreenHandle(SCREEN_HANDLE); +void ConDeleteScreenHandle(SCREEN_HANDLE hScreen); +void ConSaveViewRect(); +void ConRestoreViewRect(); void ConDeleteChars(int n); -void ConSaveWindowsState(void); - - +void ConSaveWindowsState(); +void ConMoveVisibleWindow(int offset); +int is_cursor_at_lastline_of_visible_window(); +void ConGetCursorPosition(int *x, int *y); +void ConMoveCurosorTop(CONSOLE_SCREEN_BUFFER_INFO csbi); #endif diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index e74dd7160..08d907960 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -388,10 +388,12 @@ w32_ioctl(int d, int request, ...) errno = EINVAL; return -1; } - wsize->ws_col = c_info.dwSize.X - 5; - wsize->ws_row = c_info.dwSize.Y; + + wsize->ws_col = c_info.srWindow.Right - c_info.srWindow.Left + 1; + wsize->ws_row = c_info.srWindow.Bottom - c_info.srWindow.Top + 1; wsize->ws_xpixel = 640; wsize->ws_ypixel = 480; + return 0; } default: diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h index d17278ade..6150de03a 100644 --- a/contrib/win32/win32compat/misc_internal.h +++ b/contrib/win32/win32compat/misc_internal.h @@ -1,3 +1,4 @@ +#pragma once #define PATH_MAX MAX_PATH /* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */ @@ -9,4 +10,4 @@ void w32posix_done(); char* w32_programdir(); void convertToBackslash(char *str); -void convertToForwardslash(char *str); \ No newline at end of file +void convertToForwardslash(char *str); diff --git a/contrib/win32/win32compat/shell-host.c b/contrib/win32/win32compat/shell-host.c index 7b1fd95d3..a6e5b4615 100644 --- a/contrib/win32/win32compat/shell-host.c +++ b/contrib/win32/win32compat/shell-host.c @@ -121,6 +121,9 @@ struct key_translation keys[] = { { "\x1b[24~", VK_F12, 0 } }; +static SHORT lastX = 0; +static SHORT lastY = 0; + consoleEvent* head = NULL; consoleEvent* tail = NULL; @@ -182,6 +185,17 @@ STARTUPINFO inputSi; goto cleanup; \ } while(0) +int +ConSRWidth() +{ + CONSOLE_SCREEN_BUFFER_INFOEX consoleBufferInfo; + ZeroMemory(&consoleBufferInfo, sizeof(consoleBufferInfo)); + consoleBufferInfo.cbSize = sizeof(consoleBufferInfo); + + GetConsoleScreenBufferInfoEx(child_out, &consoleBufferInfo); + return consoleBufferInfo.srWindow.Right; +} + /* * This function will handle the console keystrokes. */ @@ -426,7 +440,7 @@ SendBuffer(HANDLE hInput, CHAR_INFO *buffer, DWORD bufferSize) } void -CalculateAndSetCursor(HANDLE hInput, UINT aboveTopLine, UINT viewPortHeight, UINT x, UINT y) +CalculateAndSetCursor(HANDLE hInput, UINT x, UINT y) { SendSetCursor(pipe_out, x + 1, y + 1); @@ -548,14 +562,13 @@ ProcessEvent(void *p) case EVENT_CONSOLE_CARET: { COORD co; + co.X = LOWORD(idChild); + co.Y = HIWORD(idChild); - if (idObject == CONSOLE_CARET_SELECTION) { - co.X = HIWORD(idChild); - co.Y = LOWORD(idChild); - } else { - co.X = HIWORD(idChild); - co.Y = LOWORD(idChild); - } + lastX = co.X; + lastY = co.Y; + + SendSetCursor(pipe_out, lastX + 1, lastY + 1); break; } @@ -568,6 +581,8 @@ ProcessEvent(void *p) readRect.Bottom = HIWORD(idChild); readRect.Right = LOWORD(idChild); + readRect.Right = max(readRect.Right, ConSRWidth()); + /* Detect a "cls" (Windows) */ if (!bStartup && (readRect.Top == consoleInfo.srWindow.Top || readRect.Top == nextConsoleInfo.srWindow.Top)) { @@ -632,7 +647,7 @@ ProcessEvent(void *p) SendLF(pipe_out); /* Set cursor location based on the reported location from the message */ - CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, readRect.Left, readRect.Top); + CalculateAndSetCursor(pipe_out, readRect.Left, readRect.Top); /* Send the entire block */ SendBuffer(pipe_out, pBuffer, bufferSize); @@ -649,12 +664,37 @@ ProcessEvent(void *p) wAttributes = HIWORD(idChild); wX = LOWORD(idObject); wY = HIWORD(idObject); - + + SMALL_RECT readRect; + readRect.Top = wY; + readRect.Bottom = wY; + readRect.Left = wX; + readRect.Right = ConSRWidth(); + /* Set cursor location based on the reported location from the message */ - CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, wX, wY); + CalculateAndSetCursor(pipe_out, wX, wY); + + COORD coordBufSize; + coordBufSize.Y = readRect.Bottom - readRect.Top + 1; + coordBufSize.X = readRect.Right - readRect.Left + 1; + /* The top left destination cell of the temporary buffer is row 0, col 0 */ + COORD coordBufCoord; + coordBufCoord.X = 0; + coordBufCoord.Y = 0; + int pBufferSize = coordBufSize.X * coordBufSize.Y; /* Send the one character. Note that a CR doesn't end up here */ - SendCharacter(pipe_out, wAttributes, chUpdate); + CHAR_INFO *pBuffer = (PCHAR_INFO)malloc(sizeof(CHAR_INFO) * pBufferSize); + + /* Copy the block from the screen buffer to the temp. buffer */ + if (!ReadConsoleOutput(child_out, pBuffer, coordBufSize, coordBufCoord, &readRect)) { + DWORD dwError = GetLastError(); + free(pBuffer); + return dwError; + } + + SendBuffer(pipe_out, pBuffer, pBufferSize); + free(pBuffer); break; } @@ -699,18 +739,24 @@ ProcessEvent(void *p) } } - ZeroMemory(&consoleInfo, sizeof(consoleInfo)); - consoleInfo.cbSize = sizeof(consoleInfo); - GetConsoleScreenBufferInfoEx(child_out, &consoleInfo); - return ERROR_SUCCESS; } DWORD WINAPI ProcessEventQueue(LPVOID p) { - static SHORT lastX = 0; - static SHORT lastY = 0; + if (child_in != INVALID_HANDLE_VALUE && child_in != NULL && + child_out != INVALID_HANDLE_VALUE && child_out != NULL) { + DWORD dwInputMode; + DWORD dwOutputMode; + + if (GetConsoleMode(child_in, &dwInputMode) && GetConsoleMode(child_out, &dwOutputMode)) + if (((dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING) && + ((dwInputMode & ENABLE_VIRTUAL_TERMINAL_INPUT) == ENABLE_VIRTUAL_TERMINAL_INPUT)) + bAnsi = TRUE; + else + bAnsi = FALSE; + } while (1) { while (head) { @@ -738,14 +784,6 @@ ProcessEventQueue(LPVOID p) DWORD dwInputMode; DWORD dwOutputMode; - if (GetConsoleMode(child_in, &dwInputMode) && GetConsoleMode(child_out, &dwOutputMode)) { - if (((dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING) && - ((dwInputMode & ENABLE_VIRTUAL_TERMINAL_INPUT) == ENABLE_VIRTUAL_TERMINAL_INPUT)) - bAnsi = TRUE; - else - bAnsi = FALSE; - } - ZeroMemory(&consoleInfo, sizeof(consoleInfo)); consoleInfo.cbSize = sizeof(consoleInfo); @@ -953,7 +991,7 @@ start_with_pty(wchar_t *command) /* * Windows PTY sends cursor positions in absolute coordinates starting from <0,0> * We send a clear screen upfront to simplify client - */ + */ SendClearScreen(pipe_out); ZeroMemory(&inputSi, sizeof(STARTUPINFO)); GetStartupInfo(&inputSi); @@ -963,7 +1001,7 @@ start_with_pty(wchar_t *command) hostThreadId = GetCurrentThreadId(); hostProcessId = GetCurrentProcessId(); InitializeCriticalSection(&criticalSection); - hEventHook = __SetWinEventHook(EVENT_CONSOLE_CARET, EVENT_CONSOLE_LAYOUT, NULL, + hEventHook = __SetWinEventHook(EVENT_CONSOLE_CARET, EVENT_CONSOLE_END_APPLICATION, NULL, ConsoleEventProc, 0, 0, WINEVENT_OUTOFCONTEXT); memset(&si, 0, sizeof(STARTUPINFO)); memset(&pi, 0, sizeof(PROCESS_INFORMATION)); diff --git a/contrib/win32/win32compat/ssh-agent/agent.h b/contrib/win32/win32compat/ssh-agent/agent.h index 36686ffea..e919cfc4a 100644 --- a/contrib/win32/win32compat/ssh-agent/agent.h +++ b/contrib/win32/win32compat/ssh-agent/agent.h @@ -37,7 +37,7 @@ struct agent_connection { }; void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*); -void agent_connection_on_error(struct agent_connection* , DWORD ); +void agent_connection_on_error(struct agent_connection* , DWORD); void agent_connection_disconnect(struct agent_connection*); void agent_start(BOOL, BOOL, HANDLE); diff --git a/contrib/win32/win32compat/termio.c b/contrib/win32/win32compat/termio.c index 967b20e97..d637aded0 100644 --- a/contrib/win32/win32compat/termio.c +++ b/contrib/win32/win32compat/termio.c @@ -39,6 +39,7 @@ #include "w32fd.h" #include "tncon.h" #include "inc\utf.h" +#include "tnnet.h" #define TERM_IO_BUF_SIZE 2048 @@ -136,6 +137,7 @@ WriteAPCProc(_In_ ULONG_PTR dwParam) pio->write_overlapped.hEvent = 0; } + /* Write worker thread */ static DWORD WINAPI WriteThread(_In_ LPVOID lpParameter) @@ -145,27 +147,27 @@ WriteThread(_In_ LPVOID lpParameter) size_t resplen = 0; DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT; debug3("TermWrite thread, io:%p", pio); - - if (in_raw_mode == 0) { - /* convert stream to utf16 and dump on console */ - pio->write_details.buf[write_status.to_transfer] = '\0'; + + pio->write_details.buf[write_status.to_transfer] = '\0'; + + if (0 == in_raw_mode) { wchar_t* t = utf8_to_utf16(pio->write_details.buf); WriteConsoleW(WINHANDLE(pio), t, wcslen(t), 0, 0); - free(t); - write_status.transferred = write_status.to_transfer; + free(t); } else { - /* console mode */ - telProcessNetwork(pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen); + processBuffer(WINHANDLE(pio), pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen); /* TODO - respbuf is not null in some cases, this needs to be returned back via read stream */ - write_status.transferred = write_status.to_transfer; } + write_status.transferred = write_status.to_transfer; + if (0 == QueueUserAPC(WriteAPCProc, main_thread, (ULONG_PTR)pio)) { debug("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio); pio->write_details.pending = FALSE; pio->write_details.error = GetLastError(); DebugBreak(); } + return 0; } diff --git a/contrib/win32/win32compat/tncon.c b/contrib/win32/win32compat/tncon.c index 6d6d81e31..503816ec7 100644 --- a/contrib/win32/win32compat/tncon.c +++ b/contrib/win32/win32compat/tncon.c @@ -1,37 +1,37 @@ /* - * Author: Ray Hayes - * ANSI TTY Reader - Maps Windows console input events to ANSI stream - * - * Author: Balu - * Misc fixes and code cleanup - * - * Copyright (c) 2017 Microsoft Corp. - * All rights reserved - * - * This file is responsible for console reading calls for building an emulator - * over Windows Console. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ +* Author: Ray Hayes +* ANSI TTY Reader - Maps Windows console input events to ANSI stream +* +* Author: Balu +* Misc fixes and code cleanup +* +* Copyright (c) 2017 Microsoft Corp. +* All rights reserved +* +* This file is responsible for console reading calls for building an emulator +* over Windows Console. +* +* 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. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +*/ #include #include #include @@ -75,10 +75,10 @@ TelParams* pParams = &Parameters; void queue_terminal_window_change_event(); /* - * For our case, in NetWriteString2(), we do not use socket, but write the out going data to - * a global buffer setup by ReadConsoleForTermEmul(). - */ -int +* For our case, in NetWriteString2(), we do not use socket, but write the out going data to +* a global buffer setup by ReadConsoleForTermEmul(). +*/ +int NetWriteString2(SOCKET sock, char* source, size_t len, int options) { while (len > 0) { @@ -91,7 +91,7 @@ NetWriteString2(SOCKET sock, char* source, size_t len, int options) return glob_outlen; } -BOOL +BOOL DataAvailable(HANDLE h) { DWORD dwRet = WaitForSingleObject(h, INFINITE); @@ -102,7 +102,7 @@ DataAvailable(HANDLE h) return FALSE; } -int +int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) { HANDLE hHandle[] = { hInput, NULL }; @@ -130,7 +130,7 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) break; case FOCUS_EVENT: - /* FALLTHROUGH */ + /* FALLTHROUGH */ case MENU_EVENT: break; @@ -210,41 +210,41 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) case VK_F1: if (dwControlKeyState == 0) NetWriteString2(pParams->Socket, (char *)PF1_KEY, strlen(PF1_KEY), 0); - + else if (dwControlKeyState == SHIFT_PRESSED) NetWriteString2(pParams->Socket, (char *)SHIFT_PF1_KEY, strlen(SHIFT_PF1_KEY), 0); - + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) NetWriteString2(pParams->Socket, (char *)CTRL_PF1_KEY, strlen(CTRL_PF1_KEY), 0); - + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) NetWriteString2(pParams->Socket, (char *)ALT_PF1_KEY, strlen(ALT_PF1_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF1_KEY, strlen(SHIFT_ALT_CTRL_PF1_KEY), 0); - + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF1_KEY, strlen(ALT_CTRL_PF1_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF1_KEY, strlen(SHIFT_ALT_PF1_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF1_KEY, strlen(SHIFT_CTRL_PF1_KEY), 0); - + break; case VK_F2: if (dwControlKeyState == 0) NetWriteString2(pParams->Socket, (char *)PF2_KEY, strlen(PF2_KEY), 0); - + else if (dwControlKeyState == SHIFT_PRESSED) NetWriteString2(pParams->Socket, (char *)SHIFT_PF2_KEY, strlen(SHIFT_PF2_KEY), 0); - + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) NetWriteString2(pParams->Socket, (char *)CTRL_PF2_KEY, strlen(CTRL_PF2_KEY), 0); @@ -255,15 +255,15 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF2_KEY, strlen(SHIFT_ALT_CTRL_PF2_KEY), 0); - + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF2_KEY, strlen(ALT_CTRL_PF2_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF2_KEY, strlen(SHIFT_ALT_PF2_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF2_KEY, strlen(SHIFT_CTRL_PF2_KEY), 0); @@ -271,13 +271,13 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) case VK_F3: if (dwControlKeyState == 0) NetWriteString2(pParams->Socket, (char *)PF3_KEY, strlen(PF3_KEY), 0); - + else if (dwControlKeyState == SHIFT_PRESSED) NetWriteString2(pParams->Socket, (char *)SHIFT_PF3_KEY, strlen(SHIFT_PF3_KEY), 0); - + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) NetWriteString2(pParams->Socket, (char *)CTRL_PF3_KEY, strlen(CTRL_PF3_KEY), 0); - + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) NetWriteString2(pParams->Socket, (char *)ALT_PF3_KEY, strlen(ALT_PF3_KEY), 0); @@ -301,29 +301,29 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) case VK_F4: if (dwControlKeyState == 0) NetWriteString2(pParams->Socket, (char *)PF4_KEY, strlen(PF4_KEY), 0); - + else if (dwControlKeyState == SHIFT_PRESSED) NetWriteString2(pParams->Socket, (char *)SHIFT_PF4_KEY, strlen(SHIFT_PF4_KEY), 0); - + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) NetWriteString2(pParams->Socket, (char *)CTRL_PF4_KEY, strlen(CTRL_PF4_KEY), 0); - + else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) NetWriteString2(pParams->Socket, (char *)ALT_PF4_KEY, strlen(ALT_PF4_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF4_KEY, strlen(SHIFT_ALT_CTRL_PF4_KEY), 0); - + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF4_KEY, strlen(ALT_CTRL_PF4_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF4_KEY, strlen(SHIFT_ALT_PF4_KEY), 0); - + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF4_KEY, strlen(SHIFT_CTRL_PF4_KEY), 0); @@ -331,10 +331,10 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) case VK_F5: if (dwControlKeyState == 0) NetWriteString2(pParams->Socket, (char *)PF5_KEY, strlen(PF5_KEY), 0); - + else if (dwControlKeyState == SHIFT_PRESSED) NetWriteString2(pParams->Socket, (char *)SHIFT_PF5_KEY, strlen(SHIFT_PF5_KEY), 0); - + else if (dwControlKeyState == LEFT_CTRL_PRESSED || dwControlKeyState == RIGHT_CTRL_PRESSED) NetWriteString2(pParams->Socket, (char *)CTRL_PF5_KEY, strlen(CTRL_PF5_KEY), 0); @@ -345,7 +345,7 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF5_KEY, strlen(SHIFT_ALT_CTRL_PF5_KEY), 0); - + else if ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF5_KEY, strlen(ALT_CTRL_PF5_KEY), 0); @@ -492,7 +492,7 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) NetWriteString2(pParams->Socket, (char *)ALT_PF10_KEY, strlen(ALT_PF10_KEY), 0); else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || - (dwControlKeyState & LEFT_ALT_PRESSED)) &&((dwControlKeyState & LEFT_CTRL_PRESSED) || + (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF10_KEY, strlen(SHIFT_ALT_CTRL_PF10_KEY), 0); @@ -521,7 +521,7 @@ ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) else if (dwControlKeyState == LEFT_ALT_PRESSED || dwControlKeyState == RIGHT_ALT_PRESSED) NetWriteString2(pParams->Socket, (char *)ALT_PF11_KEY, strlen(ALT_PF11_KEY), 0); - else if ((dwControlKeyState & SHIFT_PRESSED) &&((dwControlKeyState & RIGHT_ALT_PRESSED) || + else if ((dwControlKeyState & SHIFT_PRESSED) && ((dwControlKeyState & RIGHT_ALT_PRESSED) || (dwControlKeyState & LEFT_ALT_PRESSED)) && ((dwControlKeyState & LEFT_CTRL_PRESSED) || (dwControlKeyState & RIGHT_CTRL_PRESSED))) NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF11_KEY, strlen(SHIFT_ALT_CTRL_PF11_KEY), 0); diff --git a/contrib/win32/win32compat/tnnet.c b/contrib/win32/win32compat/tnnet.c index 9763010e0..310546e60 100644 --- a/contrib/win32/win32compat/tnnet.c +++ b/contrib/win32/win32compat/tnnet.c @@ -35,17 +35,20 @@ #include #include #include "ansiprsr.h" +#include "inc\utf.h" #define dwBuffer 4096 +extern BOOL isAnsiParsingRequired; + /* * Server will always be returning a sequence of ANSI control characters which the client * protocol can either passthru directly to the console or transform based on an output terminal * type. We're not using termcap so we're only supporting the ANSI (vt100) sequences that * are hardcoded in the server and will be transformed to Windows Console commands. */ -size_t -telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resplen) +void +processBuffer(HANDLE handle, char *buf, size_t len, unsigned char **respbuf, size_t *resplen) { unsigned char szBuffer[dwBuffer + 8]; unsigned char* pszNewHead = NULL; @@ -53,7 +56,17 @@ telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resple unsigned char* pszTail = NULL; if (len == 0) - return len; + return; + + if (false == isAnsiParsingRequired) { + /* Console has the capability to parse so pass the raw buffer to console directly */ + ConRestoreViewRect(); /* Restore the visible window, otherwise WriteConsoleW() gets messy */ + wchar_t* t = utf8_to_utf16(buf); + WriteConsoleW(handle, t, wcslen(t), 0, 0); + free(t); + ConSaveViewRect(); + return; + } /* Transform a single carriage return into a single linefeed before continuing */ if ((len == 1) && (buf[0] == 13)) @@ -74,6 +87,4 @@ telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resple pszNewHead = ParseBuffer(pszHead, pszTail, respbuf, resplen); } while ((pszNewHead != pszHead) && (pszNewHead < pszTail) && (resplen == NULL || (resplen != NULL && *resplen == 0))); - len = 0; - return len; } diff --git a/contrib/win32/win32compat/tnnet.h b/contrib/win32/win32compat/tnnet.h index d2fb54b67..c3f5c312d 100644 --- a/contrib/win32/win32compat/tnnet.h +++ b/contrib/win32/win32compat/tnnet.h @@ -35,8 +35,6 @@ #ifndef __TNNET_H #define __TNNET_H +void processBuffer(HANDLE handle, char *buf, size_t len, unsigned char **respbuf, size_t *resplen); - size_t telProcessNetwork (char *buf, size_t len, unsigned char **respbuf, size_t *resplen); - -#endif - \ No newline at end of file +#endif \ No newline at end of file diff --git a/sshtty.c b/sshtty.c index aca8899cd..5825c85e7 100644 --- a/sshtty.c +++ b/sshtty.c @@ -52,8 +52,8 @@ static int _in_raw_mode = 0; * TTY raw mode routines for Windows */ -int ConInit(DWORD OutputHandle, BOOL fSmartInit); -int ConUnInit(void); +int ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit); +int ConExitRawMode(void); struct termios term_settings; @@ -70,12 +70,12 @@ struct termios * void leave_raw_mode(int quiet) { - ConUnInit(); + ConExitRawMode(); } void enter_raw_mode(int quiet) { - ConInit(STD_OUTPUT_HANDLE, TRUE); + ConEnterRawMode(STD_OUTPUT_HANDLE, TRUE); } #else /* !WINDOWS */ struct termios *