blob: 4f66be47808330fc91bc4edcc7bb93b18cb0ea5d [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>
David Luyercb40df21999-03-25 15:52:09 +000025#include <string.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
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000051DEFAULT_DEBUG_CHANNEL(console)
52
Alexandre Julliard03468f71998-02-15 19:40:49 +000053
Zygo Blaxelledc858c1999-02-09 14:14:16 +000054/* FIXME: Should be in an internal header file. OK, so which one?
55 Used by CONSOLE_makecomplex. */
56FILE *wine_openpty(int *master, int *slave, char *name,
57 struct termios *term, struct winsize *winsize);
58
Alexandre Julliard62a8b431999-01-19 17:48:23 +000059/****************************************************************************
60 * CONSOLE_GetInfo
61 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000062static BOOL CONSOLE_GetInfo( HANDLE handle, struct get_console_info_reply *reply )
Alexandre Julliard62a8b431999-01-19 17:48:23 +000063{
64 struct get_console_info_request req;
65
Alexandre Julliard96c08d81999-02-28 13:27:56 +000066 req.handle = handle;
Alexandre Julliard62a8b431999-01-19 17:48:23 +000067 CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
68 return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
69}
70
Marcus Meissner537772a1998-12-09 16:37:04 +000071/****************************************************************************
72 * XTERM_string_to_IR [internal]
73 *
74 * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the
75 * queue. Does translation of vt100 style function keys and xterm-mouse clicks.
76 */
77static void
Alexandre Julliarda3960291999-02-26 11:11:13 +000078CONSOLE_string_to_IR( HANDLE hConsoleInput,unsigned char *buf,int len) {
Marcus Meissner537772a1998-12-09 16:37:04 +000079 int j,k;
80 INPUT_RECORD ir;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +000081 DWORD junk;
Marcus Meissner537772a1998-12-09 16:37:04 +000082
83 for (j=0;j<len;j++) {
84 unsigned char inchar = buf[j];
85
86 if (inchar!=27) { /* no escape -> 'normal' keyboard event */
87 ir.EventType = 1; /* Key_event */
88
Marcus Meissner8bc54b61998-12-14 14:48:09 +000089 ir.Event.KeyEvent.bKeyDown = 1;
90 ir.Event.KeyEvent.wRepeatCount = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +000091
Marcus Meissner8bc54b61998-12-14 14:48:09 +000092 ir.Event.KeyEvent.dwControlKeyState = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +000093 if (inchar & 0x80) {
94 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
95 inchar &= ~0x80;
96 }
Marcus Meissner8bc54b61998-12-14 14:48:09 +000097 ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(inchar);
98 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100)
Marcus Meissner537772a1998-12-09 16:37:04 +000099 ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000100 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200)
101 ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED;
102 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400)
103 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
104 ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
105 ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff,
106 0 /* VirtualKeyCodes to ScanCode */
107 );
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000108 ir.Event.KeyEvent.uChar.AsciiChar = inchar;
109
110 if (inchar==127) { /* backspace */
111 ir.Event.KeyEvent.uChar.AsciiChar = '\b'; /* FIXME: hmm */
112 ir.Event.KeyEvent.wVirtualScanCode = 0x0e;
113 ir.Event.KeyEvent.wVirtualKeyCode = VK_BACK;
Marcus Meissner537772a1998-12-09 16:37:04 +0000114 } else {
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000115 if (inchar=='\n') {
116 ir.Event.KeyEvent.uChar.AsciiChar = '\r';
117 ir.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
118 ir.Event.KeyEvent.wVirtualScanCode = 0x1c;
119 } else {
120 if (inchar<' ') {
121 /* FIXME: find good values for ^X */
122 ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;
123 ir.Event.KeyEvent.wVirtualScanCode = 0xbeef;
124 }
125 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000126 }
127
Alexandre Julliarda3960291999-02-26 11:11:13 +0000128 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000129 ir.Event.KeyEvent.bKeyDown = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000130 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000131 continue;
132 }
133 /* inchar is ESC */
134 if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */
135 ir.EventType = 1; /* Key_event */
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000136 ir.Event.KeyEvent.bKeyDown = 1;
137 ir.Event.KeyEvent.wRepeatCount = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +0000138
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000139 ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(27);
140 ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
141 ir.Event.KeyEvent.wVirtualKeyCode,0
142 );
Marcus Meissner537772a1998-12-09 16:37:04 +0000143 ir.Event.KeyEvent.dwControlKeyState = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +0000144 ir.Event.KeyEvent.uChar.AsciiChar = 27;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000145 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000146 ir.Event.KeyEvent.bKeyDown = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000147 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000148 continue;
149 }
150 for (k=j;k<len;k++) {
151 if (((buf[k]>='A') && (buf[k]<='Z')) ||
152 ((buf[k]>='a') && (buf[k]<='z')) ||
153 (buf[k]=='~')
154 )
155 break;
156 }
157 if (k<len) {
158 int subid,scancode=0;
159
160 ir.EventType = 1; /* Key_event */
161 ir.Event.KeyEvent.bKeyDown = 1;
162 ir.Event.KeyEvent.wRepeatCount = 0;
163 ir.Event.KeyEvent.dwControlKeyState = 0;
164
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000165 ir.Event.KeyEvent.wVirtualKeyCode = 0xad; /* FIXME */
166 ir.Event.KeyEvent.wVirtualScanCode = 0xad; /* FIXME */
Marcus Meissner537772a1998-12-09 16:37:04 +0000167 ir.Event.KeyEvent.uChar.AsciiChar = 0;
168
169 switch (buf[k]) {
170 case '~':
171 sscanf(&buf[j+2],"%d",&subid);
172 switch (subid) {
173 case 2:/*INS */scancode = 0xe052;break;
174 case 3:/*DEL */scancode = 0xe053;break;
175 case 6:/*PGDW*/scancode = 0xe051;break;
176 case 5:/*PGUP*/scancode = 0xe049;break;
177 case 11:/*F1 */scancode = 0x003b;break;
178 case 12:/*F2 */scancode = 0x003c;break;
179 case 13:/*F3 */scancode = 0x003d;break;
180 case 14:/*F4 */scancode = 0x003e;break;
181 case 15:/*F5 */scancode = 0x003f;break;
182 case 17:/*F6 */scancode = 0x0040;break;
183 case 18:/*F7 */scancode = 0x0041;break;
184 case 19:/*F8 */scancode = 0x0042;break;
185 case 20:/*F9 */scancode = 0x0043;break;
186 case 21:/*F10 */scancode = 0x0044;break;
187 case 23:/*F11 */scancode = 0x00d9;break;
188 case 24:/*F12 */scancode = 0x00da;break;
189 /* FIXME: Shift-Fx */
190 default:
191 FIXME(console,"parse ESC[%d~\n",subid);
192 break;
193 }
194 break;
195 case 'A': /* Cursor Up */scancode = 0xe048;break;
196 case 'B': /* Cursor Down */scancode = 0xe050;break;
197 case 'D': /* Cursor Left */scancode = 0xe04b;break;
198 case 'C': /* Cursor Right */scancode = 0xe04d;break;
199 case 'F': /* End */scancode = 0xe04f;break;
200 case 'H': /* Home */scancode = 0xe047;break;
201 case 'M':
202 /* Mouse Button Press (ESCM<button+'!'><x+'!'><y+'!'>) or
203 * Release (ESCM#<x+'!'><y+'!'>
204 */
205 if (k<len-3) {
206 ir.EventType = MOUSE_EVENT;
207 ir.Event.MouseEvent.dwMousePosition.x = buf[k+2]-'!';
208 ir.Event.MouseEvent.dwMousePosition.y = buf[k+3]-'!';
209 if (buf[k+1]=='#')
210 ir.Event.MouseEvent.dwButtonState = 0;
211 else
212 ir.Event.MouseEvent.dwButtonState = 1<<(buf[k+1]-' ');
213 ir.Event.MouseEvent.dwEventFlags = 0; /* FIXME */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000214 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk));
Marcus Meissner537772a1998-12-09 16:37:04 +0000215 j=k+3;
216 }
217 break;
218
219 }
220 if (scancode) {
221 ir.Event.KeyEvent.wVirtualScanCode = scancode;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000222 ir.Event.KeyEvent.wVirtualKeyCode = MapVirtualKey16(scancode,1);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000223 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000224 ir.Event.KeyEvent.bKeyDown = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000225 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
Marcus Meissner537772a1998-12-09 16:37:04 +0000226 j=k;
227 continue;
228 }
229 }
230 }
231}
Alexandre Julliard55443871998-12-31 15:52:06 +0000232
Marcus Meissner537772a1998-12-09 16:37:04 +0000233/****************************************************************************
234 * CONSOLE_get_input (internal)
235 *
236 * Reads (nonblocking) as much input events as possible and stores them
237 * in an internal queue.
Marcus Meissner537772a1998-12-09 16:37:04 +0000238 */
239static void
Alexandre Julliarda3960291999-02-26 11:11:13 +0000240CONSOLE_get_input( HANDLE handle, BOOL blockwait )
Alexandre Julliard55443871998-12-31 15:52:06 +0000241{
Marcus Meissner537772a1998-12-09 16:37:04 +0000242 char *buf = HeapAlloc(GetProcessHeap(),0,1);
243 int len = 0;
244
Alexandre Julliard55443871998-12-31 15:52:06 +0000245 while (1)
246 {
247 DWORD res;
248 char inchar;
Marcus Meissnerba8e2a31999-01-03 16:18:33 +0000249 if (WaitForSingleObject( handle, 0 )) break;
Alexandre Julliard55443871998-12-31 15:52:06 +0000250 if (!ReadFile( handle, &inchar, 1, &res, NULL )) break;
Marcus Meissner03f10f41999-01-26 10:08:36 +0000251 if (!res) /* res 0 but readable means EOF? Hmm. */
252 break;
Marcus Meissner537772a1998-12-09 16:37:04 +0000253 buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1);
254 buf[len++]=inchar;
255 }
Alexandre Julliard55443871998-12-31 15:52:06 +0000256 CONSOLE_string_to_IR(handle,buf,len);
Marcus Meissner537772a1998-12-09 16:37:04 +0000257 HeapFree(GetProcessHeap(),0,buf);
258}
259
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000260/******************************************************************************
261 * SetConsoleCtrlHandler [KERNEL32.459] Adds function to calling process list
262 *
263 * PARAMS
264 * func [I] Address of handler function
265 * add [I] Handler to add or remove
266 *
267 * RETURNS
268 * Success: TRUE
269 * Failure: FALSE
James Sutherland577db371998-11-08 15:09:08 +0000270 *
271 * CHANGED
272 * James Sutherland (JamesSutherland@gmx.de)
273 * Added global variables console_ignore_ctrl_c and handlers[]
274 * Does not yet do any error checking, or set LastError if failed.
275 * This doesn't yet matter, since these handlers are not yet called...!
Alexandre Julliardade697e1995-11-26 13:59:11 +0000276 */
James Sutherland577db371998-11-08 15:09:08 +0000277static unsigned int console_ignore_ctrl_c = 0;
278static 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 +0000279BOOL WINAPI SetConsoleCtrlHandler( HANDLER_ROUTINE *func, BOOL add )
Alexandre Julliardade697e1995-11-26 13:59:11 +0000280{
James Sutherland577db371998-11-08 15:09:08 +0000281 unsigned int alloc_loop = sizeof(handlers)/sizeof(HANDLER_ROUTINE *);
282 unsigned int done = 0;
283 FIXME(console, "(%p,%i) - no error checking or testing yet\n", func, add);
284 if (!func)
285 {
286 console_ignore_ctrl_c = add;
287 return TRUE;
288 }
289 if (add)
290 {
291 for (;alloc_loop--;)
292 if (!handlers[alloc_loop] && !done)
293 {
294 handlers[alloc_loop] = func;
295 done++;
296 }
297 if (!done)
298 FIXME(console, "Out of space on CtrlHandler table\n");
299 return(done);
300 }
301 else
302 {
303 for (;alloc_loop--;)
304 if (handlers[alloc_loop] == func && !done)
305 {
306 handlers[alloc_loop] = 0;
307 done++;
308 }
309 if (!done)
Huw D M Davies7b06d981998-11-14 17:13:51 +0000310 WARN(console, "Attempt to remove non-installed CtrlHandler %p\n",
311 func);
James Sutherland577db371998-11-08 15:09:08 +0000312 return (done);
313 }
314 return (done);
315}
316
317
318/******************************************************************************
319 * GenerateConsoleCtrlEvent [KERNEL32.275] Simulate a CTRL-C or CTRL-BREAK
320 *
321 * PARAMS
322 * dwCtrlEvent [I] Type of event
323 * dwProcessGroupID [I] Process group ID to send event to
324 *
325 * NOTES
326 * Doesn't yet work...!
327 *
328 * RETURNS
329 * Success: True
330 * Failure: False (and *should* [but doesn't] set LastError)
331 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000332BOOL WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent,
James Sutherland577db371998-11-08 15:09:08 +0000333 DWORD dwProcessGroupID )
334{
335 if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
336 {
Marcus Meissner537772a1998-12-09 16:37:04 +0000337 ERR( console, "invalid event %d for PGID %ld\n",
James Sutherland577db371998-11-08 15:09:08 +0000338 (unsigned short)dwCtrlEvent, dwProcessGroupID );
339 return FALSE;
340 }
341 if (dwProcessGroupID == GetCurrentProcessId() )
342 {
343 FIXME( console, "Attempt to send event %d to self - stub\n",
344 (unsigned short)dwCtrlEvent );
345 return FALSE;
346 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000347 FIXME( console,"event %d to external PGID %ld - not implemented yet\n",
James Sutherland577db371998-11-08 15:09:08 +0000348 (unsigned short)dwCtrlEvent, dwProcessGroupID );
349 return FALSE;
Alexandre Julliardade697e1995-11-26 13:59:11 +0000350}
351
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000352
353/******************************************************************************
354 * CreateConsoleScreenBuffer [KERNEL32.151] Creates a console screen buffer
355 *
356 * PARAMS
357 * dwDesiredAccess [I] Access flag
358 * dwShareMode [I] Buffer share mode
359 * sa [I] Security attributes
360 * dwFlags [I] Type of buffer to create
361 * lpScreenBufferData [I] Reserved
362 *
363 * NOTES
364 * Should call SetLastError
365 *
366 * RETURNS
367 * Success: Handle to new console screen buffer
368 * Failure: INVALID_HANDLE_VALUE
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000369 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000370HANDLE WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000371 DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa,
372 DWORD dwFlags, LPVOID lpScreenBufferData )
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000373{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000374 FIXME(console, "(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess,
375 dwShareMode, sa, dwFlags, lpScreenBufferData);
Marcus Meissner537772a1998-12-09 16:37:04 +0000376 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000377 return INVALID_HANDLE_VALUE;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000378}
379
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000380
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000381/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000382 * GetConsoleScreenBufferInfo (KERNEL32.190)
383 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000384BOOL WINAPI GetConsoleScreenBufferInfo( HANDLE hConsoleOutput,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000385 LPCONSOLE_SCREEN_BUFFER_INFO csbi )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000386{
387 csbi->dwSize.x = 80;
388 csbi->dwSize.y = 24;
389 csbi->dwCursorPosition.x = 0;
390 csbi->dwCursorPosition.y = 0;
391 csbi->wAttributes = 0;
392 csbi->srWindow.Left = 0;
393 csbi->srWindow.Right = 79;
394 csbi->srWindow.Top = 0;
395 csbi->srWindow.Bottom = 23;
396 csbi->dwMaximumWindowSize.x = 80;
397 csbi->dwMaximumWindowSize.y = 24;
398 return TRUE;
399}
400
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000401
402/******************************************************************************
403 * SetConsoleActiveScreenBuffer [KERNEL32.623] Sets buffer to current console
404 *
405 * RETURNS
406 * Success: TRUE
407 * Failure: FALSE
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000408 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000409BOOL WINAPI SetConsoleActiveScreenBuffer(
410 HANDLE hConsoleOutput) /* [in] Handle to console screen buffer */
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000411{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000412 FIXME(console, "(%x): stub\n", hConsoleOutput);
413 return FALSE;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000414}
415
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000416
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000417/***********************************************************************
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000418 * GetLargestConsoleWindowSize (KERNEL32.226)
419 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000420DWORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000421{
Marcus Meissner537772a1998-12-09 16:37:04 +0000422 return (DWORD)MAKELONG(80,24);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000423}
424
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000425/***********************************************************************
Alexandre Julliard03468f71998-02-15 19:40:49 +0000426 * FreeConsole (KERNEL32.267)
427 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000428BOOL WINAPI FreeConsole(VOID)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000429{
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000430 CLIENT_SendRequest( REQ_FREE_CONSOLE, -1, 0 );
431 return !CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000432}
433
434
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000435/*************************************************************************
436 * CONSOLE_OpenHandle
437 *
438 * Open a handle to the current process console.
Alexandre Julliard03468f71998-02-15 19:40:49 +0000439 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000440HANDLE CONSOLE_OpenHandle( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES sa )
Alexandre Julliard03468f71998-02-15 19:40:49 +0000441{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000442 struct open_console_request req;
443 struct open_console_reply reply;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000444
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000445 req.output = output;
446 req.access = access;
447 req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
448 CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
Alexandre Julliard3f09ec51999-02-28 19:25:51 +0000449 SetLastError(0);
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000450 CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000451 return reply.handle;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000452}
453
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000454
Marcus Meissner537772a1998-12-09 16:37:04 +0000455/*************************************************************************
456 * CONSOLE_make_complex [internal]
457 *
458 * Turns a CONSOLE kernel object into a complex one.
459 * (switches from output/input using the terminal where WINE was started to
460 * its own xterm).
461 *
462 * This makes simple commandline tools pipeable, while complex commandline
463 * tools work without getting messed up by debugoutput.
464 *
465 * All other functions should work indedependend from this call.
466 *
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000467 * To test for complex console: pid == 0 -> simple, otherwise complex.
Marcus Meissner537772a1998-12-09 16:37:04 +0000468 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000469static BOOL CONSOLE_make_complex(HANDLE handle)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000470{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000471 struct set_console_fd_request req;
472 struct get_console_info_reply info;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000473 struct termios term;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000474 char buf[256];
Alexandre Julliard03468f71998-02-15 19:40:49 +0000475 char c = '\0';
476 int status = 0;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000477 int i,xpid,master,slave;
Marcus Meissner537772a1998-12-09 16:37:04 +0000478 DWORD xlen;
479
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000480 if (!CONSOLE_GetInfo( handle, &info )) return FALSE;
481 if (info.pid) return TRUE; /* already complex */
Marcus Meissner537772a1998-12-09 16:37:04 +0000482
483 MSG("Console: Making console complex (creating an xterm)...\n");
Alexandre Julliard03468f71998-02-15 19:40:49 +0000484
Marcus Meissner03f10f41999-01-26 10:08:36 +0000485 if (tcgetattr(0, &term) < 0) {
486 /* ignore failure, or we can't run from a script */
487 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000488 term.c_lflag = ~(ECHO|ICANON);
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000489
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000490 if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0)
491 return FALSE;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000492
Marcus Meissner537772a1998-12-09 16:37:04 +0000493 if ((xpid=fork()) == 0) {
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000494 tcsetattr(slave, TCSADRAIN, &term);
495 sprintf(buf, "-Sxx%d", master);
Marcus Meissner537772a1998-12-09 16:37:04 +0000496 /* "-fn vga" for VGA font. Harmless if vga is not present:
497 * xterm: unable to open font "vga", trying "fixed"....
498 */
499 execlp("xterm", "xterm", buf, "-fn","vga",NULL);
Alexandre Julliard54c27111998-03-29 19:44:57 +0000500 ERR(console, "error creating AllocConsole xterm\n");
Alexandre Julliard03468f71998-02-15 19:40:49 +0000501 exit(1);
502 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000503
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000504 req.handle = handle;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000505 req.pid = xpid;
506 CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1, &req, sizeof(req) );
507 CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliard03468f71998-02-15 19:40:49 +0000508
509 /* most xterms like to print their window ID when used with -S;
510 * read it and continue before the user has a chance...
Alexandre Julliard03468f71998-02-15 19:40:49 +0000511 */
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000512 for (i=0; c!='\n'; (status=read(slave, &c, 1)), i++) {
Alexandre Julliard03468f71998-02-15 19:40:49 +0000513 if (status == -1 && c == '\0') {
514 /* wait for xterm to be created */
515 usleep(100);
516 }
517 if (i > 10000) {
Marcus Meissner537772a1998-12-09 16:37:04 +0000518 ERR(console, "can't read xterm WID\n");
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000519 kill(xpid, SIGKILL);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000520 return FALSE;
521 }
522 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000523 /* enable mouseclicks */
524 sprintf(buf,"%c[?1001s%c[?1000h",27,27);
Alexandre Julliard55443871998-12-31 15:52:06 +0000525 WriteFile(handle,buf,strlen(buf),&xlen,NULL);
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000526
Alexandre Julliarda3960291999-02-26 11:11:13 +0000527 if (GetConsoleTitleA( buf, sizeof(buf) ))
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000528 {
529 WriteFile(handle,"\033]2;",4,&xlen,NULL);
530 WriteFile(handle,buf,strlen(buf),&xlen,NULL);
531 WriteFile(handle,"\a",1,&xlen,NULL);
Alexandre Julliard638f1691999-01-17 16:32:32 +0000532 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000533 return TRUE;
534
535}
536
537
538/***********************************************************************
539 * AllocConsole (KERNEL32.103)
540 *
541 * creates an xterm with a pty to our program
542 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000543BOOL WINAPI AllocConsole(VOID)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000544{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000545 struct open_console_request req;
546 struct open_console_reply reply;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000547 HANDLE hIn, hOut, hErr;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000548
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000549 CLIENT_SendRequest( REQ_ALLOC_CONSOLE, -1, 0 );
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000550 if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS) return FALSE;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000551
552 req.output = 0;
Marcus Meissnerfbc56251999-01-20 14:46:49 +0000553 req.access = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000554 req.inherit = FALSE;
555 CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
Alexandre Julliard6ebbe3c1999-01-01 17:04:00 +0000556 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000557 {
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000558 /* FIXME: free console */
Alexandre Julliard03468f71998-02-15 19:40:49 +0000559 return FALSE;
Alexandre Julliardb2340ea1998-12-30 12:10:49 +0000560 }
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000561 hIn = reply.handle;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000562
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000563 req.output = 1;
564 CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
565 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
566 {
567 CloseHandle(hIn);
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000568 /* FIXME: free console */
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000569 return FALSE;
570 }
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000571 hOut = reply.handle;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000572
Alexandre Julliardb2340ea1998-12-30 12:10:49 +0000573 if (!DuplicateHandle( GetCurrentProcess(), hOut,
574 GetCurrentProcess(), &hErr,
575 0, TRUE, DUPLICATE_SAME_ACCESS ))
Alexandre Julliard03468f71998-02-15 19:40:49 +0000576 {
577 CloseHandle(hIn);
578 CloseHandle(hOut);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000579 return FALSE;
580 }
Alexandre Julliard03468f71998-02-15 19:40:49 +0000581
Alexandre Julliard03468f71998-02-15 19:40:49 +0000582 /* NT resets the STD_*_HANDLEs on console alloc */
583 SetStdHandle(STD_INPUT_HANDLE, hIn);
584 SetStdHandle(STD_OUTPUT_HANDLE, hOut);
585 SetStdHandle(STD_ERROR_HANDLE, hErr);
586
587 SetLastError(ERROR_SUCCESS);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000588 SetConsoleTitleA("Wine Console");
Alexandre Julliard03468f71998-02-15 19:40:49 +0000589 return TRUE;
590}
591
592
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000593/******************************************************************************
594 * GetConsoleCP [KERNEL32.295] Returns the OEM code page for the console
595 *
596 * RETURNS
597 * Code page code
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000598 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000599UINT WINAPI GetConsoleCP(VOID)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000600{
601 return GetACP();
602}
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000603
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000604
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000605/***********************************************************************
606 * GetConsoleOutputCP (KERNEL32.189)
607 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000608UINT WINAPI GetConsoleOutputCP(VOID)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000609{
610 return GetConsoleCP();
611}
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000612
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000613/***********************************************************************
614 * GetConsoleMode (KERNEL32.188)
615 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000616BOOL WINAPI GetConsoleMode(HANDLE hcon,LPDWORD mode)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000617{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000618 struct get_console_mode_request req;
619 struct get_console_mode_reply reply;
Marcus Meissner537772a1998-12-09 16:37:04 +0000620
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000621 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000622 CLIENT_SendRequest( REQ_GET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
623 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
624 *mode = reply.mode;
Marcus Meissner537772a1998-12-09 16:37:04 +0000625 return TRUE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000626}
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000627
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000628
629/******************************************************************************
630 * SetConsoleMode [KERNEL32.628] Sets input mode of console's input buffer
631 *
632 * PARAMS
633 * hcon [I] Handle to console input or screen buffer
634 * mode [I] Input or output mode to set
635 *
636 * RETURNS
637 * Success: TRUE
638 * Failure: FALSE
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000639 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000640BOOL WINAPI SetConsoleMode( HANDLE hcon, DWORD mode )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000641{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000642 struct set_console_mode_request req;
Marcus Meissner537772a1998-12-09 16:37:04 +0000643
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000644 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000645 req.mode = mode;
646 CLIENT_SendRequest( REQ_SET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
647 return !CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000648}
649
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000650
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000651/***********************************************************************
652 * GetConsoleTitleA (KERNEL32.191)
653 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000654DWORD WINAPI GetConsoleTitleA(LPSTR title,DWORD size)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000655{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000656 struct get_console_info_request req;
657 struct get_console_info_reply reply;
658 int len;
659 DWORD ret = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000660 HANDLE hcon;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000661
Alexandre Julliarda3960291999-02-26 11:11:13 +0000662 if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ, 0, NULL,
663 OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000664 return 0;
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000665 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000666 CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
667 if (!CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), title, size ))
668 {
669 if (len > sizeof(reply)+size) title[size-1] = 0;
670 ret = strlen(title);
671 }
672 CloseHandle( hcon );
673 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000674}
675
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000676
677/******************************************************************************
678 * GetConsoleTitle32W [KERNEL32.192] Retrieves title string for console
679 *
680 * PARAMS
681 * title [O] Address of buffer for title
682 * size [I] Size of buffer
683 *
684 * RETURNS
685 * Success: Length of string copied
686 * Failure: 0
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000687 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000688DWORD WINAPI GetConsoleTitleW( LPWSTR title, DWORD size )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000689{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000690 char *tmp;
691 DWORD ret;
692
693 if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size ))) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000694 ret = GetConsoleTitleA( tmp, size );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000695 lstrcpyAtoW( title, tmp );
696 HeapFree( GetProcessHeap(), 0, tmp );
697 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000698}
699
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000700
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000701/***********************************************************************
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000702 * WriteConsoleA (KERNEL32.729)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000703 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000704BOOL WINAPI WriteConsoleA( HANDLE hConsoleOutput,
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000705 LPCVOID lpBuffer,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000706 DWORD nNumberOfCharsToWrite,
707 LPDWORD lpNumberOfCharsWritten,
708 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000709{
Alexandre Julliard03468f71998-02-15 19:40:49 +0000710 /* FIXME: should I check if this is a console handle? */
711 return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
712 lpNumberOfCharsWritten, NULL);
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000713}
714
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000715
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000716#define CADD(c) \
717 if (bufused==curbufsize-1) \
718 buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\
719 buffer[bufused++]=c;
720#define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}}
721
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000722/***********************************************************************
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000723 * WriteConsoleOutputA (KERNEL32.732)
724 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000725BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput,
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000726 LPCHAR_INFO lpBuffer,
727 COORD dwBufferSize,
728 COORD dwBufferCoord,
729 LPSMALL_RECT lpWriteRegion)
730{
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000731 int i,j,off=0,lastattr=-1;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000732 char sbuf[20],*buffer=NULL;
733 int bufused=0,curbufsize = 100;
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000734 DWORD res;
Marcus Meissner537772a1998-12-09 16:37:04 +0000735 const int colormap[8] = {
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000736 0,4,2,6,
737 1,5,3,7,
738 };
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000739 CONSOLE_make_complex(hConsoleOutput);
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000740 buffer = HeapAlloc(GetProcessHeap(),0,100);;
741 curbufsize = 100;
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000742
743 TRACE(console,"wr: top = %d, bottom=%d, left=%d,right=%d\n",
744 lpWriteRegion->Top,
745 lpWriteRegion->Bottom,
746 lpWriteRegion->Left,
747 lpWriteRegion->Right
748 );
749
750 for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) {
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000751 sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1);
752 SADD(sbuf);
753 for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) {
754 if (lastattr!=lpBuffer[off].Attributes) {
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000755 lastattr = lpBuffer[off].Attributes;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000756 sprintf(sbuf,"%c[0;%s3%d;4%dm",
Marcus Meissner537772a1998-12-09 16:37:04 +0000757 27,
758 (lastattr & FOREGROUND_INTENSITY)?"1;":"",
759 colormap[lastattr&7],
760 colormap[(lastattr&0x70)>>4]
761 );
762 /* FIXME: BACKGROUND_INTENSITY */
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000763 SADD(sbuf);
764 }
765 CADD(lpBuffer[off].Char.AsciiChar);
766 off++;
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000767 }
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000768 }
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000769 sprintf(sbuf,"%c[0m",27);SADD(sbuf);
770 WriteFile(hConsoleOutput,buffer,bufused,&res,NULL);
771 HeapFree(GetProcessHeap(),0,buffer);
Marcus Meissnerb02ffc71998-10-11 10:49:46 +0000772 return TRUE;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000773}
774
775/***********************************************************************
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000776 * WriteConsoleW (KERNEL32.577)
777 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000778BOOL WINAPI WriteConsoleW( HANDLE hConsoleOutput,
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000779 LPCVOID lpBuffer,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000780 DWORD nNumberOfCharsToWrite,
781 LPDWORD lpNumberOfCharsWritten,
782 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000783{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000784 BOOL ret;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000785 LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite );
786
787 lstrcpynWtoA( xstring, lpBuffer,nNumberOfCharsToWrite);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000788
789 /* FIXME: should I check if this is a console handle? */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000790 ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite,
Alexandre Julliard03468f71998-02-15 19:40:49 +0000791 lpNumberOfCharsWritten, NULL);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000792 HeapFree( GetProcessHeap(), 0, xstring );
793 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000794}
795
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000796
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000797/***********************************************************************
798 * ReadConsoleA (KERNEL32.419)
799 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000800BOOL WINAPI ReadConsoleA( HANDLE hConsoleInput,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000801 LPVOID lpBuffer,
802 DWORD nNumberOfCharsToRead,
803 LPDWORD lpNumberOfCharsRead,
804 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000805{
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000806 int charsread = 0;
Marcus Meissner537772a1998-12-09 16:37:04 +0000807 LPSTR xbuf = (LPSTR)lpBuffer;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000808 struct read_console_input_request req;
809 INPUT_RECORD ir;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000810
Marcus Meissner537772a1998-12-09 16:37:04 +0000811 TRACE(console,"(%d,%p,%ld,%p,%p)\n",
812 hConsoleInput,lpBuffer,nNumberOfCharsToRead,
813 lpNumberOfCharsRead,lpReserved
814 );
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000815
816 CONSOLE_get_input(hConsoleInput,FALSE);
817
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000818 req.handle = hConsoleInput;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000819 req.count = 1;
820 req.flush = 1;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000821
Alexandre Julliard638f1691999-01-17 16:32:32 +0000822 /* FIXME: should we read at least 1 char? The SDK does not say */
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000823 while (charsread<nNumberOfCharsToRead)
824 {
825 int len;
826
827 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
828 if (CLIENT_WaitReply( &len, NULL, 1, &ir, sizeof(ir) ))
829 return FALSE;
830 assert( !(len % sizeof(ir)) );
831 if (!len) break;
832 if (!ir.Event.KeyEvent.bKeyDown)
Marcus Meissner537772a1998-12-09 16:37:04 +0000833 continue;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000834 if (ir.EventType != KEY_EVENT)
Marcus Meissner537772a1998-12-09 16:37:04 +0000835 continue;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000836 *xbuf++ = ir.Event.KeyEvent.uChar.AsciiChar;
Marcus Meissner8bc54b61998-12-14 14:48:09 +0000837 charsread++;
Marcus Meissner537772a1998-12-09 16:37:04 +0000838 }
Marcus Meissner537772a1998-12-09 16:37:04 +0000839 if (lpNumberOfCharsRead)
840 *lpNumberOfCharsRead = charsread;
Marcus Meissner537772a1998-12-09 16:37:04 +0000841 return TRUE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000842}
843
844/***********************************************************************
845 * ReadConsoleW (KERNEL32.427)
846 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000847BOOL WINAPI ReadConsoleW( HANDLE hConsoleInput,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000848 LPVOID lpBuffer,
849 DWORD nNumberOfCharsToRead,
850 LPDWORD lpNumberOfCharsRead,
851 LPVOID lpReserved )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000852{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000853 BOOL ret;
Marcus Meissner537772a1998-12-09 16:37:04 +0000854 LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000855
Alexandre Julliarda3960291999-02-26 11:11:13 +0000856 ret = ReadConsoleA(
Marcus Meissner537772a1998-12-09 16:37:04 +0000857 hConsoleInput,
858 buf,
859 nNumberOfCharsToRead,
860 lpNumberOfCharsRead,
861 lpReserved
862 );
863 if (ret)
864 lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
865 HeapFree( GetProcessHeap(), 0, buf );
866 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000867}
868
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000869
870/******************************************************************************
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +0000871 * ReadConsoleInput32A [KERNEL32.569] Reads data from a console
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000872 *
873 * PARAMS
874 * hConsoleInput [I] Handle to console input buffer
875 * lpBuffer [O] Address of buffer for read data
876 * nLength [I] Number of records to read
877 * lpNumberOfEventsRead [O] Address of number of records read
878 *
879 * RETURNS
880 * Success: TRUE
881 * Failure: FALSE
882 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000883BOOL WINAPI ReadConsoleInputA(HANDLE hConsoleInput,
Marcus Meissner537772a1998-12-09 16:37:04 +0000884 LPINPUT_RECORD lpBuffer,
885 DWORD nLength, LPDWORD lpNumberOfEventsRead)
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000886{
Alexandre Julliard4b461121999-01-31 19:04:30 +0000887 struct read_console_input_request req;
888 int len;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000889
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000890 req.handle = hConsoleInput;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000891 req.count = nLength;
892 req.flush = 1;
Alexandre Julliard638f1691999-01-17 16:32:32 +0000893
Alexandre Julliard4b461121999-01-31 19:04:30 +0000894 /* loop until we get at least one event */
895 for (;;)
896 {
897 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
898 if (CLIENT_WaitReply( &len, NULL, 1, lpBuffer, nLength * sizeof(*lpBuffer) ))
899 return FALSE;
900 assert( !(len % sizeof(INPUT_RECORD)) );
901 if (len) break;
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000902 CONSOLE_get_input(hConsoleInput,TRUE);
903 /*WaitForSingleObject( hConsoleInput, INFINITE32 );*/
Marcus Meissner537772a1998-12-09 16:37:04 +0000904 }
Alexandre Julliard4b461121999-01-31 19:04:30 +0000905 if (lpNumberOfEventsRead) *lpNumberOfEventsRead = len / sizeof(INPUT_RECORD);
Marcus Meissner537772a1998-12-09 16:37:04 +0000906 return TRUE;
907}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000908
Alexandre Julliard4b461121999-01-31 19:04:30 +0000909
910/***********************************************************************
911 * ReadConsoleInput32W (KERNEL32.570)
912 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000913BOOL WINAPI ReadConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000914 DWORD count, LPDWORD read )
915{
916 /* FIXME: Fix this if we get UNICODE input. */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000917 return ReadConsoleInputA( handle, buffer, count, read );
Alexandre Julliard4b461121999-01-31 19:04:30 +0000918}
919
920
921/***********************************************************************
922 * FlushConsoleInputBuffer (KERNEL32.132)
923 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000924BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
Alexandre Julliard4b461121999-01-31 19:04:30 +0000925{
926 struct read_console_input_request req;
927 int len;
928
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000929 req.handle = handle;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000930 req.count = -1; /* get all records */
931 req.flush = 1;
932 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
933 return !CLIENT_WaitReply( &len, NULL, 0 );
934}
935
936
937/***********************************************************************
938 * PeekConsoleInputA (KERNEL32.550)
939 *
940 * Gets 'count' first events (or less) from input queue.
941 *
942 * Does not need a complex console.
943 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000944BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000945 DWORD count, LPDWORD read )
946{
947 struct read_console_input_request req;
948 int len;
949
Marcus Meissnera2ca7b91999-02-05 09:32:39 +0000950 CONSOLE_get_input(handle,FALSE);
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000951 req.handle = handle;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000952 req.count = count;
953 req.flush = 0;
954
955 CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
956 if (CLIENT_WaitReply( &len, NULL, 1, buffer, count * sizeof(*buffer) ))
957 return FALSE;
958 assert( !(len % sizeof(INPUT_RECORD)) );
959 if (read) *read = len / sizeof(INPUT_RECORD);
960 return TRUE;
961}
962
963
964/***********************************************************************
965 * PeekConsoleInputW (KERNEL32.551)
966 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000967BOOL WINAPI PeekConsoleInputW(HANDLE hConsoleInput,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000968 LPINPUT_RECORD pirBuffer,
969 DWORD cInRecords,
970 LPDWORD lpcRead)
971{
972 /* FIXME: Hmm. Fix this if we get UNICODE input. */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000973 return PeekConsoleInputA(hConsoleInput,pirBuffer,cInRecords,lpcRead);
Alexandre Julliard4b461121999-01-31 19:04:30 +0000974}
975
976
977/******************************************************************************
978 * WriteConsoleInput32A [KERNEL32.730] Write data to a console input buffer
979 *
980 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000981BOOL WINAPI WriteConsoleInputA( HANDLE handle, INPUT_RECORD *buffer,
Alexandre Julliard4b461121999-01-31 19:04:30 +0000982 DWORD count, LPDWORD written )
983{
984 struct write_console_input_request req;
985 struct write_console_input_reply reply;
986
Alexandre Julliard96c08d81999-02-28 13:27:56 +0000987 req.handle = handle;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000988 req.count = count;
989 CLIENT_SendRequest( REQ_WRITE_CONSOLE_INPUT, -1, 2, &req, sizeof(req),
990 buffer, count * sizeof(*buffer) );
991 if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
992 if (written) *written = reply.written;
993 return TRUE;
994}
995
996
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000997/***********************************************************************
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000998 * SetConsoleTitle32A (KERNEL32.476)
Marcus Meissner537772a1998-12-09 16:37:04 +0000999 *
1000 * Sets the console title.
1001 *
1002 * We do not necessarily need to create a complex console for that,
1003 * but should remember the title and set it on creation of the latter.
1004 * (not fixed at this time).
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001005 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001006BOOL WINAPI SetConsoleTitleA(LPCSTR title)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001007{
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001008 struct set_console_info_request req;
1009 struct get_console_info_reply info;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001010 HANDLE hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001011 DWORD written;
1012
Alexandre Julliarda3960291999-02-26 11:11:13 +00001013 if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
1014 OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001015 return FALSE;
Alexandre Julliard96c08d81999-02-28 13:27:56 +00001016 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001017 req.mask = SET_CONSOLE_INFO_TITLE;
1018 CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 2, &req, sizeof(req),
1019 title, strlen(title)+1 );
1020 if (CLIENT_WaitReply( NULL, NULL, 0 )) goto error;
1021 if (CONSOLE_GetInfo( hcon, &info ) && info.pid)
1022 {
1023 /* only set title for complex console (own xterm) */
1024 WriteFile( hcon, "\033]2;", 4, &written, NULL );
1025 WriteFile( hcon, title, strlen(title), &written, NULL );
1026 WriteFile( hcon, "\a", 1, &written, NULL );
1027 }
Alexandre Julliard96c08d81999-02-28 13:27:56 +00001028 CloseHandle( hcon );
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001029 return TRUE;
1030 error:
1031 CloseHandle( hcon );
1032 return FALSE;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001033}
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001034
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001035
1036/******************************************************************************
1037 * SetConsoleTitle32W [KERNEL32.477] Sets title bar string for console
1038 *
1039 * PARAMS
1040 * title [I] Address of new title
1041 *
1042 * NOTES
1043 * This should not be calling the A version
1044 *
1045 * RETURNS
1046 * Success: TRUE
1047 * Failure: FALSE
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001048 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001049BOOL WINAPI SetConsoleTitleW( LPCWSTR title )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001050{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001051 BOOL ret;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001052
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001053 LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001054 ret = SetConsoleTitleA(titleA);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001055 HeapFree( GetProcessHeap(), 0, titleA );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001056 return ret;
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001057}
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001058
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001059/******************************************************************************
1060 * SetConsoleCursorPosition [KERNEL32.627]
1061 * Sets the cursor position in console
1062 *
1063 * PARAMS
1064 * hConsoleOutput [I] Handle of console screen buffer
1065 * dwCursorPosition [I] New cursor position coordinates
1066 *
1067 * RETURNS STD
1068 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001069BOOL WINAPI SetConsoleCursorPosition( HANDLE hcon, COORD pos )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001070{
Marcus Meissner537772a1998-12-09 16:37:04 +00001071 char xbuf[20];
1072 DWORD xlen;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001073
Marcus Meissner03f10f41999-01-26 10:08:36 +00001074 /* make console complex only if we change lines, not just in the line */
1075 if (pos.y)
1076 CONSOLE_make_complex(hcon);
1077
Marcus Meissner537772a1998-12-09 16:37:04 +00001078 TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y );
1079 /* x are columns, y rows */
Marcus Meissner03f10f41999-01-26 10:08:36 +00001080 if (pos.y)
1081 /* full screen cursor absolute positioning */
1082 sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1);
1083 else
1084 /* relative cursor positioning in line (\r to go to 0) */
1085 sprintf(xbuf,"\r%c[%dC", 0x1B, pos.x);
Marcus Meissner537772a1998-12-09 16:37:04 +00001086 /* FIXME: store internal if we start using own console buffers */
1087 WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL);
Marcus Meissner537772a1998-12-09 16:37:04 +00001088 return TRUE;
1089}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001090
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001091/***********************************************************************
1092 * GetNumberOfConsoleInputEvents (KERNEL32.246)
1093 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001094BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hcon,LPDWORD nrofevents)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001095{
Marcus Meissnera2ca7b91999-02-05 09:32:39 +00001096 CONSOLE_get_input(hcon,FALSE);
1097 *nrofevents = 1; /* UMM */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001098 return TRUE;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001099}
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001100
1101/***********************************************************************
1102 * GetNumberOfConsoleMouseButtons (KERNEL32.358)
1103 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001104BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001105{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001106 FIXME(console,"(%p): stub\n", nrofbuttons);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001107 *nrofbuttons = 2;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001108 return TRUE;
1109}
1110
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001111/******************************************************************************
1112 * GetConsoleCursorInfo32 [KERNEL32.296] Gets size and visibility of console
1113 *
1114 * PARAMS
1115 * hcon [I] Handle to console screen buffer
1116 * cinfo [O] Address of cursor information
1117 *
1118 * RETURNS
1119 * Success: TRUE
1120 * Failure: FALSE
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001121 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001122BOOL WINAPI GetConsoleCursorInfo( HANDLE hcon,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001123 LPCONSOLE_CURSOR_INFO cinfo )
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001124{
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001125 struct get_console_info_reply reply;
Marcus Meissner537772a1998-12-09 16:37:04 +00001126
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001127 if (!CONSOLE_GetInfo( hcon, &reply )) return FALSE;
1128 if (cinfo)
1129 {
1130 cinfo->dwSize = reply.cursor_size;
1131 cinfo->bVisible = reply.cursor_visible;
Marcus Meissner537772a1998-12-09 16:37:04 +00001132 }
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001133 return TRUE;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001134}
1135
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001136
1137/******************************************************************************
1138 * SetConsoleCursorInfo32 [KERNEL32.626] Sets size and visibility of cursor
1139 *
1140 * RETURNS
1141 * Success: TRUE
1142 * Failure: FALSE
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001143 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001144BOOL WINAPI SetConsoleCursorInfo(
1145 HANDLE hcon, /* [in] Handle to console screen buffer */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001146 LPCONSOLE_CURSOR_INFO cinfo) /* [in] Address of cursor information */
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001147{
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001148 struct set_console_info_request req;
Marcus Meissner537772a1998-12-09 16:37:04 +00001149 char buf[8];
1150 DWORD xlen;
Marcus Meissner537772a1998-12-09 16:37:04 +00001151
Alexandre Julliard96c08d81999-02-28 13:27:56 +00001152 req.handle = hcon;
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001153 CONSOLE_make_complex(hcon);
1154 sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l');
Marcus Meissner537772a1998-12-09 16:37:04 +00001155 WriteFile(hcon,buf,strlen(buf),&xlen,NULL);
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001156
1157 req.cursor_size = cinfo->dwSize;
1158 req.cursor_visible = cinfo->bVisible;
1159 req.mask = SET_CONSOLE_INFO_CURSOR;
1160 CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
1161 return !CLIENT_WaitReply( NULL, NULL, 0 );
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001162}
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001163
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001164
1165/******************************************************************************
1166 * SetConsoleWindowInfo [KERNEL32.634] Sets size and position of console
1167 *
1168 * RETURNS
1169 * Success: TRUE
1170 * Failure: FALSE
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001171 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001172BOOL WINAPI SetConsoleWindowInfo(
1173 HANDLE hcon, /* [in] Handle to console screen buffer */
1174 BOOL bAbsolute, /* [in] Coordinate type flag */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001175 LPSMALL_RECT window) /* [in] Address of new window rectangle */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001176{
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001177 FIXME(console, "(%x,%d,%p): stub\n", hcon, bAbsolute, window);
1178 return TRUE;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001179}
1180
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001181
1182/******************************************************************************
1183 * SetConsoleTextAttribute32 [KERNEL32.631] Sets colors for text
1184 *
1185 * Sets the foreground and background color attributes of characters
1186 * written to the screen buffer.
1187 *
1188 * RETURNS
1189 * Success: TRUE
1190 * Failure: FALSE
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001191 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001192BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttr)
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001193{
Marcus Meissner537772a1998-12-09 16:37:04 +00001194 const int colormap[8] = {
1195 0,4,2,6,
1196 1,5,3,7,
1197 };
1198 DWORD xlen;
1199 char buffer[20];
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001200
Marcus Meissner8bc54b61998-12-14 14:48:09 +00001201 TRACE(console,"(%d,%d)\n",hConsoleOutput,wAttr);
Marcus Meissner537772a1998-12-09 16:37:04 +00001202 sprintf(buffer,"%c[0;%s3%d;4%dm",
1203 27,
1204 (wAttr & FOREGROUND_INTENSITY)?"1;":"",
1205 colormap[wAttr&7],
1206 colormap[(wAttr&0x70)>>4]
1207 );
1208 WriteFile(hConsoleOutput,buffer,strlen(buffer),&xlen,NULL);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001209 return TRUE;
1210}
1211
1212
1213/******************************************************************************
1214 * SetConsoleScreenBufferSize [KERNEL32.630] Changes size of console
1215 *
1216 * PARAMS
1217 * hConsoleOutput [I] Handle to console screen buffer
1218 * dwSize [I] New size in character rows and cols
1219 *
1220 * RETURNS
1221 * Success: TRUE
1222 * Failure: FALSE
1223 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001224BOOL WINAPI SetConsoleScreenBufferSize( HANDLE hConsoleOutput,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001225 COORD dwSize )
1226{
1227 FIXME(console, "(%d,%dx%d): stub\n",hConsoleOutput,dwSize.x,dwSize.y);
1228 return TRUE;
1229}
1230
1231
1232/******************************************************************************
1233 * FillConsoleOutputCharacterA [KERNEL32.242]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001234 *
1235 * PARAMS
1236 * hConsoleOutput [I] Handle to screen buffer
1237 * cCharacter [I] Character to write
1238 * nLength [I] Number of cells to write to
1239 * dwCoord [I] Coords of first cell
1240 * lpNumCharsWritten [O] Pointer to number of cells written
1241 *
1242 * RETURNS
1243 * Success: TRUE
1244 * Failure: FALSE
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001245 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001246BOOL WINAPI FillConsoleOutputCharacterA(
1247 HANDLE hConsoleOutput,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001248 BYTE cCharacter,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001249 DWORD nLength,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001250 COORD dwCoord,
1251 LPDWORD lpNumCharsWritten)
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001252{
Marcus Meissner537772a1998-12-09 16:37:04 +00001253 long count;
1254 DWORD xlen;
1255
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001256 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1257 for(count=0;count<nLength;count++)
Marcus Meissner537772a1998-12-09 16:37:04 +00001258 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001259 *lpNumCharsWritten = nLength;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001260 return TRUE;
1261}
1262
1263
1264/******************************************************************************
1265 * FillConsoleOutputCharacterW [KERNEL32.243] Writes characters to console
1266 *
1267 * PARAMS
1268 * hConsoleOutput [I] Handle to screen buffer
1269 * cCharacter [I] Character to write
1270 * nLength [I] Number of cells to write to
1271 * dwCoord [I] Coords of first cell
1272 * lpNumCharsWritten [O] Pointer to number of cells written
1273 *
1274 * RETURNS
1275 * Success: TRUE
1276 * Failure: FALSE
1277 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001278BOOL WINAPI FillConsoleOutputCharacterW(HANDLE hConsoleOutput,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001279 WCHAR cCharacter,
1280 DWORD nLength,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001281 COORD dwCoord,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001282 LPDWORD lpNumCharsWritten)
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001283{
Marcus Meissner537772a1998-12-09 16:37:04 +00001284 long count;
1285 DWORD xlen;
1286
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001287 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
Marcus Meissner537772a1998-12-09 16:37:04 +00001288 /* FIXME: not quite correct ... but the lower part of UNICODE char comes
1289 * first
1290 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001291 for(count=0;count<nLength;count++)
Marcus Meissner537772a1998-12-09 16:37:04 +00001292 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001293 *lpNumCharsWritten = nLength;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001294 return TRUE;
1295}
1296
1297
1298/******************************************************************************
1299 * FillConsoleOutputAttribute [KERNEL32.241] Sets attributes for console
1300 *
1301 * PARAMS
1302 * hConsoleOutput [I] Handle to screen buffer
1303 * wAttribute [I] Color attribute to write
1304 * nLength [I] Number of cells to write to
1305 * dwCoord [I] Coords of first cell
1306 * lpNumAttrsWritten [O] Pointer to number of cells written
1307 *
1308 * RETURNS
1309 * Success: TRUE
1310 * Failure: FALSE
1311 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001312BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001313 WORD wAttribute, DWORD nLength, COORD dwCoord,
1314 LPDWORD lpNumAttrsWritten)
1315{
1316 FIXME(console, "(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1317 wAttribute,nLength,dwCoord.x,dwCoord.y,lpNumAttrsWritten);
1318 *lpNumAttrsWritten = nLength;
1319 return TRUE;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001320}
1321
Alexandre Julliarda845b881998-06-01 10:44:35 +00001322/******************************************************************************
1323 * ReadConsoleOutputCharacter32A [KERNEL32.573]
1324 *
1325 * BUGS
1326 * Unimplemented
1327 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001328BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput,
Alexandre Julliarda845b881998-06-01 10:44:35 +00001329 LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1330{
1331 FIXME(console, "(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1332 dword,coord.x,coord.y,lpdword);
1333 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1334 return FALSE;
1335}
Alexandre Julliard642d3131998-07-12 19:29:36 +00001336
1337
1338/******************************************************************************
1339 * ScrollConsoleScreenBuffer [KERNEL32.612]
1340 *
1341 * BUGS
1342 * Unimplemented
1343 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001344BOOL WINAPI ScrollConsoleScreenBuffer( HANDLE hConsoleOutput,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001345 LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1346 COORD dwDestOrigin, LPCHAR_INFO lpFill)
1347{
1348 FIXME(console, "(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1349 lpClipRect,dwDestOrigin.x,dwDestOrigin.y,lpFill);
1350 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1351 return FALSE;
1352}