/* * CONSOLE.C - console input/output functions. * * * History: * * 20-Jan-1999 (Eric Kohl) * started * * 03-Apr-2005 (Magnus Olsen ) * Remove all hardcoded strings in En.rc * * 01-Jul-2005 (Brandon Turner ) * Added ConPrintfPaging and ConOutPrintfPaging * * 02-Feb-2007 (Paolo Devoti ) * Fixed ConPrintfPaging */ #include "precomp.h" #define OUTPUT_BUFFER_SIZE 4096 /* Cache codepage for text streams */ UINT InputCodePage; UINT OutputCodePage; /* Global console Screen and Pager */ CON_SCREEN StdOutScreen = INIT_CON_SCREEN(StdOut); CON_PAGER StdOutPager = INIT_CON_PAGER(&StdOutScreen); /********************* Console STREAM IN utility functions ********************/ VOID ConInDisable(VOID) { HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); DWORD dwMode; GetConsoleMode(hInput, &dwMode); dwMode &= ~ENABLE_PROCESSED_INPUT; SetConsoleMode(hInput, dwMode); } VOID ConInEnable(VOID) { HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); DWORD dwMode; GetConsoleMode(hInput, &dwMode); dwMode |= ENABLE_PROCESSED_INPUT; SetConsoleMode(hInput, dwMode); } VOID ConInFlush(VOID) { FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); } VOID ConInKey(PINPUT_RECORD lpBuffer) { HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); DWORD dwRead; if (hInput == INVALID_HANDLE_VALUE) WARN ("Invalid input handle!!!\n"); do { ReadConsoleInput(hInput, lpBuffer, 1, &dwRead); if (lpBuffer->EventType == KEY_EVENT && lpBuffer->Event.KeyEvent.bKeyDown) { break; } } while (TRUE); } VOID ConInString(LPWSTR lpInput, DWORD dwLength) { DWORD dwOldMode; DWORD dwRead = 0; HANDLE hFile; LPWSTR p; PCHAR pBuf; pBuf = (PCHAR)cmd_alloc(dwLength - 1); ZeroMemory(lpInput, dwLength * sizeof(WCHAR)); hFile = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hFile, &dwOldMode); SetConsoleMode(hFile, ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); ReadFile(hFile, (PVOID)pBuf, dwLength - 1, &dwRead, NULL); MultiByteToWideChar(InputCodePage, 0, pBuf, dwRead, lpInput, dwLength - 1); cmd_free(pBuf); for (p = lpInput; *p; p++) { if (*p == L'\r') // Terminate at the carriage-return. { *p = L'\0'; break; } } SetConsoleMode(hFile, dwOldMode); } /******************** Console STREAM OUT utility functions ********************/ VOID ConOutChar(WCHAR c) { ConWrite(StdOut, &c, 1); } VOID ConErrChar(WCHAR c) { ConWrite(StdErr, &c, 1); } VOID __cdecl ConFormatMessage(PCON_STREAM Stream, DWORD MessageId, ...) { INT Len; va_list arg_ptr; va_start(arg_ptr, MessageId); Len = ConMsgPrintfV(Stream, FORMAT_MESSAGE_FROM_SYSTEM, NULL, MessageId, LANG_USER_DEFAULT, &arg_ptr); va_end(arg_ptr); if (Len <= 0) ConResPrintf(Stream, STRING_CONSOLE_ERROR, MessageId); } /************************** Console PAGER functions ***************************/ BOOL ConPrintfVPaging(PCON_PAGER Pager, BOOL StartPaging, LPWSTR szFormat, va_list arg_ptr) { // INT len; WCHAR szOut[OUTPUT_BUFFER_SIZE]; /* Return if no string has been given */ if (szFormat == NULL) return TRUE; /*len =*/ vswprintf(szOut, szFormat, arg_ptr); // return ConPutsPaging(Pager, PagePrompt, StartPaging, szOut); return ConWritePaging(Pager, PagePrompt, StartPaging, szOut, wcslen(szOut)); } BOOL __cdecl ConOutPrintfPaging(BOOL StartPaging, LPWSTR szFormat, ...) { BOOL bRet; va_list arg_ptr; va_start(arg_ptr, szFormat); bRet = ConPrintfVPaging(&StdOutPager, StartPaging, szFormat, arg_ptr); va_end(arg_ptr); return bRet; } VOID ConOutResPaging(BOOL StartPaging, UINT resID) { ConResPaging(&StdOutPager, PagePrompt, StartPaging, resID); } /************************** Console SCREEN functions **************************/ VOID SetCursorXY(SHORT x, SHORT y) { COORD coPos; coPos.X = x; coPos.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coPos); } VOID GetCursorXY(PSHORT x, PSHORT y) { CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); *x = csbi.dwCursorPosition.X; *y = csbi.dwCursorPosition.Y; } SHORT GetCursorX(VOID) { CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); return csbi.dwCursorPosition.X; } SHORT GetCursorY(VOID) { CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); return csbi.dwCursorPosition.Y; } VOID SetCursorType(BOOL bInsert, BOOL bVisible) { CONSOLE_CURSOR_INFO cci; cci.dwSize = bInsert ? 10 : 99; cci.bVisible = bVisible; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci); } VOID GetScreenSize(PSHORT maxx, PSHORT maxy) { CONSOLE_SCREEN_BUFFER_INFO csbi; if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { csbi.dwSize.X = 80; csbi.dwSize.Y = 25; } if (maxx) *maxx = csbi.dwSize.X; if (maxy) *maxy = csbi.dwSize.Y; } #ifdef INCLUDE_CMD_COLOR BOOL ConGetDefaultAttributes(PWORD pwDefAttr) { BOOL Success; HANDLE hConsole; CONSOLE_SCREEN_BUFFER_INFO csbi; /* Do not modify *pwDefAttr if we fail, in which case use default attributes */ hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hConsole == INVALID_HANDLE_VALUE) return FALSE; // No default console Success = GetConsoleScreenBufferInfo(hConsole, &csbi); if (Success) *pwDefAttr = csbi.wAttributes; CloseHandle(hConsole); return Success; } #endif BOOL ConSetTitle(IN LPCWSTR lpConsoleTitle) { /* Now really set the console title */ return SetConsoleTitle(lpConsoleTitle); } #ifdef INCLUDE_CMD_BEEP VOID ConRingBell(HANDLE hOutput) { #if 0 /* Emit an error beep sound */ if (IsConsoleHandle(hOutput)) Beep(800, 200); else if (IsTTYHandle(hOutput)) ConOutPuts(_T("\a")); // BEL character 0x07 else #endif MessageBeep(-1); } #endif #ifdef INCLUDE_CMD_COLOR BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill) { DWORD dwWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; COORD coPos; /* Foreground and Background colors can't be the same */ if ((wColor & 0x0F) == (wColor & 0xF0) >> 4) return FALSE; /* Fill the whole background if needed */ if (bFill) { GetConsoleScreenBufferInfo(hOutput, &csbi); coPos.X = 0; coPos.Y = 0; FillConsoleOutputAttribute(hOutput, wColor & 0x00FF, csbi.dwSize.X * csbi.dwSize.Y, coPos, &dwWritten); } /* Set the text attribute */ SetConsoleTextAttribute(hOutput, wColor & 0x00FF); return TRUE; } #endif #include #include "wcwidth.c" // NOTE: The check against 0x80 is to avoid calling the helper function // for characters that we already know are not full-width. #define IS_FULL_WIDTH(wch) \ (((USHORT)(wch) >= 0x0080) && (mk_wcwidth_cjk(wch) == 2)) SIZE_T ConGetTextWidthW(PCWSTR pszText) { SIZE_T ich, cxWidth; if (!IsCJKCodePage(OutputCodePage)) return _tcslen(pszText); for (ich = cxWidth = 0; pszText[ich]; ++ich) { if (IS_FULL_WIDTH(pszText[ich])) cxWidth += 2; else ++cxWidth; } return cxWidth; } SIZE_T ConGetTextWidthA(PCSTR pszText) { int cchMax; PWSTR pszWide; SIZE_T cxWidth; cchMax = MultiByteToWideChar(OutputCodePage, 0, pszText, -1, NULL, 0); pszWide = cmd_alloc(cchMax * sizeof(WCHAR)); MultiByteToWideChar(OutputCodePage, 0, pszText, -1, pszWide, cchMax); cxWidth = ConGetTextWidthW(pszWide); cmd_free(pszWide); return cxWidth; } /* EOF */