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
ConInDisable(VOID)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
ConInEnable(VOID)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
ConInFlush(VOID)56 VOID ConInFlush(VOID)
57 {
58 FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
59 }
60
ConInKey(PINPUT_RECORD lpBuffer)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
ConInString(LPWSTR lpInput,DWORD dwLength)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
ConOutChar(WCHAR c)119 VOID ConOutChar(WCHAR c)
120 {
121 ConWrite(StdOut, &c, 1);
122 }
123
ConErrChar(WCHAR c)124 VOID ConErrChar(WCHAR c)
125 {
126 ConWrite(StdErr, &c, 1);
127 }
128
ConFormatMessage(PCON_STREAM Stream,DWORD MessageId,...)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
ConPrintfVPaging(PCON_PAGER Pager,BOOL StartPaging,LPWSTR szFormat,va_list arg_ptr)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
ConOutPrintfPaging(BOOL StartPaging,LPWSTR szFormat,...)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
ConOutResPaging(BOOL StartPaging,UINT resID)178 VOID ConOutResPaging(BOOL StartPaging, UINT resID)
179 {
180 ConResPaging(&StdOutPager, PagePrompt, StartPaging, resID);
181 }
182
183
184
185 /************************** Console SCREEN functions **************************/
186
SetCursorXY(SHORT x,SHORT y)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
GetCursorXY(PSHORT x,PSHORT y)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
GetCursorX(VOID)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
GetCursorY(VOID)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
SetCursorType(BOOL bInsert,BOOL bVisible)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
GetScreenSize(PSHORT maxx,PSHORT maxy)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
ConGetDefaultAttributes(PWORD pwDefAttr)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
ConSetTitle(IN LPCWSTR lpConsoleTitle)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
ConRingBell(HANDLE hOutput)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
ConSetScreenColor(HANDLE hOutput,WORD wColor,BOOL bFill)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
ConGetTextWidthW(PCWSTR pszText)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
ConGetTextWidthA(PCSTR pszText)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