1 /* 2 * CONSOLE.C - console input/output functions. 3 * 4 * 5 * History: 6 * 7 * 20-Jan-1999 (Eric Kohl) 8 * started 9 * 10 * 03-Apr-2005 (Magnus Olsen <magnus@greatlord.com>) 11 * Remove all hardcoded strings in En.rc 12 * 13 * 01-Jul-2005 (Brandon Turner <turnerb7@msu.edu>) 14 * Added ConPrintfPaging and ConOutPrintfPaging 15 * 16 * 02-Feb-2007 (Paolo Devoti <devotip at gmail.com>) 17 * Fixed ConPrintfPaging 18 */ 19 20 #include "precomp.h" 21 22 #define OUTPUT_BUFFER_SIZE 4096 23 24 /* Cache codepage for text streams */ 25 UINT InputCodePage; 26 UINT OutputCodePage; 27 28 /* Global console Screen and Pager */ 29 CON_SCREEN StdOutScreen = INIT_CON_SCREEN(StdOut); 30 CON_PAGER StdOutPager = INIT_CON_PAGER(&StdOutScreen); 31 32 33 34 /********************* Console STREAM IN utility functions ********************/ 35 36 VOID ConInDisable(VOID) 37 { 38 HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); 39 DWORD dwMode; 40 41 GetConsoleMode(hInput, &dwMode); 42 dwMode &= ~ENABLE_PROCESSED_INPUT; 43 SetConsoleMode(hInput, dwMode); 44 } 45 46 VOID ConInEnable(VOID) 47 { 48 HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); 49 DWORD dwMode; 50 51 GetConsoleMode(hInput, &dwMode); 52 dwMode |= ENABLE_PROCESSED_INPUT; 53 SetConsoleMode(hInput, dwMode); 54 } 55 56 VOID ConInFlush(VOID) 57 { 58 FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); 59 } 60 61 VOID ConInKey(PINPUT_RECORD lpBuffer) 62 { 63 HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); 64 DWORD dwRead; 65 66 if (hInput == INVALID_HANDLE_VALUE) 67 WARN ("Invalid input handle!!!\n"); 68 69 do 70 { 71 ReadConsoleInput(hInput, lpBuffer, 1, &dwRead); 72 if (lpBuffer->EventType == KEY_EVENT && 73 lpBuffer->Event.KeyEvent.bKeyDown) 74 { 75 break; 76 } 77 } 78 while (TRUE); 79 } 80 81 VOID ConInString(LPWSTR lpInput, DWORD dwLength) 82 { 83 DWORD dwOldMode; 84 DWORD dwRead = 0; 85 HANDLE hFile; 86 87 LPWSTR p; 88 PCHAR pBuf; 89 90 pBuf = (PCHAR)cmd_alloc(dwLength - 1); 91 92 ZeroMemory(lpInput, dwLength * sizeof(WCHAR)); 93 hFile = GetStdHandle(STD_INPUT_HANDLE); 94 GetConsoleMode(hFile, &dwOldMode); 95 96 SetConsoleMode(hFile, ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); 97 98 ReadFile(hFile, (PVOID)pBuf, dwLength - 1, &dwRead, NULL); 99 100 MultiByteToWideChar(InputCodePage, 0, pBuf, dwRead, lpInput, dwLength - 1); 101 cmd_free(pBuf); 102 103 for (p = lpInput; *p; p++) 104 { 105 if (*p == L'\r') // Terminate at the carriage-return. 106 { 107 *p = L'\0'; 108 break; 109 } 110 } 111 112 SetConsoleMode(hFile, dwOldMode); 113 } 114 115 116 117 /******************** Console STREAM OUT utility functions ********************/ 118 119 VOID ConOutChar(WCHAR c) 120 { 121 ConWrite(StdOut, &c, 1); 122 } 123 124 VOID ConErrChar(WCHAR c) 125 { 126 ConWrite(StdErr, &c, 1); 127 } 128 129 VOID __cdecl ConFormatMessage(PCON_STREAM Stream, DWORD MessageId, ...) 130 { 131 INT Len; 132 va_list arg_ptr; 133 134 va_start(arg_ptr, MessageId); 135 Len = ConMsgPrintfV(Stream, 136 FORMAT_MESSAGE_FROM_SYSTEM, 137 NULL, 138 MessageId, 139 LANG_USER_DEFAULT, 140 &arg_ptr); 141 va_end(arg_ptr); 142 143 if (Len <= 0) 144 ConResPrintf(Stream, STRING_CONSOLE_ERROR, MessageId); 145 } 146 147 148 149 /************************** Console PAGER functions ***************************/ 150 151 BOOL ConPrintfVPaging(PCON_PAGER Pager, BOOL StartPaging, LPWSTR szFormat, va_list arg_ptr) 152 { 153 // INT len; 154 WCHAR szOut[OUTPUT_BUFFER_SIZE]; 155 156 /* Return if no string has been given */ 157 if (szFormat == NULL) 158 return TRUE; 159 160 /*len =*/ vswprintf(szOut, szFormat, arg_ptr); 161 162 // return ConPutsPaging(Pager, PagePrompt, StartPaging, szOut); 163 return ConWritePaging(Pager, PagePrompt, StartPaging, 164 szOut, wcslen(szOut)); 165 } 166 167 BOOL __cdecl ConOutPrintfPaging(BOOL StartPaging, LPWSTR szFormat, ...) 168 { 169 BOOL bRet; 170 va_list arg_ptr; 171 172 va_start(arg_ptr, szFormat); 173 bRet = ConPrintfVPaging(&StdOutPager, StartPaging, szFormat, arg_ptr); 174 va_end(arg_ptr); 175 return bRet; 176 } 177 178 VOID ConOutResPaging(BOOL StartPaging, UINT resID) 179 { 180 ConResPaging(&StdOutPager, PagePrompt, StartPaging, resID); 181 } 182 183 184 185 /************************** Console SCREEN functions **************************/ 186 187 VOID SetCursorXY(SHORT x, SHORT y) 188 { 189 COORD coPos; 190 191 coPos.X = x; 192 coPos.Y = y; 193 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coPos); 194 } 195 196 VOID GetCursorXY(PSHORT x, PSHORT y) 197 { 198 CONSOLE_SCREEN_BUFFER_INFO csbi; 199 200 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 201 202 *x = csbi.dwCursorPosition.X; 203 *y = csbi.dwCursorPosition.Y; 204 } 205 206 SHORT GetCursorX(VOID) 207 { 208 CONSOLE_SCREEN_BUFFER_INFO csbi; 209 210 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 211 return csbi.dwCursorPosition.X; 212 } 213 214 SHORT GetCursorY(VOID) 215 { 216 CONSOLE_SCREEN_BUFFER_INFO csbi; 217 218 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 219 return csbi.dwCursorPosition.Y; 220 } 221 222 VOID SetCursorType(BOOL bInsert, BOOL bVisible) 223 { 224 CONSOLE_CURSOR_INFO cci; 225 226 cci.dwSize = bInsert ? 10 : 99; 227 cci.bVisible = bVisible; 228 229 SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci); 230 } 231 232 VOID GetScreenSize(PSHORT maxx, PSHORT maxy) 233 { 234 CONSOLE_SCREEN_BUFFER_INFO csbi; 235 236 if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) 237 { 238 csbi.dwSize.X = 80; 239 csbi.dwSize.Y = 25; 240 } 241 242 if (maxx) *maxx = csbi.dwSize.X; 243 if (maxy) *maxy = csbi.dwSize.Y; 244 } 245 246 247 248 249 #ifdef INCLUDE_CMD_COLOR 250 251 BOOL ConGetDefaultAttributes(PWORD pwDefAttr) 252 { 253 BOOL Success; 254 HANDLE hConsole; 255 CONSOLE_SCREEN_BUFFER_INFO csbi; 256 257 /* Do not modify *pwDefAttr if we fail, in which case use default attributes */ 258 259 hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE, 260 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, 261 OPEN_EXISTING, 0, NULL); 262 if (hConsole == INVALID_HANDLE_VALUE) 263 return FALSE; // No default console 264 265 Success = GetConsoleScreenBufferInfo(hConsole, &csbi); 266 if (Success) 267 *pwDefAttr = csbi.wAttributes; 268 269 CloseHandle(hConsole); 270 return Success; 271 } 272 273 #endif 274 275 276 BOOL ConSetTitle(IN LPCWSTR lpConsoleTitle) 277 { 278 /* Now really set the console title */ 279 return SetConsoleTitle(lpConsoleTitle); 280 } 281 282 #ifdef INCLUDE_CMD_BEEP 283 VOID ConRingBell(HANDLE hOutput) 284 { 285 #if 0 286 /* Emit an error beep sound */ 287 if (IsConsoleHandle(hOutput)) 288 Beep(800, 200); 289 else if (IsTTYHandle(hOutput)) 290 ConOutPuts(_T("\a")); // BEL character 0x07 291 else 292 #endif 293 MessageBeep(-1); 294 } 295 #endif 296 297 #ifdef INCLUDE_CMD_COLOR 298 BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill) 299 { 300 DWORD dwWritten; 301 CONSOLE_SCREEN_BUFFER_INFO csbi; 302 COORD coPos; 303 304 /* Foreground and Background colors can't be the same */ 305 if ((wColor & 0x0F) == (wColor & 0xF0) >> 4) 306 return FALSE; 307 308 /* Fill the whole background if needed */ 309 if (bFill) 310 { 311 GetConsoleScreenBufferInfo(hOutput, &csbi); 312 313 coPos.X = 0; 314 coPos.Y = 0; 315 FillConsoleOutputAttribute(hOutput, 316 wColor & 0x00FF, 317 csbi.dwSize.X * csbi.dwSize.Y, 318 coPos, 319 &dwWritten); 320 } 321 322 /* Set the text attribute */ 323 SetConsoleTextAttribute(hOutput, wColor & 0x00FF); 324 return TRUE; 325 } 326 #endif 327 328 #include <cjkcode.h> 329 #include "wcwidth.c" 330 331 // NOTE: The check against 0x80 is to avoid calling the helper function 332 // for characters that we already know are not full-width. 333 #define IS_FULL_WIDTH(wch) \ 334 (((USHORT)(wch) >= 0x0080) && (mk_wcwidth_cjk(wch) == 2)) 335 336 SIZE_T ConGetTextWidthW(PCWSTR pszText) 337 { 338 SIZE_T ich, cxWidth; 339 340 if (!IsCJKCodePage(OutputCodePage)) 341 return _tcslen(pszText); 342 343 for (ich = cxWidth = 0; pszText[ich]; ++ich) 344 { 345 if (IS_FULL_WIDTH(pszText[ich])) 346 cxWidth += 2; 347 else 348 ++cxWidth; 349 } 350 351 return cxWidth; 352 } 353 354 SIZE_T ConGetTextWidthA(PCSTR pszText) 355 { 356 int cchMax; 357 PWSTR pszWide; 358 SIZE_T cxWidth; 359 360 cchMax = MultiByteToWideChar(OutputCodePage, 0, pszText, -1, NULL, 0); 361 pszWide = cmd_alloc(cchMax * sizeof(WCHAR)); 362 MultiByteToWideChar(OutputCodePage, 0, pszText, -1, pszWide, cchMax); 363 cxWidth = ConGetTextWidthW(pszWide); 364 cmd_free(pszWide); 365 return cxWidth; 366 } 367 368 /* EOF */ 369