blob: 414a40ac036dc77b5e9245e9193fb069dc082a9c [file] [log] [blame]
Alexandre Julliardade697e1995-11-26 13:59:11 +00001/*
2 * Win32 kernel functions
3 *
4 * Copyright 1995 Martin von Loewis and Cameron Heide
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00005 * Copyright 1997 Karl Garrison
Alexandre Julliard03468f71998-02-15 19:40:49 +00006 * Copyright 1998 John Richardson
Marcus Meissner537772a1998-12-09 16:37:04 +00007 * Copyright 1998 Marcus Meissner
8 */
9
10/* FIXME:
Marcus Meissner8bc54b61998-12-14 14:48:09 +000011 * - Completely lacks SCREENBUFFER interface.
12 * - No abstraction for something other than xterm.
13 * - Key input translation shouldn't use VkKeyScan and MapVirtualKey, since
14 * they are window (USER) driver dependend.
15 * - Output sometimes is buffered (We switched off buffering by ~ICANON ?)
16 */
17/* Reference applications:
18 * - IDA (interactive disassembler) full version 3.75. Works.
19 * - LYNX/W32. Works mostly, some keys crash it.
Alexandre Julliardade697e1995-11-26 13:59:11 +000020 */
21
Alexandre Julliard84c70f51997-05-09 08:40:27 +000022#include <stdlib.h>
Alexandre Julliard03468f71998-02-15 19:40:49 +000023#include <unistd.h>
Alexandre Julliard03468f71998-02-15 19:40:49 +000024#include <termios.h>
Marcus Meissnerb02ffc71998-10-11 10:49:46 +000025#include <strings.h>
Alexandre Julliard03468f71998-02-15 19:40:49 +000026#include <sys/ioctl.h>
27#include <sys/types.h>
Marcus Meissnerb02ffc71998-10-11 10:49:46 +000028#include <sys/time.h>
Alexandre Julliard03468f71998-02-15 19:40:49 +000029#include <unistd.h>
30#include <fcntl.h>
31#include <errno.h>
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000032#include <sys/errno.h>
Alexandre Julliard03468f71998-02-15 19:40:49 +000033#include <signal.h>
34#include <assert.h>
Marcus Meissnerad7538b1998-12-14 18:15:10 +000035
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000036#include "winbase.h"
37#include "wine/winuser16.h"
38#include "wine/keyboard16.h"
Marcus Meissnerad7538b1998-12-14 18:15:10 +000039#include "thread.h"
40#include "async.h"
Alexandre Julliard03468f71998-02-15 19:40:49 +000041#include "file.h"
42#include "process.h"
Alexandre Julliardade697e1995-11-26 13:59:11 +000043#include "winerror.h"
Alexandre Julliardade697e1995-11-26 13:59:11 +000044#include "wincon.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000045#include "heap.h"
Alexandre Julliardade697e1995-11-26 13:59:11 +000046#include "debug.h"
47
Alexandre Julliardb2340ea1998-12-30 12:10:49 +000048#include "server/request.h"
49#include "server.h"
50
Alexandre Julliard03468f71998-02-15 19:40:49 +000051
Zygo Blaxelledc858c1999-02-09 14:14:16 +000052/* FIXME: Should be in an internal header file. OK, so which one?
53 Used by CONSOLE_makecomplex. */
54FILE *wine_openpty(int *master, int *slave, char *name,
55 struct termios *term, struct winsize *winsize);
56
Alexandre Julliard62a8b431999-01-19 17:48:23 +000057/****************************************************************************
58 * CONSOLE_GetInfo
59 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000060static BOOL CONSOLE_GetInfo( HANDLE handle, struct get_console_info_reply *reply )
Alexandre Julliard62a8b431999-01-19 17:48:23 +000061{
62 struct get_console_info_request req;
63
Alexandre Julliard96c08d81999-02-28 13:27:56 +000064 req.handle = handle;
Alexandre Julliard62a8b431999-01-19 17:48:23 +000065 CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
66 return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
67}
68
Marcus Meissner537772a1998-12-09 16:37:04 +000069/****************************************************************************
70 * XTERM_string_to_IR [internal]
71 *
72 * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the
73 * queue. Does translation of vt100 style function keys and xterm-mouse clicks.
74 */
75static void
Alexandre Julliarda3960291999-02-26 11:11:13 +000076CONSOLE_string_to_IR( HANDLE hConsoleInput,unsigned char *buf,int len) {
Marcus Meissner537772a1998-12-09 16:37:04 +000077 int j,k;
78 INPUT_RECORD ir;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +000079 DWORD junk;
Marcus Meissner537772a1998-12-09 16:37:04 +000080
81 for (j=0;j<len;j++) {
82 unsigned char inchar = buf[j];
83
84 if (inchar!=27) { /* no escape -> 'normal' keyboard event */
85 ir.EventType = 1; /* Key_event */
86
Marcus Meissner8bc54b61998-12-14 14:48:09 +000087 ir.Event.KeyEvent.bKeyDown = 1;
88 ir.Event.KeyEvent.wRepeatCount = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +000089
Marcus Meissner8bc54b61998-12-14 14:48:09 +000090 ir.Event.KeyEvent.dwControlKeyState = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +000091 if (inchar & 0x80) {
92 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
93 inchar &= ~0x80;
94 }
Marcus Meissner8bc54b61998-12-14 14:48:09 +000095 ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(inchar);
96 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100)
Marcus Meissner537772a1998-12-09 16:37:04 +000097 ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED;
Marcus Meissner8bc54b61998-12-14 14:48:09 +000098 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200)
99 ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED;
100 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400)
101 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
102 ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
103 ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff,
104 0 /* VirtualKeyCodes to ScanCode */
105 );
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000106 ir.Event.KeyEvent.uChar.AsciiChar = inchar;
107
108 if (inchar==127) { /* backspace */
109 ir.Event.KeyEvent.uChar.AsciiChar = '\b'; /* FIXME: hmm */
110 ir.Event.KeyEvent.wVirtualScanCode = 0x0e;
111 ir.Event.KeyEvent.wVirtualKeyCode = VK_BACK;
Marcus Meissner537772a1998-12-09 16:37:04 +0000112 } else {
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000113 if (inchar=='\n') {
114 ir.Event.KeyEvent.uChar.AsciiChar = '\r';
115 ir.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
116 ir.Event.KeyEvent.wVirtualScanCode = 0x1c;
117 } else {
118 if (inchar<' ') {
119 /* FIXME: find good values for ^X */
120 ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;
121 ir.Event.KeyEvent.wVirtualScanCode = 0xbeef;
122 }
123 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000124 }
125
Alexandre Julliarda3960291999-02-26 11:11:13 +0000126 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000127 ir.Event.KeyEvent.bKeyDown = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000128 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000129 continue;
130 }
131 /* inchar is ESC */
132 if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */
133 ir.EventType = 1; /* Key_event */
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000134 ir.Event.KeyEvent.bKeyDown = 1;
135 ir.Event.KeyEvent.wRepeatCount = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +0000136
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000137 ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(27);
138 ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
139 ir.Event.KeyEvent.wVirtualKeyCode,0
140 );
Marcus Meissner537772a1998-12-09 16:37:04 +0000141 ir.Event.KeyEvent.dwControlKeyState = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +0000142 ir.Event.KeyEvent.uChar.AsciiChar = 27;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000143 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000144 ir.Event.KeyEvent.bKeyDown = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000145 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000146 continue;
147 }
148 for (k=j;k<len;k++) {
149 if (((buf[k]>='A') && (buf[k]<='Z')) ||
150 ((buf[k]>='a') && (buf[k]<='z')) ||
151 (buf[k]=='~')
152 )
153 break;
154 }
155 if (k<len) {
156 int subid,scancode=0;
157
158 ir.EventType = 1; /* Key_event */
159 ir.Event.KeyEvent.bKeyDown = 1;
160 ir.Event.KeyEvent.wRepeatCount = 0;
161 ir.Event.KeyEvent.dwControlKeyState = 0;
162
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000163 ir.Event.KeyEvent.wVirtualKeyCode = 0xad; /* FIXME */
164 ir.Event.KeyEvent.wVirtualScanCode = 0xad; /* FIXME */
Marcus Meissner537772a1998-12-09 16:37:04 +0000165 ir.Event.KeyEvent.uChar.AsciiChar = 0;
166
167 switch (buf[k]) {
168 case '~':
169 sscanf(&buf[j+2],"%d",&subid);
170 switch (subid) {
171 case 2:/*INS */scancode = 0xe052;break;
172 case 3:/*DEL */scancode = 0xe053;break;
173 case 6:/*PGDW*/scancode = 0xe051;break;
174 case 5:/*PGUP*/scancode = 0xe049;break;
175 case 11:/*F1 */scancode = 0x003b;break;
176 case 12:/*F2 */scancode = 0x003c;break;
177 case 13:/*F3 */scancode = 0x003d;break;
178 case 14:/*F4 */scancode = 0x003e;break;
179 case 15:/*F5 */scancode = 0x003f;break;
180 case 17:/*F6 */scancode = 0x0040;break;
181 case 18:/*F7 */scancode = 0x0041;break;
182 case 19:/*F8 */scancode = 0x0042;break;
183 case 20:/*F9 */scancode = 0x0043;break;
184 case 21:/*F10 */scancode = 0x0044;break;
185 case 23:/*F11 */scancode = 0x00d9;break;
186 case 24:/*F12 */scancode = 0x00da;break;
187 /* FIXME: Shift-Fx */
188 default:
189 FIXME(console,"parse ESC[%d~\n",subid);
190 break;
191 }
192 break;
193 case 'A': /* Cursor Up */scancode = 0xe048;break;
194 case 'B': /* Cursor Down */scancode = 0xe050;break;
195 case 'D': /* Cursor Left */scancode = 0xe04b;break;
196 case 'C': /* Cursor Right */scancode = 0xe04d;break;
197 case 'F': /* End */scancode = 0xe04f;break;
198 case 'H': /* Home */scancode = 0xe047;break;
199 case 'M':
200 /* Mouse Button Press (ESCM<button+'!'><x+'!'><y+'!'>) or
201 * Release (ESCM#<x+'!'><y+'!'>
202 */
203 if (k<len-3) {
204 ir.EventType = MOUSE_EVENT;
205 ir.Event.MouseEvent.dwMousePosition.x = buf[k+2]-'!';
206 ir.Event.MouseEvent.dwMousePosition.y = buf[k+3]-'!';
207 if (buf[k+1]=='#')
208 ir.Event.MouseEvent.dwButtonState = 0;
209 else
210 ir.Event.MouseEvent.dwButtonState = 1<<(buf[k+1]-' ');
211 ir.Event.MouseEvent.dwEventFlags = 0; /* FIXME */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000212 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk));
Marcus Meissner537772a1998-12-09 16:37:04 +0000213 j=k+3;
214 }
215 break;
216
217 }
218 if (scancode) {
219 ir.Event.KeyEvent.wVirtualScanCode = scancode;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000220 ir.Event.KeyEvent.wVirtualKeyCode = MapVirtualKey16(scancode,1);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000221 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000222 ir.Event.KeyEvent.bKeyDown = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000223 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000224 j=k;
225 continue;
226 }
227 }
228 }
229}
Alexandre Julliard55443871998-12-31 15:52:06 +0000230
Marcus Meissner537772a1998-12-09 16:37:04 +0000231/****************************************************************************
232 * CONSOLE_get_input (internal)
233 *
234 * Reads (nonblocking) as much input events as possible and stores them
235 * in an internal queue.
Marcus Meissner537772a1998-12-09 16:37:04 +0000236 */
237static void
Alexandre Julliarda3960291999-02-26 11:11:13 +0000238CONSOLE_get_input( HANDLE handle, BOOL blockwait )
Alexandre Julliard55443871998-12-31 15:52:06 +0000239{
Marcus Meissner537772a1998-12-09 16:37:04 +0000240 char *buf = HeapAlloc(GetProcessHeap(),0,1);
241 int len = 0;
242
Alexandre Julliard55443871998-12-31 15:52:06 +0000243 while (1)
244 {
245 DWORD res;
246 char inchar;
Marcus Meissnerba8e2a31999-01-03 16:18:33 +0000247 if (WaitForSingleObject( handle, 0 )) break;
Alexandre Julliard55443871998-12-31 15:52:06 +0000248 if (!ReadFile( handle, &inchar, 1, &res, NULL )) break;
Marcus Meissner03f10f41999-01-26 10:08:36 +0000249 if (!res) /* res 0 but readable means EOF? Hmm. */
250 break;
Marcus Meissner537772a1998-12-09 16:37:04 +0000251 buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1);
252 buf[len++]=inchar;
253 }
Alexandre Julliard55443871998-12-31 15:52:06 +0000254 CONSOLE_string_to_IR(handle,buf,len);
Marcus Meissner537772a1998-12-09 16:37:04 +0000255 HeapFree(GetProcessHeap(),0,buf);
256}
257
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000258/******************************************************************************
259 * SetConsoleCtrlHandler [KERNEL32.459] Adds function to calling process list
260 *
261 * PARAMS
262 * func [I] Address of handler function
263 * add [I] Handler to add or remove
264 *
265 * RETURNS
266 * Success: TRUE
267 * Failure: FALSE
James Sutherland577db371998-11-08 15:09:08 +0000268 *
269 * CHANGED
270 * James Sutherland (JamesSutherland@gmx.de)
271 * Added global variables console_ignore_ctrl_c and handlers[]
272 * Does not yet do any error checking, or set LastError if failed.
273 * This doesn't yet matter, since these handlers are not yet called...!
Alexandre Julliardade697e1995-11-26 13:59:11 +0000274 */
James Sutherland577db371998-11-08 15:09:08 +0000275static unsigned int console_ignore_ctrl_c = 0;
276static HANDLER_ROUTINE *handlers[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
Alexandre Julliarda3960291999-02-26 11:11:13 +0000277BOOL WINAPI SetConsoleCtrlHandler( HANDLER_ROUTINE *func, BOOL add )
Alexandre Julliardade697e1995-11-26 13:59:11 +0000278{
James Sutherland577db371998-11-08 15:09:08 +0000279 unsigned int alloc_loop = sizeof(handlers)/sizeof(HANDLER_ROUTINE *);
280 unsigned int done = 0;
281 FIXME(console, "(%p,%i) - no error checking or testing yet\n", func, add);
282 if (!func)
283 {
284 console_ignore_ctrl_c = add;
285 return TRUE;
286 }
287 if (add)
288 {
289 for (;alloc_loop--;)
290 if (!handlers[alloc_loop] && !done)
291 {
292 handlers[alloc_loop] = func;
293 done++;
294 }
295 if (!done)
296 FIXME(console, "Out of space on CtrlHandler table\n");
297 return(done);
298 }
299 else
300 {
301 for (;alloc_loop--;)
302 if (handlers[alloc_loop] == func && !done)
303 {
304 handlers[alloc_loop] = 0;
305 done++;
306 }
307 if (!done)
Huw D M Davies7b06d981998-11-14 17:13:51 +0000308 WARN(console, "Attempt to remove non-installed CtrlHandler %p\n",
309 func);
James Sutherland577db371998-11-08 15:09:08 +0000310 return (done);
311 }
312 return (done);
313}
314
315
316/******************************************************************************
317 * GenerateConsoleCtrlEvent [KERNEL32.275] Simulate a CTRL-C or CTRL-BREAK
318 *
319 * PARAMS
320 * dwCtrlEvent [I] Type of event
321 * dwProcessGroupID [I] Process group ID to send event to
322 *
323 * NOTES
324 * Doesn't yet work...!
325 *
326 * RETURNS
327 * Success: True
328 * Failure: False (and *should* [but doesn't] set LastError)
329 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000330BOOL WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent,
James Sutherland577db371998-11-08 15:09:08 +0000331 DWORD dwProcessGroupID )
332{
333 if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
334 {
Marcus Meissner537772a1998-12-09 16:37:04 +0000335 ERR( console, "invalid event %d for PGID %ld\n",
James Sutherland577db371998-11-08 15:09:08 +0000336 (unsigned short)dwCtrlEvent, dwProcessGroupID );
337 return FALSE;
338 }
339 if (dwProcessGroupID == GetCurrentProcessId() )
340 {
341 FIXME( console, "Attempt to send event %d to self - stub\n",
342 (unsigned short)dwCtrlEvent );
343 return FALSE;
344 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000345 FIXME( console,"event %d to external PGID %ld - not implemented yet\n",
James Sutherland577db371998-11-08 15:09:08 +0000346 (unsigned short)dwCtrlEvent, dwProcessGroupID );
347 return FALSE;
Alexandre Julliardade697e1995-11-26 13:59:11 +0000348}
349
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000350
351/******************************************************************************
352 * CreateConsoleScreenBuffer [KERNEL32.151] Creates a console screen buffer
353 *
354 * PARAMS
355 * dwDesiredAccess [I] Access flag
356 * dwShareMode [I] Buffer share mode
357 * sa [I] Security attributes
358 * dwFlags [I] Type of buffer to create
359 * lpScreenBufferData [I] Reserved
360 *
361 * NOTES
362 * Should call SetLastError
363 *
364 * RETURNS
365 * Success: Handle to new console screen buffer
366 * Failure: INVALID_HANDLE_VALUE
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000367 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000368HANDLE WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000369 DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa,
370 DWORD dwFlags, LPVOID lpScreenBufferData )
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000371{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000372 FIXME(console, "(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess,
373 dwShareMode, sa, dwFlags, lpScreenBufferData);
Marcus Meissner537772a1998-12-09 16:37:04 +0000374 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000375 return INVALID_HANDLE_VALUE;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000376}
377
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000378
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000379/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000380 * GetConsoleScreenBufferInfo (KERNEL32.190)
381 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000382BOOL WINAPI GetConsoleScreenBufferInfo( HANDLE hConsoleOutput,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000383 LPCONSOLE_SCREEN_BUFFER_INFO csbi )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000384{
385 csbi->dwSize.x = 80;
386 csbi->dwSize.y = 24;
387 csbi->dwCursorPosition.x = 0;
388 csbi->dwCursorPosition.y = 0;
389 csbi->wAttributes = 0;
390 csbi->srWindow.Left = 0;
391 csbi->srWindow.Right = 79;
392 csbi->srWindow.Top = 0;
393 csbi->srWindow.Bottom = 23;
394 csbi->dwMaximumWindowSize.x = 80;
395 csbi->dwMaximumWindowSize.y = 24;
396 return TRUE;
397}
398
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000399
400/******************************************************************************
401 * SetConsoleActiveScreenBuffer [KERNEL32.623] Sets buffer to current console
402 *
403 * RETURNS
404 * Success: TRUE
405 * Failure: FALSE
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000406 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000407BOOL WINAPI SetConsoleActiveScreenBuffer(
408 HANDLE hConsoleOutput) /* [in] Handle to console screen buffer */
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000409{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000410 FIXME(console, "(%x): stub\n", hConsoleOutput);
411 return FALSE;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000412}
413
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000414
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000415/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000416 * GetLargestConsoleWindowSize (KERNEL32.226)
417 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000418DWORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000419{
Marcus Meissner537772a1998-12-09 16:37:04 +0000420 return (DWORD)MAKELONG(80,24);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000421}
422
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000423/***********************************************************************
Alexandre Julliard03468f71998-02-15 19:40:49 +0000424 * FreeConsole (KERNEL32.267)
425 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000426BOOL WINAPI FreeConsole(VOID)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000427{
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000428 CLIENT_SendRequest( REQ_FREE_CONSOLE, -1, 0 );
429 return !CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000430}
431
432
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000433/*************************************************************************
434 * CONSOLE_OpenHandle
435 *
436 * Open a handle to the current process console.
Alexandre Julliard03468f71998-02-15 19:40:49 +0000437 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000438HANDLE CONSOLE_OpenHandle( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES sa )
Alexandre Julliard03468f71998-02-15 19:40:49 +0000439{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000440 struct open_console_request req;
441 struct open_console_reply reply;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000442
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000443 req.output = output;
444 req.access = access;
445 req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
446 CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
Alexandre Julliard3f09ec51999-02-28 19:25:51 +0000447 SetLastError(0);
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000448 CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000449 return reply.handle;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000450}
451
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000452
Marcus Meissner537772a1998-12-09 16:37:04 +0000453/*************************************************************************
454 * CONSOLE_make_complex [internal]
455 *
456 * Turns a CONSOLE kernel object into a complex one.
457 * (switches from output/input using the terminal where WINE was started to
458 * its own xterm).
459 *
460 * This makes simple commandline tools pipeable, while complex commandline
461 * tools work without getting messed up by debugoutput.
462 *
463 * All other functions should work indedependend from this call.
464 *
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000465 * To test for complex console: pid == 0 -> simple, otherwise complex.
Marcus Meissner537772a1998-12-09 16:37:04 +0000466 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000467static BOOL CONSOLE_make_complex(HANDLE handle)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000468{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000469 struct set_console_fd_request req;
470 struct get_console_info_reply info;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000471 struct termios term;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000472 char buf[256];
Alexandre Julliard03468f71998-02-15 19:40:49 +0000473 char c = '\0';
474 int status = 0;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000475 int i,xpid,master,slave;
Marcus Meissner537772a1998-12-09 16:37:04 +0000476 DWORD xlen;
477
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000478 if (!CONSOLE_GetInfo( handle, &info )) return FALSE;
479 if (info.pid) return TRUE; /* already complex */
Marcus Meissner537772a1998-12-09 16:37:04 +0000480
481 MSG("Console: Making console complex (creating an xterm)...\n");
Alexandre Julliard03468f71998-02-15 19:40:49 +0000482
Marcus Meissner03f10f41999-01-26 10:08:36 +0000483 if (tcgetattr(0, &term) < 0) {
484 /* ignore failure, or we can't run from a script */
485 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000486 term.c_lflag = ~(ECHO|ICANON);
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000487
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000488 if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0)
489 return FALSE;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000490
Marcus Meissner537772a1998-12-09 16:37:04 +0000491 if ((xpid=fork()) == 0) {
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000492 tcsetattr(slave, TCSADRAIN, &term);
493 sprintf(buf, "-Sxx%d", master);
Marcus Meissner537772a1998-12-09 16:37:04 +0000494 /* "-fn vga" for VGA font. Harmless if vga is not present:
495 * xterm: unable to open font "vga", trying "fixed"....
496 */
497 execlp("xterm", "xterm", buf, "-fn","vga",NULL);
Alexandre Julliard54c27111998-03-29 19:44:57 +0000498 ERR(console, "error creating AllocConsole xterm\n");
Alexandre Julliard03468f71998-02-15 19:40:49 +0000499 exit(1);
500 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000501
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000502 req.handle = handle;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000503 req.pid = xpid;
504 CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1, &req, sizeof(req) );
505 CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000506
507 /* most xterms like to print their window ID when used with -S;
508 * read it and continue before the user has a chance...
Alexandre Julliard03468f71998-02-15 19:40:49 +0000509 */
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000510 for (i=0; c!='\n'; (status=read(slave, &c, 1)), i++) {
Alexandre Julliard03468f71998-02-15 19:40:49 +0000511 if (status == -1 && c == '\0') {
512 /* wait for xterm to be created */
513 usleep(100);
514 }
515 if (i > 10000) {
Marcus Meissner537772a1998-12-09 16:37:04 +0000516 ERR(console, "can't read xterm WID\n");
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000517 kill(xpid, SIGKILL);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000518 return FALSE;
519 }
520 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000521 /* enable mouseclicks */
522 sprintf(buf,"%c[?1001s%c[?1000h",27,27);
Alexandre Julliard55443871998-12-31 15:52:06 +0000523 WriteFile(handle,buf,strlen(buf),&xlen,NULL);
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000524
Alexandre Julliarda3960291999-02-26 11:11:13 +0000525 if (GetConsoleTitleA( buf, sizeof(buf) ))
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000526 {
527 WriteFile(handle,"\033]2;",4,&xlen,NULL);
528 WriteFile(handle,buf,strlen(buf),&xlen,NULL);
529 WriteFile(handle,"\a",1,&xlen,NULL);
Alexandre Julliard638f1691999-01-17 16:32:32 +0000530 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000531 return TRUE;
532
533}
534
535
536/***********************************************************************
537 * AllocConsole (KERNEL32.103)
538 *
539 * creates an xterm with a pty to our program
540 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000541BOOL WINAPI AllocConsole(VOID)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000542{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000543 struct open_console_request req;
544 struct open_console_reply reply;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000545 HANDLE hIn, hOut, hErr;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000546
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000547 CLIENT_SendRequest( REQ_ALLOC_CONSOLE, -1, 0 );
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000548 if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS) return FALSE;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000549
550 req.output = 0;
Marcus Meissnerfbc56251999-01-20 14:46:49 +0000551 req.access = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000552 req.inherit = FALSE;
553 CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
Alexandre Julliard6ebbe3c1999-01-01 17:04:00 +0000554 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000555 {
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000556 /* FIXME: free console */
Alexandre Julliard03468f71998-02-15 19:40:49 +0000557 return FALSE;
Alexandre Julliardb2340ea1998-12-30 12:10:49 +0000558 }
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000559 hIn = reply.handle;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000560
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000561 req.output = 1;
562 CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
563 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
564 {
565 CloseHandle(hIn);
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000566 /* FIXME: free console */
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000567 return FALSE;
568 }
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000569 hOut = reply.handle;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000570
Alexandre Julliardb2340ea1998-12-30 12:10:49 +0000571 if (!DuplicateHandle( GetCurrentProcess(), hOut,
572 GetCurrentProcess(), &hErr,
573 0, TRUE, DUPLICATE_SAME_ACCESS ))
Alexandre Julliard03468f71998-02-15 19:40:49 +0000574 {
575 CloseHandle(hIn);
576 CloseHandle(hOut);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000577 return FALSE;
578 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000579
Alexandre Julliard03468f71998-02-15 19:40:49 +0000580 /* NT resets the STD_*_HANDLEs on console alloc */
581 SetStdHandle(STD_INPUT_HANDLE, hIn);
582 SetStdHandle(STD_OUTPUT_HANDLE, hOut);
583 SetStdHandle(STD_ERROR_HANDLE, hErr);
584
585 SetLastError(ERROR_SUCCESS);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000586 SetConsoleTitleA("Wine Console");
Alexandre Julliard03468f71998-02-15 19:40:49 +0000587 return TRUE;
588}
589
590
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000591/******************************************************************************
592 * GetConsoleCP [KERNEL32.295] Returns the OEM code page for the console
593 *
594 * RETURNS
595 * Code page code
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000596 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000597UINT WINAPI GetConsoleCP(VOID)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000598{
599 return GetACP();
600}
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000601
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000602
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000603/***********************************************************************
604 * GetConsoleOutputCP (KERNEL32.189)
605 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000606UINT WINAPI GetConsoleOutputCP(VOID)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000607{
608 return GetConsoleCP();
609}
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000610
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000611/***********************************************************************
612 * GetConsoleMode (KERNEL32.188)
613 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000614BOOL WINAPI GetConsoleMode(HANDLE hcon,LPDWORD mode)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000615{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000616 struct get_console_mode_request req;
617 struct get_console_mode_reply reply;
Marcus Meissner537772a1998-12-09 16:37:04 +0000618
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000619 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000620 CLIENT_SendRequest( REQ_GET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
621 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
622 *mode = reply.mode;
Marcus Meissner537772a1998-12-09 16:37:04 +0000623 return TRUE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000624}
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000625
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000626
627/******************************************************************************
628 * SetConsoleMode [KERNEL32.628] Sets input mode of console's input buffer
629 *
630 * PARAMS
631 * hcon [I] Handle to console input or screen buffer
632 * mode [I] Input or output mode to set
633 *
634 * RETURNS
635 * Success: TRUE
636 * Failure: FALSE
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000637 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000638BOOL WINAPI SetConsoleMode( HANDLE hcon, DWORD mode )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000639{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000640 struct set_console_mode_request req;
Marcus Meissner537772a1998-12-09 16:37:04 +0000641
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000642 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000643 req.mode = mode;
644 CLIENT_SendRequest( REQ_SET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
645 return !CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000646}
647
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000648
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000649/***********************************************************************
650 * GetConsoleTitleA (KERNEL32.191)
651 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000652DWORD WINAPI GetConsoleTitleA(LPSTR title,DWORD size)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000653{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000654 struct get_console_info_request req;
655 struct get_console_info_reply reply;
656 int len;
657 DWORD ret = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000658 HANDLE hcon;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000659
Alexandre Julliarda3960291999-02-26 11:11:13 +0000660 if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ, 0, NULL,
661 OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000662 return 0;
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000663 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000664 CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
665 if (!CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), title, size ))
666 {
667 if (len > sizeof(reply)+size) title[size-1] = 0;
668 ret = strlen(title);
669 }
670 CloseHandle( hcon );
671 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000672}
673
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000674
675/******************************************************************************
676 * GetConsoleTitle32W [KERNEL32.192] Retrieves title string for console
677 *
678 * PARAMS
679 * title [O] Address of buffer for title
680 * size [I] Size of buffer
681 *
682 * RETURNS
683 * Success: Length of string copied
684 * Failure: 0
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000685 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000686DWORD WINAPI GetConsoleTitleW( LPWSTR title, DWORD size )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000687{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000688 char *tmp;
689 DWORD ret;
690
691 if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size ))) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000692 ret = GetConsoleTitleA( tmp, size );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000693 lstrcpyAtoW( title, tmp );
694 HeapFree( GetProcessHeap(), 0, tmp );
695 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000696}
697
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000698
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000699/***********************************************************************
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000700 * WriteConsoleA (KERNEL32.729)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000701 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000702BOOL WINAPI WriteConsoleA( HANDLE hConsoleOutput,
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000703 LPCVOID lpBuffer,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000704 DWORD nNumberOfCharsToWrite,
705 LPDWORD lpNumberOfCharsWritten,
706 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000707{
Alexandre Julliard03468f71998-02-15 19:40:49 +0000708 /* FIXME: should I check if this is a console handle? */
709 return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
710 lpNumberOfCharsWritten, NULL);
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000711}
712
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000713
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000714#define CADD(c) \
715 if (bufused==curbufsize-1) \
716 buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\
717 buffer[bufused++]=c;
718#define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}}
719
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000720/***********************************************************************
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000721 * WriteConsoleOutputA (KERNEL32.732)
722 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000723BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput,
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000724 LPCHAR_INFO lpBuffer,
725 COORD dwBufferSize,
726 COORD dwBufferCoord,
727 LPSMALL_RECT lpWriteRegion)
728{
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000729 int i,j,off=0,lastattr=-1;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000730 char sbuf[20],*buffer=NULL;
731 int bufused=0,curbufsize = 100;
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000732 DWORD res;
Marcus Meissner537772a1998-12-09 16:37:04 +0000733 const int colormap[8] = {
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000734 0,4,2,6,
735 1,5,3,7,
736 };
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000737 CONSOLE_make_complex(hConsoleOutput);
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000738 buffer = HeapAlloc(GetProcessHeap(),0,100);;
739 curbufsize = 100;
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000740
741 TRACE(console,"wr: top = %d, bottom=%d, left=%d,right=%d\n",
742 lpWriteRegion->Top,
743 lpWriteRegion->Bottom,
744 lpWriteRegion->Left,
745 lpWriteRegion->Right
746 );
747
748 for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) {
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000749 sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1);
750 SADD(sbuf);
751 for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) {
752 if (lastattr!=lpBuffer[off].Attributes) {
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000753 lastattr = lpBuffer[off].Attributes;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000754 sprintf(sbuf,"%c[0;%s3%d;4%dm",
Marcus Meissner537772a1998-12-09 16:37:04 +0000755 27,
756 (lastattr & FOREGROUND_INTENSITY)?"1;":"",
757 colormap[lastattr&7],
758 colormap[(lastattr&0x70)>>4]
759 );
760 /* FIXME: BACKGROUND_INTENSITY */
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000761 SADD(sbuf);
762 }
763 CADD(lpBuffer[off].Char.AsciiChar);
764 off++;
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000765 }
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000766 }
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000767 sprintf(sbuf,"%c[0m",27);SADD(sbuf);
768 WriteFile(hConsoleOutput,buffer,bufused,&res,NULL);
769 HeapFree(GetProcessHeap(),0,buffer);
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000770 return TRUE;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000771}
772
773/***********************************************************************
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000774 * WriteConsoleW (KERNEL32.577)
775 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000776BOOL WINAPI WriteConsoleW( HANDLE hConsoleOutput,
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000777 LPCVOID lpBuffer,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000778 DWORD nNumberOfCharsToWrite,
779 LPDWORD lpNumberOfCharsWritten,
780 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000781{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000782 BOOL ret;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000783 LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite );
784
785 lstrcpynWtoA( xstring, lpBuffer,nNumberOfCharsToWrite);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000786
787 /* FIXME: should I check if this is a console handle? */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000788 ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite,
Alexandre Julliard03468f71998-02-15 19:40:49 +0000789 lpNumberOfCharsWritten, NULL);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000790 HeapFree( GetProcessHeap(), 0, xstring );
791 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000792}
793
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000794
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000795/***********************************************************************
796 * ReadConsoleA (KERNEL32.419)
797 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000798BOOL WINAPI ReadConsoleA( HANDLE hConsoleInput,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000799 LPVOID lpBuffer,
800 DWORD nNumberOfCharsToRead,
801 LPDWORD lpNumberOfCharsRead,
802 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000803{
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000804 int charsread = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +0000805 LPSTR xbuf = (LPSTR)lpBuffer;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000806 struct read_console_input_request req;
807 INPUT_RECORD ir;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000808
Marcus Meissner537772a1998-12-09 16:37:04 +0000809 TRACE(console,"(%d,%p,%ld,%p,%p)\n",
810 hConsoleInput,lpBuffer,nNumberOfCharsToRead,
811 lpNumberOfCharsRead,lpReserved
812 );
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000813
814 CONSOLE_get_input(hConsoleInput,FALSE);
815
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000816 req.handle = hConsoleInput;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000817 req.count = 1;
818 req.flush = 1;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000819
Alexandre Julliard638f1691999-01-17 16:32:32 +0000820 /* FIXME: should we read at least 1 char? The SDK does not say */
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000821 while (charsread<nNumberOfCharsToRead)
822 {
823 int len;
824
825 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
826 if (CLIENT_WaitReply( &len, NULL, 1, &ir, sizeof(ir) ))
827 return FALSE;
828 assert( !(len % sizeof(ir)) );
829 if (!len) break;
830 if (!ir.Event.KeyEvent.bKeyDown)
Marcus Meissner537772a1998-12-09 16:37:04 +0000831 continue;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000832 if (ir.EventType != KEY_EVENT)
Marcus Meissner537772a1998-12-09 16:37:04 +0000833 continue;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000834 *xbuf++ = ir.Event.KeyEvent.uChar.AsciiChar;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000835 charsread++;
Marcus Meissner537772a1998-12-09 16:37:04 +0000836 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000837 if (lpNumberOfCharsRead)
838 *lpNumberOfCharsRead = charsread;
Marcus Meissner537772a1998-12-09 16:37:04 +0000839 return TRUE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000840}
841
842/***********************************************************************
843 * ReadConsoleW (KERNEL32.427)
844 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000845BOOL WINAPI ReadConsoleW( HANDLE hConsoleInput,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000846 LPVOID lpBuffer,
847 DWORD nNumberOfCharsToRead,
848 LPDWORD lpNumberOfCharsRead,
849 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000850{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000851 BOOL ret;
Marcus Meissner537772a1998-12-09 16:37:04 +0000852 LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000853
Alexandre Julliarda3960291999-02-26 11:11:13 +0000854 ret = ReadConsoleA(
Marcus Meissner537772a1998-12-09 16:37:04 +0000855 hConsoleInput,
856 buf,
857 nNumberOfCharsToRead,
858 lpNumberOfCharsRead,
859 lpReserved
860 );
861 if (ret)
862 lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
863 HeapFree( GetProcessHeap(), 0, buf );
864 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000865}
866
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000867
868/******************************************************************************
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +0000869 * ReadConsoleInput32A [KERNEL32.569] Reads data from a console
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000870 *
871 * PARAMS
872 * hConsoleInput [I] Handle to console input buffer
873 * lpBuffer [O] Address of buffer for read data
874 * nLength [I] Number of records to read
875 * lpNumberOfEventsRead [O] Address of number of records read
876 *
877 * RETURNS
878 * Success: TRUE
879 * Failure: FALSE
880 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000881BOOL WINAPI ReadConsoleInputA(HANDLE hConsoleInput,
Marcus Meissner537772a1998-12-09 16:37:04 +0000882 LPINPUT_RECORD lpBuffer,
883 DWORD nLength, LPDWORD lpNumberOfEventsRead)
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000884{
Alexandre Julliard4b461121999-01-31 19:04:30 +0000885 struct read_console_input_request req;
886 int len;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000887
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000888 req.handle = hConsoleInput;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000889 req.count = nLength;
890 req.flush = 1;
Alexandre Julliard638f1691999-01-17 16:32:32 +0000891
Alexandre Julliard4b461121999-01-31 19:04:30 +0000892 /* loop until we get at least one event */
893 for (;;)
894 {
895 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
896 if (CLIENT_WaitReply( &len, NULL, 1, lpBuffer, nLength * sizeof(*lpBuffer) ))
897 return FALSE;
898 assert( !(len % sizeof(INPUT_RECORD)) );
899 if (len) break;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000900 CONSOLE_get_input(hConsoleInput,TRUE);
901 /*WaitForSingleObject( hConsoleInput, INFINITE32 );*/
Marcus Meissner537772a1998-12-09 16:37:04 +0000902 }
Alexandre Julliard4b461121999-01-31 19:04:30 +0000903 if (lpNumberOfEventsRead) *lpNumberOfEventsRead = len / sizeof(INPUT_RECORD);
Marcus Meissner537772a1998-12-09 16:37:04 +0000904 return TRUE;
905}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000906
Alexandre Julliard4b461121999-01-31 19:04:30 +0000907
908/***********************************************************************
909 * ReadConsoleInput32W (KERNEL32.570)
910 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000911BOOL WINAPI ReadConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000912 DWORD count, LPDWORD read )
913{
914 /* FIXME: Fix this if we get UNICODE input. */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000915 return ReadConsoleInputA( handle, buffer, count, read );
Alexandre Julliard4b461121999-01-31 19:04:30 +0000916}
917
918
919/***********************************************************************
920 * FlushConsoleInputBuffer (KERNEL32.132)
921 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000922BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
Alexandre Julliard4b461121999-01-31 19:04:30 +0000923{
924 struct read_console_input_request req;
925 int len;
926
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000927 req.handle = handle;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000928 req.count = -1; /* get all records */
929 req.flush = 1;
930 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
931 return !CLIENT_WaitReply( &len, NULL, 0 );
932}
933
934
935/***********************************************************************
936 * PeekConsoleInputA (KERNEL32.550)
937 *
938 * Gets 'count' first events (or less) from input queue.
939 *
940 * Does not need a complex console.
941 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000942BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000943 DWORD count, LPDWORD read )
944{
945 struct read_console_input_request req;
946 int len;
947
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000948 CONSOLE_get_input(handle,FALSE);
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000949 req.handle = handle;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000950 req.count = count;
951 req.flush = 0;
952
953 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
954 if (CLIENT_WaitReply( &len, NULL, 1, buffer, count * sizeof(*buffer) ))
955 return FALSE;
956 assert( !(len % sizeof(INPUT_RECORD)) );
957 if (read) *read = len / sizeof(INPUT_RECORD);
958 return TRUE;
959}
960
961
962/***********************************************************************
963 * PeekConsoleInputW (KERNEL32.551)
964 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000965BOOL WINAPI PeekConsoleInputW(HANDLE hConsoleInput,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000966 LPINPUT_RECORD pirBuffer,
967 DWORD cInRecords,
968 LPDWORD lpcRead)
969{
970 /* FIXME: Hmm. Fix this if we get UNICODE input. */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000971 return PeekConsoleInputA(hConsoleInput,pirBuffer,cInRecords,lpcRead);
Alexandre Julliard4b461121999-01-31 19:04:30 +0000972}
973
974
975/******************************************************************************
976 * WriteConsoleInput32A [KERNEL32.730] Write data to a console input buffer
977 *
978 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000979BOOL WINAPI WriteConsoleInputA( HANDLE handle, INPUT_RECORD *buffer,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000980 DWORD count, LPDWORD written )
981{
982 struct write_console_input_request req;
983 struct write_console_input_reply reply;
984
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000985 req.handle = handle;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000986 req.count = count;
987 CLIENT_SendRequest( REQ_WRITE_CONSOLE_INPUT, -1, 2, &req, sizeof(req),
988 buffer, count * sizeof(*buffer) );
989 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
990 if (written) *written = reply.written;
991 return TRUE;
992}
993
994
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000995/***********************************************************************
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000996 * SetConsoleTitle32A (KERNEL32.476)
Marcus Meissner537772a1998-12-09 16:37:04 +0000997 *
998 * Sets the console title.
999 *
1000 * We do not necessarily need to create a complex console for that,
1001 * but should remember the title and set it on creation of the latter.
1002 * (not fixed at this time).
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001003 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001004BOOL WINAPI SetConsoleTitleA(LPCSTR title)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001005{
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001006 struct set_console_info_request req;
1007 struct get_console_info_reply info;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001008 HANDLE hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001009 DWORD written;
1010
Alexandre Julliarda3960291999-02-26 11:11:13 +00001011 if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
1012 OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001013 return FALSE;
Alexandre Julliard96c08d81999-02-28 13:27:56 +00001014 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001015 req.mask = SET_CONSOLE_INFO_TITLE;
1016 CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 2, &req, sizeof(req),
1017 title, strlen(title)+1 );
1018 if (CLIENT_WaitReply( NULL, NULL, 0 )) goto error;
1019 if (CONSOLE_GetInfo( hcon, &info ) && info.pid)
1020 {
1021 /* only set title for complex console (own xterm) */
1022 WriteFile( hcon, "\033]2;", 4, &written, NULL );
1023 WriteFile( hcon, title, strlen(title), &written, NULL );
1024 WriteFile( hcon, "\a", 1, &written, NULL );
1025 }
Alexandre Julliard96c08d81999-02-28 13:27:56 +00001026 CloseHandle( hcon );
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001027 return TRUE;
1028 error:
1029 CloseHandle( hcon );
1030 return FALSE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001031}
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001032
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001033
1034/******************************************************************************
1035 * SetConsoleTitle32W [KERNEL32.477] Sets title bar string for console
1036 *
1037 * PARAMS
1038 * title [I] Address of new title
1039 *
1040 * NOTES
1041 * This should not be calling the A version
1042 *
1043 * RETURNS
1044 * Success: TRUE
1045 * Failure: FALSE
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001046 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001047BOOL WINAPI SetConsoleTitleW( LPCWSTR title )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001048{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001049 BOOL ret;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001050
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001051 LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001052 ret = SetConsoleTitleA(titleA);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001053 HeapFree( GetProcessHeap(), 0, titleA );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001054 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001055}
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001056
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001057/******************************************************************************
1058 * SetConsoleCursorPosition [KERNEL32.627]
1059 * Sets the cursor position in console
1060 *
1061 * PARAMS
1062 * hConsoleOutput [I] Handle of console screen buffer
1063 * dwCursorPosition [I] New cursor position coordinates
1064 *
1065 * RETURNS STD
1066 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001067BOOL WINAPI SetConsoleCursorPosition( HANDLE hcon, COORD pos )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001068{
Marcus Meissner537772a1998-12-09 16:37:04 +00001069 char xbuf[20];
1070 DWORD xlen;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001071
Marcus Meissner03f10f41999-01-26 10:08:36 +00001072 /* make console complex only if we change lines, not just in the line */
1073 if (pos.y)
1074 CONSOLE_make_complex(hcon);
1075
Marcus Meissner537772a1998-12-09 16:37:04 +00001076 TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y );
1077 /* x are columns, y rows */
Marcus Meissner03f10f41999-01-26 10:08:36 +00001078 if (pos.y)
1079 /* full screen cursor absolute positioning */
1080 sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1);
1081 else
1082 /* relative cursor positioning in line (\r to go to 0) */
1083 sprintf(xbuf,"\r%c[%dC", 0x1B, pos.x);
Marcus Meissner537772a1998-12-09 16:37:04 +00001084 /* FIXME: store internal if we start using own console buffers */
1085 WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL);
Marcus Meissner537772a1998-12-09 16:37:04 +00001086 return TRUE;
1087}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001088
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001089/***********************************************************************
1090 * GetNumberOfConsoleInputEvents (KERNEL32.246)
1091 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001092BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hcon,LPDWORD nrofevents)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001093{
Marcus Meissnera2ca7b91999-02-05 09:32:39 +00001094 CONSOLE_get_input(hcon,FALSE);
1095 *nrofevents = 1; /* UMM */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001096 return TRUE;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001097}
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001098
1099/***********************************************************************
1100 * GetNumberOfConsoleMouseButtons (KERNEL32.358)
1101 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001102BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001103{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001104 FIXME(console,"(%p): stub\n", nrofbuttons);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001105 *nrofbuttons = 2;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001106 return TRUE;
1107}
1108
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001109/******************************************************************************
1110 * GetConsoleCursorInfo32 [KERNEL32.296] Gets size and visibility of console
1111 *
1112 * PARAMS
1113 * hcon [I] Handle to console screen buffer
1114 * cinfo [O] Address of cursor information
1115 *
1116 * RETURNS
1117 * Success: TRUE
1118 * Failure: FALSE
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001119 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001120BOOL WINAPI GetConsoleCursorInfo( HANDLE hcon,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001121 LPCONSOLE_CURSOR_INFO cinfo )
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001122{
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001123 struct get_console_info_reply reply;
Marcus Meissner537772a1998-12-09 16:37:04 +00001124
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001125 if (!CONSOLE_GetInfo( hcon, &reply )) return FALSE;
1126 if (cinfo)
1127 {
1128 cinfo->dwSize = reply.cursor_size;
1129 cinfo->bVisible = reply.cursor_visible;
Marcus Meissner537772a1998-12-09 16:37:04 +00001130 }
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001131 return TRUE;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001132}
1133
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001134
1135/******************************************************************************
1136 * SetConsoleCursorInfo32 [KERNEL32.626] Sets size and visibility of cursor
1137 *
1138 * RETURNS
1139 * Success: TRUE
1140 * Failure: FALSE
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001141 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001142BOOL WINAPI SetConsoleCursorInfo(
1143 HANDLE hcon, /* [in] Handle to console screen buffer */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001144 LPCONSOLE_CURSOR_INFO cinfo) /* [in] Address of cursor information */
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001145{
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001146 struct set_console_info_request req;
Marcus Meissner537772a1998-12-09 16:37:04 +00001147 char buf[8];
1148 DWORD xlen;
Marcus Meissner537772a1998-12-09 16:37:04 +00001149
Alexandre Julliard96c08d81999-02-28 13:27:56 +00001150 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001151 CONSOLE_make_complex(hcon);
1152 sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l');
Marcus Meissner537772a1998-12-09 16:37:04 +00001153 WriteFile(hcon,buf,strlen(buf),&xlen,NULL);
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001154
1155 req.cursor_size = cinfo->dwSize;
1156 req.cursor_visible = cinfo->bVisible;
1157 req.mask = SET_CONSOLE_INFO_CURSOR;
1158 CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
1159 return !CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001160}
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001161
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001162
1163/******************************************************************************
1164 * SetConsoleWindowInfo [KERNEL32.634] Sets size and position of console
1165 *
1166 * RETURNS
1167 * Success: TRUE
1168 * Failure: FALSE
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001169 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001170BOOL WINAPI SetConsoleWindowInfo(
1171 HANDLE hcon, /* [in] Handle to console screen buffer */
1172 BOOL bAbsolute, /* [in] Coordinate type flag */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001173 LPSMALL_RECT window) /* [in] Address of new window rectangle */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001174{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001175 FIXME(console, "(%x,%d,%p): stub\n", hcon, bAbsolute, window);
1176 return TRUE;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001177}
1178
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001179
1180/******************************************************************************
1181 * SetConsoleTextAttribute32 [KERNEL32.631] Sets colors for text
1182 *
1183 * Sets the foreground and background color attributes of characters
1184 * written to the screen buffer.
1185 *
1186 * RETURNS
1187 * Success: TRUE
1188 * Failure: FALSE
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001189 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001190BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttr)
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001191{
Marcus Meissner537772a1998-12-09 16:37:04 +00001192 const int colormap[8] = {
1193 0,4,2,6,
1194 1,5,3,7,
1195 };
1196 DWORD xlen;
1197 char buffer[20];
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001198
Marcus Meissner8bc54b61998-12-14 14:48:09 +00001199 TRACE(console,"(%d,%d)\n",hConsoleOutput,wAttr);
Marcus Meissner537772a1998-12-09 16:37:04 +00001200 sprintf(buffer,"%c[0;%s3%d;4%dm",
1201 27,
1202 (wAttr & FOREGROUND_INTENSITY)?"1;":"",
1203 colormap[wAttr&7],
1204 colormap[(wAttr&0x70)>>4]
1205 );
1206 WriteFile(hConsoleOutput,buffer,strlen(buffer),&xlen,NULL);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001207 return TRUE;
1208}
1209
1210
1211/******************************************************************************
1212 * SetConsoleScreenBufferSize [KERNEL32.630] Changes size of console
1213 *
1214 * PARAMS
1215 * hConsoleOutput [I] Handle to console screen buffer
1216 * dwSize [I] New size in character rows and cols
1217 *
1218 * RETURNS
1219 * Success: TRUE
1220 * Failure: FALSE
1221 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001222BOOL WINAPI SetConsoleScreenBufferSize( HANDLE hConsoleOutput,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001223 COORD dwSize )
1224{
1225 FIXME(console, "(%d,%dx%d): stub\n",hConsoleOutput,dwSize.x,dwSize.y);
1226 return TRUE;
1227}
1228
1229
1230/******************************************************************************
1231 * FillConsoleOutputCharacterA [KERNEL32.242]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001232 *
1233 * PARAMS
1234 * hConsoleOutput [I] Handle to screen buffer
1235 * cCharacter [I] Character to write
1236 * nLength [I] Number of cells to write to
1237 * dwCoord [I] Coords of first cell
1238 * lpNumCharsWritten [O] Pointer to number of cells written
1239 *
1240 * RETURNS
1241 * Success: TRUE
1242 * Failure: FALSE
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001243 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001244BOOL WINAPI FillConsoleOutputCharacterA(
1245 HANDLE hConsoleOutput,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001246 BYTE cCharacter,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001247 DWORD nLength,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001248 COORD dwCoord,
1249 LPDWORD lpNumCharsWritten)
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001250{
Marcus Meissner537772a1998-12-09 16:37:04 +00001251 long count;
1252 DWORD xlen;
1253
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001254 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1255 for(count=0;count<nLength;count++)
Marcus Meissner537772a1998-12-09 16:37:04 +00001256 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001257 *lpNumCharsWritten = nLength;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001258 return TRUE;
1259}
1260
1261
1262/******************************************************************************
1263 * FillConsoleOutputCharacterW [KERNEL32.243] Writes characters to console
1264 *
1265 * PARAMS
1266 * hConsoleOutput [I] Handle to screen buffer
1267 * cCharacter [I] Character to write
1268 * nLength [I] Number of cells to write to
1269 * dwCoord [I] Coords of first cell
1270 * lpNumCharsWritten [O] Pointer to number of cells written
1271 *
1272 * RETURNS
1273 * Success: TRUE
1274 * Failure: FALSE
1275 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001276BOOL WINAPI FillConsoleOutputCharacterW(HANDLE hConsoleOutput,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001277 WCHAR cCharacter,
1278 DWORD nLength,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001279 COORD dwCoord,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001280 LPDWORD lpNumCharsWritten)
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001281{
Marcus Meissner537772a1998-12-09 16:37:04 +00001282 long count;
1283 DWORD xlen;
1284
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001285 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
Marcus Meissner537772a1998-12-09 16:37:04 +00001286 /* FIXME: not quite correct ... but the lower part of UNICODE char comes
1287 * first
1288 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001289 for(count=0;count<nLength;count++)
Marcus Meissner537772a1998-12-09 16:37:04 +00001290 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001291 *lpNumCharsWritten = nLength;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001292 return TRUE;
1293}
1294
1295
1296/******************************************************************************
1297 * FillConsoleOutputAttribute [KERNEL32.241] Sets attributes for console
1298 *
1299 * PARAMS
1300 * hConsoleOutput [I] Handle to screen buffer
1301 * wAttribute [I] Color attribute to write
1302 * nLength [I] Number of cells to write to
1303 * dwCoord [I] Coords of first cell
1304 * lpNumAttrsWritten [O] Pointer to number of cells written
1305 *
1306 * RETURNS
1307 * Success: TRUE
1308 * Failure: FALSE
1309 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001310BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001311 WORD wAttribute, DWORD nLength, COORD dwCoord,
1312 LPDWORD lpNumAttrsWritten)
1313{
1314 FIXME(console, "(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1315 wAttribute,nLength,dwCoord.x,dwCoord.y,lpNumAttrsWritten);
1316 *lpNumAttrsWritten = nLength;
1317 return TRUE;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001318}
1319
Alexandre Julliarda845b881998-06-01 10:44:35 +00001320/******************************************************************************
1321 * ReadConsoleOutputCharacter32A [KERNEL32.573]
1322 *
1323 * BUGS
1324 * Unimplemented
1325 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001326BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput,
Alexandre Julliarda845b881998-06-01 10:44:35 +00001327 LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1328{
1329 FIXME(console, "(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1330 dword,coord.x,coord.y,lpdword);
1331 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1332 return FALSE;
1333}
Alexandre Julliard642d3131998-07-12 19:29:36 +00001334
1335
1336/******************************************************************************
1337 * ScrollConsoleScreenBuffer [KERNEL32.612]
1338 *
1339 * BUGS
1340 * Unimplemented
1341 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001342BOOL WINAPI ScrollConsoleScreenBuffer( HANDLE hConsoleOutput,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001343 LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1344 COORD dwDestOrigin, LPCHAR_INFO lpFill)
1345{
1346 FIXME(console, "(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1347 lpClipRect,dwDestOrigin.x,dwDestOrigin.y,lpFill);
1348 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1349 return FALSE;
1350}