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(LPTSTR lpInput, DWORD dwLength) 82 { 83 DWORD dwOldMode; 84 DWORD dwRead = 0; 85 HANDLE hFile; 86 87 LPTSTR p; 88 PCHAR pBuf; 89 90 #ifdef _UNICODE 91 pBuf = (PCHAR)cmd_alloc(dwLength - 1); 92 #else 93 pBuf = lpInput; 94 #endif 95 ZeroMemory(lpInput, dwLength * sizeof(TCHAR)); 96 hFile = GetStdHandle(STD_INPUT_HANDLE); 97 GetConsoleMode(hFile, &dwOldMode); 98 99 SetConsoleMode(hFile, ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); 100 101 ReadFile(hFile, (PVOID)pBuf, dwLength - 1, &dwRead, NULL); 102 103 #ifdef _UNICODE 104 MultiByteToWideChar(InputCodePage, 0, pBuf, dwRead, lpInput, dwLength - 1); 105 cmd_free(pBuf); 106 #endif 107 for (p = lpInput; *p; p++) 108 { 109 if (*p == _T('\r')) // Terminate at the carriage-return. 110 { 111 *p = _T('\0'); 112 break; 113 } 114 } 115 116 SetConsoleMode(hFile, dwOldMode); 117 } 118 119 120 121 /******************** Console STREAM OUT utility functions ********************/ 122 123 VOID ConOutChar(TCHAR c) 124 { 125 ConWrite(StdOut, &c, 1); 126 } 127 128 VOID ConErrChar(TCHAR c) 129 { 130 ConWrite(StdErr, &c, 1); 131 } 132 133 VOID __cdecl ConFormatMessage(PCON_STREAM Stream, DWORD MessageId, ...) 134 { 135 INT Len; 136 va_list arg_ptr; 137 138 va_start(arg_ptr, MessageId); 139 Len = ConMsgPrintfV(Stream, 140 FORMAT_MESSAGE_FROM_SYSTEM, 141 NULL, 142 MessageId, 143 LANG_USER_DEFAULT, 144 &arg_ptr); 145 va_end(arg_ptr); 146 147 if (Len <= 0) 148 ConResPrintf(Stream, STRING_CONSOLE_ERROR, MessageId); 149 } 150 151 152 153 /************************** Console PAGER functions ***************************/ 154 155 BOOL ConPrintfVPaging(PCON_PAGER Pager, BOOL StartPaging, LPTSTR szFormat, va_list arg_ptr) 156 { 157 // INT len; 158 TCHAR szOut[OUTPUT_BUFFER_SIZE]; 159 160 /* Return if no string has been given */ 161 if (szFormat == NULL) 162 return TRUE; 163 164 /*len =*/ _vstprintf(szOut, szFormat, arg_ptr); 165 166 // return ConPutsPaging(Pager, PagePrompt, StartPaging, szOut); 167 return ConWritePaging(Pager, PagePrompt, StartPaging, 168 szOut, wcslen(szOut)); 169 } 170 171 BOOL __cdecl ConOutPrintfPaging(BOOL StartPaging, LPTSTR szFormat, ...) 172 { 173 BOOL bRet; 174 va_list arg_ptr; 175 176 va_start(arg_ptr, szFormat); 177 bRet = ConPrintfVPaging(&StdOutPager, StartPaging, szFormat, arg_ptr); 178 va_end(arg_ptr); 179 return bRet; 180 } 181 182 VOID ConOutResPaging(BOOL StartPaging, UINT resID) 183 { 184 ConResPaging(&StdOutPager, PagePrompt, StartPaging, resID); 185 } 186 187 188 189 /************************** Console SCREEN functions **************************/ 190 191 VOID SetCursorXY(SHORT x, SHORT y) 192 { 193 COORD coPos; 194 195 coPos.X = x; 196 coPos.Y = y; 197 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coPos); 198 } 199 200 VOID GetCursorXY(PSHORT x, PSHORT y) 201 { 202 CONSOLE_SCREEN_BUFFER_INFO csbi; 203 204 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 205 206 *x = csbi.dwCursorPosition.X; 207 *y = csbi.dwCursorPosition.Y; 208 } 209 210 SHORT GetCursorX(VOID) 211 { 212 CONSOLE_SCREEN_BUFFER_INFO csbi; 213 214 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 215 return csbi.dwCursorPosition.X; 216 } 217 218 SHORT GetCursorY(VOID) 219 { 220 CONSOLE_SCREEN_BUFFER_INFO csbi; 221 222 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 223 return csbi.dwCursorPosition.Y; 224 } 225 226 VOID SetCursorType(BOOL bInsert, BOOL bVisible) 227 { 228 CONSOLE_CURSOR_INFO cci; 229 230 cci.dwSize = bInsert ? 10 : 99; 231 cci.bVisible = bVisible; 232 233 SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci); 234 } 235 236 VOID GetScreenSize(PSHORT maxx, PSHORT maxy) 237 { 238 CONSOLE_SCREEN_BUFFER_INFO csbi; 239 240 if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) 241 { 242 csbi.dwSize.X = 80; 243 csbi.dwSize.Y = 25; 244 } 245 246 if (maxx) *maxx = csbi.dwSize.X; 247 if (maxy) *maxy = csbi.dwSize.Y; 248 } 249 250 251 252 253 #ifdef INCLUDE_CMD_COLOR 254 255 BOOL ConGetDefaultAttributes(PWORD pwDefAttr) 256 { 257 BOOL Success; 258 HANDLE hConsole; 259 CONSOLE_SCREEN_BUFFER_INFO csbi; 260 261 /* Do not modify *pwDefAttr if we fail, in which case use default attributes */ 262 263 hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE, 264 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, 265 OPEN_EXISTING, 0, NULL); 266 if (hConsole == INVALID_HANDLE_VALUE) 267 return FALSE; // No default console 268 269 Success = GetConsoleScreenBufferInfo(hConsole, &csbi); 270 if (Success) 271 *pwDefAttr = csbi.wAttributes; 272 273 CloseHandle(hConsole); 274 return Success; 275 } 276 277 #endif 278 279 280 BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle) 281 { 282 /* Now really set the console title */ 283 return SetConsoleTitle(lpConsoleTitle); 284 } 285 286 #ifdef INCLUDE_CMD_BEEP 287 VOID ConRingBell(HANDLE hOutput) 288 { 289 #if 0 290 /* Emit an error beep sound */ 291 if (IsConsoleHandle(hOutput)) 292 Beep(800, 200); 293 else if (IsTTYHandle(hOutput)) 294 ConOutPuts(_T("\a")); // BEL character 0x07 295 else 296 #endif 297 MessageBeep(-1); 298 } 299 #endif 300 301 #ifdef INCLUDE_CMD_COLOR 302 BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill) 303 { 304 DWORD dwWritten; 305 CONSOLE_SCREEN_BUFFER_INFO csbi; 306 COORD coPos; 307 308 /* Foreground and Background colors can't be the same */ 309 if ((wColor & 0x0F) == (wColor & 0xF0) >> 4) 310 return FALSE; 311 312 /* Fill the whole background if needed */ 313 if (bFill) 314 { 315 GetConsoleScreenBufferInfo(hOutput, &csbi); 316 317 coPos.X = 0; 318 coPos.Y = 0; 319 FillConsoleOutputAttribute(hOutput, 320 wColor & 0x00FF, 321 csbi.dwSize.X * csbi.dwSize.Y, 322 coPos, 323 &dwWritten); 324 } 325 326 /* Set the text attribute */ 327 SetConsoleTextAttribute(hOutput, wColor & 0x00FF); 328 return TRUE; 329 } 330 #endif 331 332 #include <cjkcode.h> 333 #include "wcwidth.c" 334 335 // NOTE: The check against 0x80 is to avoid calling the helper function 336 // for characters that we already know are not full-width. 337 #define IS_FULL_WIDTH(wch) \ 338 (((USHORT)(wch) >= 0x0080) && (mk_wcwidth_cjk(wch) == 2)) 339 340 SIZE_T ConGetTextWidthW(PCWSTR pszText) 341 { 342 SIZE_T ich, cxWidth; 343 344 if (!IsCJKCodePage(OutputCodePage)) 345 return _tcslen(pszText); 346 347 for (ich = cxWidth = 0; pszText[ich]; ++ich) 348 { 349 if (IS_FULL_WIDTH(pszText[ich])) 350 cxWidth += 2; 351 else 352 ++cxWidth; 353 } 354 355 return cxWidth; 356 } 357 358 SIZE_T ConGetTextWidthA(PCSTR pszText) 359 { 360 int cchMax; 361 PWSTR pszWide; 362 SIZE_T cxWidth; 363 364 cchMax = MultiByteToWideChar(OutputCodePage, 0, pszText, -1, NULL, 0); 365 pszWide = cmd_alloc(cchMax * sizeof(WCHAR)); 366 MultiByteToWideChar(OutputCodePage, 0, pszText, -1, pszWide, cchMax); 367 cxWidth = ConGetTextWidthW(pszWide); 368 cmd_free(pszWide); 369 return cxWidth; 370 } 371 372 /* EOF */ 373