Return success in CreateProcess when we started a non-Winelib Unix
[wine/multimedia.git] / win32 / console.c
blob2734e3f55a9f1b603ab061c18227b8d7d630fc1d
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 * Copyright 1997 Karl Garrison
6 * Copyright 1998 John Richardson
7 * Copyright 1998 Marcus Meissner
8 */
10 /* FIXME:
11 * - Completely lacks SCREENBUFFER interface.
12 * - No abstraction for something other than xterm.
13 * - Output sometimes is buffered (We switched off buffering by ~ICANON ?)
15 /* Reference applications:
16 * - IDA (interactive disassembler) full version 3.75. Works.
17 * - LYNX/W32. Works mostly, some keys crash it.
20 #include "config.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <termios.h>
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #ifdef HAVE_SYS_ERRNO_H
33 #include <sys/errno.h>
34 #endif
35 #include <signal.h>
36 #include <assert.h>
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winnls.h"
41 #include "wingdi.h"
42 #include "wine/winuser16.h"
43 #include "thread.h"
44 #include "winerror.h"
45 #include "wincon.h"
46 #include "heap.h"
47 #include "wine/server.h"
48 #include "debugtools.h"
50 DEFAULT_DEBUG_CHANNEL(console);
52 /* Ascii -> VK, generated by calling VkKeyScanA(i) */
53 static int vkkeyscan_table[256] = {
54 0,0,0,0,0,0,0,0,8,9,0,0,0,13,0,0,0,0,0,19,145,556,0,0,0,0,0,27,0,0,0,
55 0,32,305,478,307,308,309,311,222,313,304,312,443,188,189,190,191,48,
56 49,50,51,52,53,54,55,56,57,442,186,444,187,446,447,306,321,322,323,
57 324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,
58 341,342,343,344,345,346,219,220,221,310,445,192,65,66,67,68,69,70,71,
59 72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,475,476,477,
60 448,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0
66 static int mapvkey_0[256]={
67 0,0,0,0,0,0,0,0,14,15,0,0,0,28,0,0,42,29,56,69,58,0,0,0,0,0,0,1,0,0,
68 0,0,57,73,81,79,71,75,72,77,80,0,0,0,55,82,83,0,11,2,3,4,5,6,7,8,9,
69 10,0,0,0,0,0,0,0,30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,
70 19,31,20,22,47,17,45,21,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,78,0,74,
71 0,53,59,60,61,62,63,64,65,66,67,68,87,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
72 0,0,0,0,0,0,69,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,13,51,12,52,53,41,0,0,0,0,0,0,0,0,0,
74 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,43,27,40,76,96,0,0,0,0,0,0,0,0,
75 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
78 static int mapvkey_1[256]={
79 0,27,49,50,51,52,53,54,55,56,57,48,189,187,8,9,81,87,69,82,84,89,85,
80 73,79,80,219,221,13,17,65,83,68,70,71,72,74,75,76,186,222,192,16,220,
81 90,88,67,86,66,78,77,188,190,191,16,106,18,32,20,112,113,114,115,116,
82 117,118,119,120,121,144,145,36,38,33,109,37,223,39,107,35,40,34,45,
83 46,0,0,0,122,123,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
85 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
86 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
87 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
88 0,0,0,0,0,0,0
91 /* FIXME: Should be in an internal header file. OK, so which one?
92 Used by CONSOLE_make_complex. */
93 extern int wine_openpty(int *master, int *slave, char *name,
94 struct termios *term, struct winsize *winsize);
96 /****************************************************************************
97 * CONSOLE_GetPid
99 static int CONSOLE_GetPid( HANDLE handle )
101 int ret = 0;
102 SERVER_START_REQ( get_console_info )
104 req->handle = handle;
105 if (!SERVER_CALL_ERR()) ret = req->pid;
107 SERVER_END_REQ;
108 return ret;
111 /****************************************************************************
112 * XTERM_string_to_IR [internal]
114 * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the
115 * queue. Does translation of vt100 style function keys and xterm-mouse clicks.
117 static void
118 CONSOLE_string_to_IR( HANDLE hConsoleInput,unsigned char *buf,int len) {
119 int j,k;
120 INPUT_RECORD ir;
121 DWORD junk;
123 for (j=0;j<len;j++) {
124 unsigned char inchar = buf[j];
126 if (inchar!=27) { /* no escape -> 'normal' keyboard event */
127 ir.EventType = 1; /* Key_event */
129 ir.Event.KeyEvent.bKeyDown = 1;
130 ir.Event.KeyEvent.wRepeatCount = 0;
132 ir.Event.KeyEvent.dwControlKeyState = 0;
133 if (inchar & 0x80) {
134 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
135 inchar &= ~0x80;
137 ir.Event.KeyEvent.wVirtualKeyCode = vkkeyscan_table[inchar];
138 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100)
139 ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED;
140 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200)
141 ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED;
142 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400)
143 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
144 ir.Event.KeyEvent.wVirtualScanCode = mapvkey_0[
145 ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff
146 ]; /* VirtualKeyCodes to ScanCode */
147 ir.Event.KeyEvent.uChar.AsciiChar = inchar;
149 if ((inchar==127)||(inchar=='\b')) { /* backspace */
150 ir.Event.KeyEvent.uChar.AsciiChar = '\b'; /* FIXME: hmm */
151 ir.Event.KeyEvent.wVirtualScanCode = 0x0e;
152 ir.Event.KeyEvent.wVirtualKeyCode = VK_BACK;
153 } else {
154 if ((inchar=='\n')||(inchar=='\r')) {
155 ir.Event.KeyEvent.uChar.AsciiChar = '\r';
156 ir.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
157 ir.Event.KeyEvent.wVirtualScanCode = 0x1c;
158 ir.Event.KeyEvent.dwControlKeyState = 0;
159 } else {
160 if (inchar<' ') {
161 /* FIXME: find good values for ^X */
162 ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;
163 ir.Event.KeyEvent.wVirtualScanCode = 0xbeef;
168 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
169 ir.Event.KeyEvent.bKeyDown = 0;
170 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
171 continue;
173 /* inchar is ESC */
174 if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */
175 ir.EventType = 1; /* Key_event */
176 ir.Event.KeyEvent.bKeyDown = 1;
177 ir.Event.KeyEvent.wRepeatCount = 0;
179 ir.Event.KeyEvent.wVirtualKeyCode = VK_ESCAPE;
180 ir.Event.KeyEvent.wVirtualScanCode = mapvkey_0[
181 ir.Event.KeyEvent.wVirtualKeyCode
183 ir.Event.KeyEvent.dwControlKeyState = 0;
184 ir.Event.KeyEvent.uChar.AsciiChar = 27;
185 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
186 ir.Event.KeyEvent.bKeyDown = 0;
187 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
188 continue;
190 for (k=j;k<len;k++) {
191 if (((buf[k]>='A') && (buf[k]<='Z')) ||
192 ((buf[k]>='a') && (buf[k]<='z')) ||
193 (buf[k]=='~')
195 break;
197 if (k<len) {
198 int subid,scancode=0;
200 ir.EventType = 1; /* Key_event */
201 ir.Event.KeyEvent.bKeyDown = 1;
202 ir.Event.KeyEvent.wRepeatCount = 0;
203 ir.Event.KeyEvent.dwControlKeyState = 0;
205 ir.Event.KeyEvent.wVirtualKeyCode = 0xad; /* FIXME */
206 ir.Event.KeyEvent.wVirtualScanCode = 0xad; /* FIXME */
207 ir.Event.KeyEvent.uChar.AsciiChar = 0;
209 switch (buf[k]) {
210 case '~':
211 sscanf(&buf[j+2],"%d",&subid);
212 switch (subid) {
213 case 2:/*INS */scancode = 0xe052;break;
214 case 3:/*DEL */scancode = 0xe053;break;
215 case 6:/*PGDW*/scancode = 0xe051;break;
216 case 5:/*PGUP*/scancode = 0xe049;break;
217 case 11:/*F1 */scancode = 0x003b;break;
218 case 12:/*F2 */scancode = 0x003c;break;
219 case 13:/*F3 */scancode = 0x003d;break;
220 case 14:/*F4 */scancode = 0x003e;break;
221 case 15:/*F5 */scancode = 0x003f;break;
222 case 17:/*F6 */scancode = 0x0040;break;
223 case 18:/*F7 */scancode = 0x0041;break;
224 case 19:/*F8 */scancode = 0x0042;break;
225 case 20:/*F9 */scancode = 0x0043;break;
226 case 21:/*F10 */scancode = 0x0044;break;
227 case 23:/*F11 */scancode = 0x00d9;break;
228 case 24:/*F12 */scancode = 0x00da;break;
229 /* FIXME: Shift-Fx */
230 default:
231 FIXME("parse ESC[%d~\n",subid);
232 break;
234 break;
235 case 'A': /* Cursor Up */scancode = 0xe048;break;
236 case 'B': /* Cursor Down */scancode = 0xe050;break;
237 case 'D': /* Cursor Left */scancode = 0xe04b;break;
238 case 'C': /* Cursor Right */scancode = 0xe04d;break;
239 case 'F': /* End */scancode = 0xe04f;break;
240 case 'H': /* Home */scancode = 0xe047;break;
241 case 'M':
242 /* Mouse Button Press (ESCM<button+'!'><x+'!'><y+'!'>) or
243 * Release (ESCM#<x+'!'><y+'!'>
245 if (k<len-3) {
246 ir.EventType = MOUSE_EVENT;
247 ir.Event.MouseEvent.dwMousePosition.X = buf[k+2]-'!';
248 ir.Event.MouseEvent.dwMousePosition.Y = buf[k+3]-'!';
249 if (buf[k+1]=='#')
250 ir.Event.MouseEvent.dwButtonState = 0;
251 else
252 ir.Event.MouseEvent.dwButtonState = 1<<(buf[k+1]-' ');
253 ir.Event.MouseEvent.dwEventFlags = 0; /* FIXME */
254 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk));
255 j=k+3;
257 break;
258 case 'c':
259 j=k;
260 break;
262 if (scancode) {
263 ir.Event.KeyEvent.wVirtualScanCode = scancode;
264 ir.Event.KeyEvent.wVirtualKeyCode = mapvkey_1[scancode];
265 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
266 ir.Event.KeyEvent.bKeyDown = 0;
267 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
268 j=k;
269 continue;
275 /****************************************************************************
276 * CONSOLE_get_input (internal)
278 * Reads (nonblocking) as much input events as possible and stores them
279 * in an internal queue.
281 static void
282 CONSOLE_get_input( HANDLE handle, BOOL blockwait )
284 char *buf = HeapAlloc(GetProcessHeap(),0,1);
285 int len = 0, escape_seen = 0;
287 while (1)
289 DWORD res;
290 char inchar;
292 /* If we have at one time seen escape in this loop, we are
293 * within an Escape sequence, so wait for a bit more input for the
294 * rest of the loop.
296 if (WaitForSingleObject( handle, escape_seen*10 )) break;
297 if (!ReadFile( handle, &inchar, 1, &res, NULL )) break;
298 if (!res) /* res 0 but readable means EOF? Hmm. */
299 break;
300 buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1);
301 buf[len++]=inchar;
302 if (inchar == 27) {
303 if (len>1) {
304 /* If we spot an ESC, we flush all up to it
305 * since we can be sure that we have a complete
306 * sequence.
308 CONSOLE_string_to_IR(handle,buf,len-1);
309 buf = HeapReAlloc(GetProcessHeap(),0,buf,1);
310 buf[0] = 27;
311 len = 1;
313 escape_seen = 1;
316 CONSOLE_string_to_IR(handle,buf,len);
317 HeapFree(GetProcessHeap(),0,buf);
321 /******************************************************************************
322 * read_console_input
324 * Helper function for ReadConsole, ReadConsoleInput and PeekConsoleInput
326 static BOOL read_console_input( HANDLE handle, LPINPUT_RECORD buffer, DWORD count,
327 LPDWORD read, BOOL flush )
329 BOOL ret;
331 count = min( count, REQUEST_MAX_VAR_SIZE/sizeof(INPUT_RECORD) );
333 SERVER_START_VAR_REQ( read_console_input, count*sizeof(INPUT_RECORD) )
335 req->handle = handle;
336 req->flush = flush;
337 if ((ret = !SERVER_CALL_ERR()))
339 if (count) memcpy( buffer, server_data_ptr(req), server_data_size(req) );
340 if (read) *read = req->read;
343 SERVER_END_VAR_REQ;
344 return ret;
348 /******************************************************************************
349 * SetConsoleCtrlHandler [KERNEL32.@] Adds function to calling process list
351 * PARAMS
352 * func [I] Address of handler function
353 * add [I] Handler to add or remove
355 * RETURNS
356 * Success: TRUE
357 * Failure: FALSE
359 * CHANGED
360 * James Sutherland (JamesSutherland@gmx.de)
361 * Added global variables console_ignore_ctrl_c and handlers[]
362 * Does not yet do any error checking, or set LastError if failed.
363 * This doesn't yet matter, since these handlers are not yet called...!
365 static unsigned int console_ignore_ctrl_c = 0;
366 static PHANDLER_ROUTINE handlers[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
367 BOOL WINAPI SetConsoleCtrlHandler( PHANDLER_ROUTINE func, BOOL add )
369 unsigned int alloc_loop = sizeof(handlers)/sizeof(PHANDLER_ROUTINE);
370 unsigned int done = 0;
371 FIXME("(%p,%i) - no error checking or testing yet\n", func, add);
372 if (!func)
374 console_ignore_ctrl_c = add;
375 return TRUE;
377 if (add)
379 for (;alloc_loop--;)
380 if (!handlers[alloc_loop] && !done)
382 handlers[alloc_loop] = func;
383 done++;
385 if (!done)
386 FIXME("Out of space on CtrlHandler table\n");
387 return(done);
389 else
391 for (;alloc_loop--;)
392 if (handlers[alloc_loop] == func && !done)
394 handlers[alloc_loop] = 0;
395 done++;
397 if (!done)
398 WARN("Attempt to remove non-installed CtrlHandler %p\n",
399 func);
400 return (done);
402 return (done);
406 /******************************************************************************
407 * GenerateConsoleCtrlEvent [KERNEL32.@] Simulate a CTRL-C or CTRL-BREAK
409 * PARAMS
410 * dwCtrlEvent [I] Type of event
411 * dwProcessGroupID [I] Process group ID to send event to
413 * NOTES
414 * Doesn't yet work...!
416 * RETURNS
417 * Success: True
418 * Failure: False (and *should* [but doesn't] set LastError)
420 BOOL WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent,
421 DWORD dwProcessGroupID )
423 if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
425 ERR("invalid event %d for PGID %ld\n",
426 (unsigned short)dwCtrlEvent, dwProcessGroupID );
427 return FALSE;
429 if (dwProcessGroupID == GetCurrentProcessId() )
431 FIXME("Attempt to send event %d to self - stub\n",
432 (unsigned short)dwCtrlEvent );
433 return FALSE;
435 FIXME("event %d to external PGID %ld - not implemented yet\n",
436 (unsigned short)dwCtrlEvent, dwProcessGroupID );
437 return FALSE;
441 /******************************************************************************
442 * CreateConsoleScreenBuffer [KERNEL32.@] Creates a console screen buffer
444 * PARAMS
445 * dwDesiredAccess [I] Access flag
446 * dwShareMode [I] Buffer share mode
447 * sa [I] Security attributes
448 * dwFlags [I] Type of buffer to create
449 * lpScreenBufferData [I] Reserved
451 * NOTES
452 * Should call SetLastError
454 * RETURNS
455 * Success: Handle to new console screen buffer
456 * Failure: INVALID_HANDLE_VALUE
458 HANDLE WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
459 DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa,
460 DWORD dwFlags, LPVOID lpScreenBufferData )
462 FIXME("(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess,
463 dwShareMode, sa, dwFlags, lpScreenBufferData);
464 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
465 return INVALID_HANDLE_VALUE;
469 /***********************************************************************
470 * GetConsoleScreenBufferInfo (KERNEL32.@)
472 BOOL WINAPI GetConsoleScreenBufferInfo( HANDLE hConsoleOutput,
473 LPCONSOLE_SCREEN_BUFFER_INFO csbi )
475 csbi->dwSize.X = 80;
476 csbi->dwSize.Y = 24;
477 csbi->dwCursorPosition.X = 0;
478 csbi->dwCursorPosition.Y = 0;
479 csbi->wAttributes = 0;
480 csbi->srWindow.Left = 0;
481 csbi->srWindow.Right = 79;
482 csbi->srWindow.Top = 0;
483 csbi->srWindow.Bottom = 23;
484 csbi->dwMaximumWindowSize.X = 80;
485 csbi->dwMaximumWindowSize.Y = 24;
486 return TRUE;
490 /******************************************************************************
491 * SetConsoleActiveScreenBuffer [KERNEL32.@] Sets buffer to current console
493 * RETURNS
494 * Success: TRUE
495 * Failure: FALSE
497 BOOL WINAPI SetConsoleActiveScreenBuffer(
498 HANDLE hConsoleOutput) /* [in] Handle to console screen buffer */
500 FIXME("(%x): stub\n", hConsoleOutput);
501 return FALSE;
505 /***********************************************************************
506 * GetLargestConsoleWindowSize (KERNEL32.@)
508 * NOTE
509 * This should return a COORD, but calling convention for returning
510 * structures is different between Windows and gcc on i386.
512 * VERSION: [i386]
514 #ifdef __i386__
515 #undef GetLargestConsoleWindowSize
516 DWORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput )
518 COORD c;
519 c.X = 80;
520 c.Y = 24;
521 return *(DWORD *)&c;
523 #endif /* defined(__i386__) */
526 /***********************************************************************
527 * GetLargestConsoleWindowSize (KERNEL32.@)
529 * NOTE
530 * This should return a COORD, but calling convention for returning
531 * structures is different between Windows and gcc on i386.
533 * VERSION: [!i386]
535 #ifndef __i386__
536 COORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput )
538 COORD c;
539 c.X = 80;
540 c.Y = 24;
541 return c;
543 #endif /* defined(__i386__) */
546 /***********************************************************************
547 * FreeConsole (KERNEL32.@)
549 BOOL WINAPI FreeConsole(VOID)
551 BOOL ret;
552 SERVER_START_REQ( free_console )
554 ret = !SERVER_CALL_ERR();
556 SERVER_END_REQ;
557 return ret;
561 /*************************************************************************
562 * CONSOLE_make_complex [internal]
564 * Turns a CONSOLE kernel object into a complex one.
565 * (switches from output/input using the terminal where WINE was started to
566 * its own xterm).
568 * This makes simple commandline tools pipeable, while complex commandline
569 * tools work without getting messed up by debug output.
571 * All other functions should work independently from this call.
573 * To test for complex console: pid == 0 -> simple, otherwise complex.
575 static BOOL CONSOLE_make_complex(HANDLE handle)
577 struct termios term;
578 char buf[256];
579 char c = '\0';
580 int i,xpid,master,slave;
582 if (CONSOLE_GetPid( handle )) return TRUE; /* already complex */
584 MESSAGE("Console: Making console complex (creating an xterm)...\n");
586 if (tcgetattr(0, &term) < 0) {
587 /* ignore failure, or we can't run from a script */
589 term.c_lflag = ~(ECHO|ICANON);
591 if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0)
592 return FALSE;
594 if ((xpid=fork()) == 0) {
595 tcsetattr(slave, TCSADRAIN, &term);
596 close( slave );
597 sprintf(buf, "-Sxx%d", master);
598 /* "-fn vga" for VGA font. Harmless if vga is not present:
599 * xterm: unable to open font "vga", trying "fixed"....
601 execlp("xterm", "xterm", buf, "-fn","vga",NULL);
602 ERR("error creating AllocConsole xterm\n");
603 exit(1);
605 close( master );
607 /* most xterms like to print their window ID when used with -S;
608 * read it and continue before the user has a chance...
610 for (i = 0; i < 10000; i++)
612 if (read( slave, &c, 1 ) == 1)
614 if (c == '\n') break;
616 else usleep(100); /* wait for xterm to be created */
618 if (i == 10000)
620 ERR("can't read xterm WID\n");
621 close( slave );
622 return FALSE;
625 wine_server_send_fd( slave );
626 SERVER_START_REQ( set_console_fd )
628 req->handle = handle;
629 req->fd_in = slave;
630 req->fd_out = slave;
631 req->pid = xpid;
632 SERVER_CALL();
633 close( slave );
635 SERVER_END_REQ;
637 /* enable mouseclicks */
638 strcpy( buf, "\033[?1002h" );
639 WriteFile(handle,buf,strlen(buf),NULL,NULL);
641 strcpy( buf, "\033]2;" );
642 if (GetConsoleTitleA( buf + 4, sizeof(buf) - 5 ))
644 strcat( buf, "\a" );
645 WriteFile(handle,buf,strlen(buf),NULL,NULL);
647 return TRUE;
652 /***********************************************************************
653 * AllocConsole (KERNEL32.@)
655 * creates an xterm with a pty to our program
657 BOOL WINAPI AllocConsole(VOID)
659 BOOL ret;
660 HANDLE hStderr;
661 int handle_in, handle_out;
663 TRACE("()\n");
665 SERVER_START_REQ( alloc_console )
667 req->access = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE;
668 req->inherit = FALSE;
669 ret = !SERVER_CALL_ERR();
670 handle_in = req->handle_in;
671 handle_out = req->handle_out;
673 SERVER_END_REQ;
674 if (!ret) return FALSE;
676 if (!DuplicateHandle( GetCurrentProcess(), handle_out, GetCurrentProcess(), &hStderr,
677 0, TRUE, DUPLICATE_SAME_ACCESS ))
679 CloseHandle( handle_in );
680 CloseHandle( handle_out );
681 FreeConsole();
682 return FALSE;
685 /* NT resets the STD_*_HANDLEs on console alloc */
686 SetStdHandle( STD_INPUT_HANDLE, handle_in );
687 SetStdHandle( STD_OUTPUT_HANDLE, handle_out );
688 SetStdHandle( STD_ERROR_HANDLE, hStderr );
690 SetLastError(ERROR_SUCCESS);
691 SetConsoleTitleA("Wine Console");
692 return TRUE;
696 /******************************************************************************
697 * GetConsoleCP [KERNEL32.@] Returns the OEM code page for the console
699 * RETURNS
700 * Code page code
702 UINT WINAPI GetConsoleCP(VOID)
704 return GetACP();
708 /***********************************************************************
709 * GetConsoleOutputCP (KERNEL32.@)
711 UINT WINAPI GetConsoleOutputCP(VOID)
713 return GetConsoleCP();
716 /***********************************************************************
717 * GetConsoleMode (KERNEL32.@)
719 BOOL WINAPI GetConsoleMode(HANDLE hcon,LPDWORD mode)
721 BOOL ret;
722 SERVER_START_REQ( get_console_mode )
724 req->handle = hcon;
725 ret = !SERVER_CALL_ERR();
726 if (ret && mode) *mode = req->mode;
728 SERVER_END_REQ;
729 return ret;
733 /******************************************************************************
734 * SetConsoleMode [KERNEL32.@] Sets input mode of console's input buffer
736 * PARAMS
737 * hcon [I] Handle to console input or screen buffer
738 * mode [I] Input or output mode to set
740 * RETURNS
741 * Success: TRUE
742 * Failure: FALSE
744 BOOL WINAPI SetConsoleMode( HANDLE hcon, DWORD mode )
746 BOOL ret;
747 SERVER_START_REQ( set_console_mode )
749 req->handle = hcon;
750 req->mode = mode;
751 ret = !SERVER_CALL_ERR();
753 SERVER_END_REQ;
754 return ret;
758 /******************************************************************************
759 * SetConsoleOutputCP [KERNEL32.@] Set the output codepage used by the console
761 * PARAMS
762 * cp [I] code page to set
764 * RETURNS
765 * Success: TRUE
766 * Failure: FALSE
768 BOOL WINAPI SetConsoleOutputCP( UINT cp )
770 FIXME("stub\n");
771 return TRUE;
775 /***********************************************************************
776 * GetConsoleTitleA (KERNEL32.@)
778 DWORD WINAPI GetConsoleTitleA(LPSTR title,DWORD size)
780 DWORD ret = 0;
781 HANDLE hcon;
783 if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ, 0, NULL,
784 OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
785 return 0;
786 SERVER_START_VAR_REQ( get_console_info, REQUEST_MAX_VAR_SIZE )
788 req->handle = hcon;
789 if (!SERVER_CALL_ERR())
791 ret = server_data_size(req);
792 size = min( size-1, ret );
793 memcpy( title, server_data_ptr(req), size );
794 title[size] = 0;
797 SERVER_END_VAR_REQ;
798 CloseHandle( hcon );
799 return ret;
803 /******************************************************************************
804 * GetConsoleTitleW [KERNEL32.@] Retrieves title string for console
806 * PARAMS
807 * title [O] Address of buffer for title
808 * size [I] Size of buffer
810 * RETURNS
811 * Success: Length of string copied
812 * Failure: 0
814 DWORD WINAPI GetConsoleTitleW( LPWSTR title, DWORD size )
816 char *tmp;
817 DWORD ret;
819 if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size*sizeof(WCHAR) ))) return 0;
820 GetConsoleTitleA( tmp, size*sizeof(WCHAR) );
821 ret = MultiByteToWideChar( CP_ACP, 0, tmp, -1, title, size );
822 HeapFree( GetProcessHeap(), 0, tmp );
823 return ret;
827 /***********************************************************************
828 * WriteConsoleA (KERNEL32.@)
830 BOOL WINAPI WriteConsoleA( HANDLE hConsoleOutput,
831 LPCVOID lpBuffer,
832 DWORD nNumberOfCharsToWrite,
833 LPDWORD lpNumberOfCharsWritten,
834 LPVOID lpReserved )
836 /* FIXME: should I check if this is a console handle? */
837 return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
838 lpNumberOfCharsWritten, NULL);
842 #define CADD(c) \
843 if (bufused==curbufsize-1) \
844 buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\
845 buffer[bufused++]=c;
846 #define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}}
848 /***********************************************************************
849 * WriteConsoleOutputA (KERNEL32.@)
851 BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput,
852 LPCHAR_INFO lpBuffer,
853 COORD dwBufferSize,
854 COORD dwBufferCoord,
855 LPSMALL_RECT lpWriteRegion)
857 int i,j,off=0,lastattr=-1;
858 int offbase;
859 char sbuf[20],*buffer=NULL;
860 int bufused=0,curbufsize = 100;
861 DWORD res;
862 CONSOLE_SCREEN_BUFFER_INFO csbi;
863 const int colormap[8] = {
864 0,4,2,6,
865 1,5,3,7,
867 CONSOLE_make_complex(hConsoleOutput);
868 buffer = HeapAlloc(GetProcessHeap(),0,curbufsize);
869 offbase = (dwBufferCoord.Y - 1) * dwBufferSize.X +
870 (dwBufferCoord.X - lpWriteRegion->Left);
872 TRACE("orig rect top = %d, bottom=%d, left=%d, right=%d\n",
873 lpWriteRegion->Top,
874 lpWriteRegion->Bottom,
875 lpWriteRegion->Left,
876 lpWriteRegion->Right
879 GetConsoleScreenBufferInfo(hConsoleOutput, &csbi);
880 sprintf(sbuf,"%c7",27);SADD(sbuf);
882 /* Step 1. Make (Bottom,Right) offset of intersection with
883 Screen Buffer */
884 lpWriteRegion->Bottom = min(lpWriteRegion->Bottom, csbi.dwSize.Y-1) -
885 lpWriteRegion->Top;
886 lpWriteRegion->Right = min(lpWriteRegion->Right, csbi.dwSize.X-1) -
887 lpWriteRegion->Left;
889 /* Step 2. If either offset is negative, then no action
890 should be performed. (Implies that requested rectangle is
891 outside the current screen buffer rectangle.) */
892 if ((lpWriteRegion->Bottom < 0) ||
893 (lpWriteRegion->Right < 0)) {
894 /* readjust (Bottom Right) for rectangle */
895 lpWriteRegion->Bottom += lpWriteRegion->Top;
896 lpWriteRegion->Right += lpWriteRegion->Left;
898 TRACE("invisible rect top = %d, bottom=%d, left=%d, right=%d\n",
899 lpWriteRegion->Top,
900 lpWriteRegion->Bottom,
901 lpWriteRegion->Left,
902 lpWriteRegion->Right
905 HeapFree(GetProcessHeap(),0,buffer);
906 return TRUE;
909 /* Step 3. Intersect with source rectangle */
910 lpWriteRegion->Bottom = lpWriteRegion->Top - dwBufferCoord.Y +
911 min(lpWriteRegion->Bottom + dwBufferCoord.Y, dwBufferSize.Y-1);
912 lpWriteRegion->Right = lpWriteRegion->Left - dwBufferCoord.X +
913 min(lpWriteRegion->Right + dwBufferCoord.X, dwBufferSize.X-1);
915 TRACE("clipped rect top = %d, bottom=%d, left=%d,right=%d\n",
916 lpWriteRegion->Top,
917 lpWriteRegion->Bottom,
918 lpWriteRegion->Left,
919 lpWriteRegion->Right
922 /* Validate above computations made sense, if not then issue
923 error and fudge to single character rectangle */
924 if ((lpWriteRegion->Bottom < lpWriteRegion->Top) ||
925 (lpWriteRegion->Right < lpWriteRegion->Left)) {
926 ERR("Invalid clipped rectangle top = %d, bottom=%d, left=%d,right=%d\n",
927 lpWriteRegion->Top,
928 lpWriteRegion->Bottom,
929 lpWriteRegion->Left,
930 lpWriteRegion->Right
932 lpWriteRegion->Bottom = lpWriteRegion->Top;
933 lpWriteRegion->Right = lpWriteRegion->Left;
936 /* Now do the real processing and move the characters */
937 for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) {
938 offbase += dwBufferSize.X;
939 sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1);
940 SADD(sbuf);
941 for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) {
942 off = j + offbase;
943 if (lastattr!=lpBuffer[off].Attributes) {
944 lastattr = lpBuffer[off].Attributes;
945 sprintf(sbuf,"%c[0;%s3%d;4%dm",
947 (lastattr & FOREGROUND_INTENSITY)?"1;":"",
948 colormap[lastattr&7],
949 colormap[(lastattr&0x70)>>4]
951 /* FIXME: BACKGROUND_INTENSITY */
952 SADD(sbuf);
954 CADD(lpBuffer[off].Char.AsciiChar);
957 sprintf(sbuf,"%c[0m%c8",27,27);SADD(sbuf);
958 WriteFile(hConsoleOutput,buffer,bufused,&res,NULL);
959 HeapFree(GetProcessHeap(),0,buffer);
960 return TRUE;
963 /***********************************************************************
964 * WriteConsoleOutputW (KERNEL32.@)
966 BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput,
967 LPCHAR_INFO lpBuffer,
968 COORD dwBufferSize,
969 COORD dwBufferCoord,
970 LPSMALL_RECT lpWriteRegion)
972 FIXME("(%d,%p,%dx%d,%dx%d,%p): stub\n", hConsoleOutput, lpBuffer,
973 dwBufferSize.X,dwBufferSize.Y,dwBufferCoord.X,dwBufferCoord.Y,lpWriteRegion);
975 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
976 return FALSE;
979 /***********************************************************************
980 * WriteConsoleW (KERNEL32.@)
982 BOOL WINAPI WriteConsoleW( HANDLE hConsoleOutput,
983 LPCVOID lpBuffer,
984 DWORD nNumberOfCharsToWrite,
985 LPDWORD lpNumberOfCharsWritten,
986 LPVOID lpReserved )
988 BOOL ret;
989 LPSTR xstring;
990 DWORD n;
992 n = WideCharToMultiByte(CP_ACP,0,lpBuffer,nNumberOfCharsToWrite,NULL,0,NULL,NULL);
993 xstring=HeapAlloc( GetProcessHeap(), 0, n );
995 n = WideCharToMultiByte(CP_ACP,0,lpBuffer,nNumberOfCharsToWrite,xstring,n,NULL,NULL);
997 /* FIXME: should I check if this is a console handle? */
998 ret= WriteFile(hConsoleOutput, xstring, n,
999 lpNumberOfCharsWritten, NULL);
1000 /* FIXME: lpNumberOfCharsWritten should be converted to numofchars in UNICODE */
1001 HeapFree( GetProcessHeap(), 0, xstring );
1002 return ret;
1006 /***********************************************************************
1007 * ReadConsoleA (KERNEL32.@)
1009 BOOL WINAPI ReadConsoleA( HANDLE hConsoleInput,
1010 LPVOID lpBuffer,
1011 DWORD nNumberOfCharsToRead,
1012 LPDWORD lpNumberOfCharsRead,
1013 LPVOID lpReserved )
1015 DWORD charsread = 0;
1016 LPSTR xbuf = (LPSTR)lpBuffer;
1018 TRACE("(%d,%p,%ld,%p,%p)\n",
1019 hConsoleInput,lpBuffer,nNumberOfCharsToRead,
1020 lpNumberOfCharsRead,lpReserved
1023 CONSOLE_get_input(hConsoleInput,FALSE);
1025 /* FIXME: should we read at least 1 char? The SDK does not say */
1026 while (charsread<nNumberOfCharsToRead)
1028 INPUT_RECORD ir;
1029 DWORD count;
1030 if (!read_console_input( hConsoleInput, &ir, 1, &count, TRUE )) return FALSE;
1031 if (!count) break;
1032 if (ir.EventType != KEY_EVENT) continue;
1033 if (!ir.Event.KeyEvent.bKeyDown) continue;
1034 *xbuf++ = ir.Event.KeyEvent.uChar.AsciiChar;
1035 charsread++;
1037 if (lpNumberOfCharsRead)
1038 *lpNumberOfCharsRead = charsread;
1039 return TRUE;
1042 /***********************************************************************
1043 * ReadConsoleW (KERNEL32.@)
1045 BOOL WINAPI ReadConsoleW( HANDLE hConsoleInput,
1046 LPVOID lpBuffer,
1047 DWORD nNumberOfCharsToRead,
1048 LPDWORD lpNumberOfCharsRead,
1049 LPVOID lpReserved )
1051 BOOL ret;
1052 LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead);
1054 ret = ReadConsoleA(
1055 hConsoleInput,
1056 buf,
1057 nNumberOfCharsToRead,
1058 lpNumberOfCharsRead,
1059 lpReserved
1061 if (ret)
1062 MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nNumberOfCharsToRead );
1064 HeapFree( GetProcessHeap(), 0, buf );
1065 return ret;
1069 /******************************************************************************
1070 * ReadConsoleInputA [KERNEL32.@] Reads data from a console
1072 * PARAMS
1073 * hConsoleInput [I] Handle to console input buffer
1074 * lpBuffer [O] Address of buffer for read data
1075 * nLength [I] Number of records to read
1076 * lpNumberOfEventsRead [O] Address of number of records read
1078 * RETURNS
1079 * Success: TRUE
1080 * Failure: FALSE
1082 BOOL WINAPI ReadConsoleInputA(HANDLE hConsoleInput, LPINPUT_RECORD lpBuffer,
1083 DWORD nLength, LPDWORD lpNumberOfEventsRead)
1085 if (!nLength)
1087 if (lpNumberOfEventsRead) *lpNumberOfEventsRead = 0;
1088 return TRUE;
1091 /* loop until we get at least one event */
1092 for (;;)
1094 DWORD count;
1095 BOOL ret = read_console_input( hConsoleInput, lpBuffer, nLength, &count, TRUE );
1097 if (!ret) return FALSE;
1098 if (count)
1100 if (lpNumberOfEventsRead) *lpNumberOfEventsRead = count;
1101 return TRUE;
1103 CONSOLE_get_input(hConsoleInput,TRUE);
1104 /*WaitForSingleObject( hConsoleInput, INFINITE32 );*/
1109 /***********************************************************************
1110 * ReadConsoleInputW (KERNEL32.@)
1112 BOOL WINAPI ReadConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer,
1113 DWORD count, LPDWORD read )
1115 /* FIXME: Fix this if we get UNICODE input. */
1116 return ReadConsoleInputA( handle, buffer, count, read );
1120 /***********************************************************************
1121 * FlushConsoleInputBuffer (KERNEL32.@)
1123 BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
1125 return read_console_input( handle, NULL, 0, NULL, TRUE );
1129 /***********************************************************************
1130 * PeekConsoleInputA (KERNEL32.@)
1132 * Gets 'count' first events (or less) from input queue.
1134 * Does not need a complex console.
1136 BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD read )
1138 CONSOLE_get_input(handle,FALSE);
1139 if (!count)
1141 if (read) *read = 0;
1142 return TRUE;
1144 return read_console_input( handle, buffer, count, read, FALSE );
1148 /***********************************************************************
1149 * PeekConsoleInputW (KERNEL32.@)
1151 BOOL WINAPI PeekConsoleInputW(HANDLE hConsoleInput,
1152 LPINPUT_RECORD pirBuffer,
1153 DWORD cInRecords,
1154 LPDWORD lpcRead)
1156 /* FIXME: Hmm. Fix this if we get UNICODE input. */
1157 return PeekConsoleInputA(hConsoleInput,pirBuffer,cInRecords,lpcRead);
1161 /******************************************************************************
1162 * WriteConsoleInputA [KERNEL32.@] Write data to a console input buffer
1165 BOOL WINAPI WriteConsoleInputA( HANDLE handle, INPUT_RECORD *buffer,
1166 DWORD count, LPDWORD written )
1168 BOOL ret = TRUE;
1170 if (written) *written = 0;
1171 while (count && ret)
1173 DWORD len = min( count, REQUEST_MAX_VAR_SIZE/sizeof(INPUT_RECORD) );
1174 SERVER_START_VAR_REQ( write_console_input, len * sizeof(INPUT_RECORD) )
1176 req->handle = handle;
1177 memcpy( server_data_ptr(req), buffer, len * sizeof(INPUT_RECORD) );
1178 if ((ret = !SERVER_CALL_ERR()))
1180 if (written) *written += req->written;
1181 count -= len;
1182 buffer += len;
1185 SERVER_END_VAR_REQ;
1187 return ret;
1190 /******************************************************************************
1191 * WriteConsoleInputW [KERNEL32.@] Write data to a console input buffer
1194 BOOL WINAPI WriteConsoleInputW( HANDLE handle, INPUT_RECORD *buffer,
1195 DWORD count, LPDWORD written )
1197 FIXME("(%d,%p,%ld,%p): stub!\n", handle, buffer, count, written);
1199 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1200 return FALSE;
1204 /***********************************************************************
1205 * SetConsoleTitleA (KERNEL32.@)
1207 * Sets the console title.
1209 * We do not necessarily need to create a complex console for that,
1210 * but should remember the title and set it on creation of the latter.
1211 * (not fixed at this time).
1213 BOOL WINAPI SetConsoleTitleA(LPCSTR title)
1215 size_t len = strlen(title);
1216 HANDLE hcon;
1217 DWORD written;
1218 BOOL ret;
1220 if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
1221 OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
1222 return FALSE;
1224 len = min( len, REQUEST_MAX_VAR_SIZE );
1225 SERVER_START_VAR_REQ( set_console_info, len )
1227 req->handle = hcon;
1228 req->mask = SET_CONSOLE_INFO_TITLE;
1229 memcpy( server_data_ptr(req), title, len );
1230 ret = !SERVER_CALL_ERR();
1232 SERVER_END_VAR_REQ;
1234 if (ret && CONSOLE_GetPid( hcon ))
1236 /* only set title for complex console (own xterm) */
1237 WriteFile( hcon, "\033]2;", 4, &written, NULL );
1238 WriteFile( hcon, title, strlen(title), &written, NULL );
1239 WriteFile( hcon, "\a", 1, &written, NULL );
1241 CloseHandle( hcon );
1242 return ret;
1246 /******************************************************************************
1247 * SetConsoleTitleW [KERNEL32.@] Sets title bar string for console
1249 * PARAMS
1250 * title [I] Address of new title
1252 * NOTES
1253 * This should not be calling the A version
1255 * RETURNS
1256 * Success: TRUE
1257 * Failure: FALSE
1259 BOOL WINAPI SetConsoleTitleW( LPCWSTR title )
1261 BOOL ret;
1263 LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1264 ret = SetConsoleTitleA(titleA);
1265 HeapFree( GetProcessHeap(), 0, titleA );
1266 return ret;
1269 /******************************************************************************
1270 * SetConsoleCursorPosition [KERNEL32.@]
1271 * Sets the cursor position in console
1273 * PARAMS
1274 * hConsoleOutput [I] Handle of console screen buffer
1275 * dwCursorPosition [I] New cursor position coordinates
1277 * RETURNS STD
1279 BOOL WINAPI SetConsoleCursorPosition( HANDLE hcon, COORD pos )
1281 char xbuf[20];
1282 DWORD xlen;
1284 /* make console complex only if we change lines, not just in the line */
1285 if (pos.Y)
1286 CONSOLE_make_complex(hcon);
1288 TRACE("%d (%dx%d)\n", hcon, pos.X , pos.Y );
1289 /* x are columns, y rows */
1290 if (pos.Y)
1291 /* full screen cursor absolute positioning */
1292 sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.Y+1, pos.X+1);
1293 else
1294 /* relative cursor positioning in line (\r to go to 0) */
1295 sprintf(xbuf,"\r%c[%dC", 0x1B, pos.X);
1296 /* FIXME: store internal if we start using own console buffers */
1297 WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL);
1298 return TRUE;
1301 /***********************************************************************
1302 * GetNumberOfConsoleInputEvents (KERNEL32.@)
1304 BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hcon,LPDWORD nrofevents)
1306 CONSOLE_get_input (hcon, FALSE);
1308 return read_console_input( hcon, NULL, 0, nrofevents, FALSE );
1311 /***********************************************************************
1312 * GetNumberOfConsoleMouseButtons (KERNEL32.@)
1314 BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
1316 FIXME("(%p): stub\n", nrofbuttons);
1317 *nrofbuttons = 2;
1318 return TRUE;
1321 /******************************************************************************
1322 * GetConsoleCursorInfo [KERNEL32.@] Gets size and visibility of console
1324 * PARAMS
1325 * hcon [I] Handle to console screen buffer
1326 * cinfo [O] Address of cursor information
1328 * RETURNS
1329 * Success: TRUE
1330 * Failure: FALSE
1332 BOOL WINAPI GetConsoleCursorInfo( HANDLE hcon, LPCONSOLE_CURSOR_INFO cinfo )
1334 BOOL ret;
1336 SERVER_START_REQ( get_console_info )
1338 req->handle = hcon;
1339 ret = !SERVER_CALL_ERR();
1340 if (ret && cinfo)
1342 cinfo->dwSize = req->cursor_size;
1343 cinfo->bVisible = req->cursor_visible;
1346 SERVER_END_REQ;
1347 return ret;
1351 /******************************************************************************
1352 * SetConsoleCursorInfo [KERNEL32.@] Sets size and visibility of cursor
1354 * RETURNS
1355 * Success: TRUE
1356 * Failure: FALSE
1358 BOOL WINAPI SetConsoleCursorInfo(
1359 HANDLE hcon, /* [in] Handle to console screen buffer */
1360 LPCONSOLE_CURSOR_INFO cinfo) /* [in] Address of cursor information */
1362 char buf[8];
1363 DWORD xlen;
1364 BOOL ret;
1366 CONSOLE_make_complex(hcon);
1367 sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l');
1368 WriteFile(hcon,buf,strlen(buf),&xlen,NULL);
1370 SERVER_START_REQ( set_console_info )
1372 req->handle = hcon;
1373 req->cursor_size = cinfo->dwSize;
1374 req->cursor_visible = cinfo->bVisible;
1375 req->mask = SET_CONSOLE_INFO_CURSOR;
1376 ret = !SERVER_CALL_ERR();
1378 SERVER_END_REQ;
1379 return ret;
1383 /******************************************************************************
1384 * SetConsoleWindowInfo [KERNEL32.@] Sets size and position of console
1386 * RETURNS
1387 * Success: TRUE
1388 * Failure: FALSE
1390 BOOL WINAPI SetConsoleWindowInfo(
1391 HANDLE hcon, /* [in] Handle to console screen buffer */
1392 BOOL bAbsolute, /* [in] Coordinate type flag */
1393 LPSMALL_RECT window) /* [in] Address of new window rectangle */
1395 FIXME("(%x,%d,%p): stub\n", hcon, bAbsolute, window);
1396 return TRUE;
1400 /******************************************************************************
1401 * SetConsoleTextAttribute [KERNEL32.@] Sets colors for text
1403 * Sets the foreground and background color attributes of characters
1404 * written to the screen buffer.
1406 * RETURNS
1407 * Success: TRUE
1408 * Failure: FALSE
1410 BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttr)
1412 const int colormap[8] = {
1413 0,4,2,6,
1414 1,5,3,7,
1416 DWORD xlen;
1417 char buffer[20];
1419 TRACE("(%d,%d)\n",hConsoleOutput,wAttr);
1420 sprintf(buffer,"%c[0;%s3%d;4%dm",
1422 (wAttr & FOREGROUND_INTENSITY)?"1;":"",
1423 colormap[wAttr&7],
1424 colormap[(wAttr&0x70)>>4]
1426 WriteFile(hConsoleOutput,buffer,strlen(buffer),&xlen,NULL);
1427 return TRUE;
1431 /******************************************************************************
1432 * SetConsoleScreenBufferSize [KERNEL32.@] Changes size of console
1434 * PARAMS
1435 * hConsoleOutput [I] Handle to console screen buffer
1436 * dwSize [I] New size in character rows and cols
1438 * RETURNS
1439 * Success: TRUE
1440 * Failure: FALSE
1442 BOOL WINAPI SetConsoleScreenBufferSize( HANDLE hConsoleOutput,
1443 COORD dwSize )
1445 FIXME("(%d,%dx%d): stub\n",hConsoleOutput,dwSize.X,dwSize.Y);
1446 return TRUE;
1450 /******************************************************************************
1451 * FillConsoleOutputCharacterA [KERNEL32.@]
1453 * PARAMS
1454 * hConsoleOutput [I] Handle to screen buffer
1455 * cCharacter [I] Character to write
1456 * nLength [I] Number of cells to write to
1457 * dwCoord [I] Coords of first cell
1458 * lpNumCharsWritten [O] Pointer to number of cells written
1460 * RETURNS
1461 * Success: TRUE
1462 * Failure: FALSE
1464 BOOL WINAPI FillConsoleOutputCharacterA(
1465 HANDLE hConsoleOutput,
1466 BYTE cCharacter,
1467 DWORD nLength,
1468 COORD dwCoord,
1469 LPDWORD lpNumCharsWritten)
1471 DWORD count;
1472 DWORD xlen;
1474 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1475 for(count=0;count<nLength;count++)
1476 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
1477 *lpNumCharsWritten = nLength;
1478 return TRUE;
1482 /******************************************************************************
1483 * FillConsoleOutputCharacterW [KERNEL32.@] Writes characters to console
1485 * PARAMS
1486 * hConsoleOutput [I] Handle to screen buffer
1487 * cCharacter [I] Character to write
1488 * nLength [I] Number of cells to write to
1489 * dwCoord [I] Coords of first cell
1490 * lpNumCharsWritten [O] Pointer to number of cells written
1492 * RETURNS
1493 * Success: TRUE
1494 * Failure: FALSE
1496 BOOL WINAPI FillConsoleOutputCharacterW(HANDLE hConsoleOutput,
1497 WCHAR cCharacter,
1498 DWORD nLength,
1499 COORD dwCoord,
1500 LPDWORD lpNumCharsWritten)
1502 DWORD count;
1503 DWORD xlen;
1505 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1506 /* FIXME: not quite correct ... but the lower part of UNICODE char comes
1507 * first
1509 for(count=0;count<nLength;count++)
1510 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
1511 *lpNumCharsWritten = nLength;
1512 return TRUE;
1516 /******************************************************************************
1517 * FillConsoleOutputAttribute [KERNEL32.@] Sets attributes for console
1519 * PARAMS
1520 * hConsoleOutput [I] Handle to screen buffer
1521 * wAttribute [I] Color attribute to write
1522 * nLength [I] Number of cells to write to
1523 * dwCoord [I] Coords of first cell
1524 * lpNumAttrsWritten [O] Pointer to number of cells written
1526 * RETURNS
1527 * Success: TRUE
1528 * Failure: FALSE
1530 BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput,
1531 WORD wAttribute, DWORD nLength, COORD dwCoord,
1532 LPDWORD lpNumAttrsWritten)
1534 FIXME("(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1535 wAttribute,nLength,dwCoord.X,dwCoord.Y,lpNumAttrsWritten);
1536 *lpNumAttrsWritten = nLength;
1537 return TRUE;
1540 /******************************************************************************
1541 * ReadConsoleOutputCharacterA [KERNEL32.@]
1543 * BUGS
1544 * Unimplemented
1546 BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput,
1547 LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1549 FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1550 dword,coord.X,coord.Y,lpdword);
1551 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1552 return FALSE;
1555 /******************************************************************************
1556 * ReadConsoleOutputCharacterW [KERNEL32.@]
1558 * BUGS
1559 * Unimplemented
1561 BOOL WINAPI ReadConsoleOutputCharacterW(HANDLE hConsoleOutput,
1562 LPWSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1564 FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1565 dword,coord.X,coord.Y,lpdword);
1566 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1567 return FALSE;
1571 /******************************************************************************
1572 * ScrollConsoleScreenBufferA [KERNEL32.@]
1574 * BUGS
1575 * Unimplemented
1577 BOOL WINAPI ScrollConsoleScreenBufferA( HANDLE hConsoleOutput,
1578 LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1579 COORD dwDestOrigin, LPCHAR_INFO lpFill)
1581 FIXME("(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1582 lpClipRect,dwDestOrigin.X,dwDestOrigin.Y,lpFill);
1583 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1584 return FALSE;
1587 /******************************************************************************
1588 * ScrollConsoleScreenBufferW [KERNEL32.@]
1590 * BUGS
1591 * Unimplemented
1593 BOOL WINAPI ScrollConsoleScreenBufferW( HANDLE hConsoleOutput,
1594 LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1595 COORD dwDestOrigin, LPCHAR_INFO lpFill)
1597 FIXME("(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1598 lpClipRect,dwDestOrigin.X,dwDestOrigin.Y,lpFill);
1599 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1600 return FALSE;
1603 /******************************************************************************
1604 * ReadConsoleOutputA [KERNEL32.@]
1606 * BUGS
1607 * Unimplemented
1609 BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput,
1610 LPCHAR_INFO lpBuffer,
1611 COORD dwBufferSize,
1612 COORD dwBufferCoord,
1613 LPSMALL_RECT lpReadRegion )
1615 FIXME("(%d,%p,%dx%d,%dx%d,%p): stub\n", hConsoleOutput, lpBuffer,
1616 dwBufferSize.X, dwBufferSize.Y, dwBufferSize.X, dwBufferSize.Y,
1617 lpReadRegion);
1619 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1620 return FALSE;
1623 /******************************************************************************
1624 * ReadConsoleOutputW [KERNEL32.@]
1626 * BUGS
1627 * Unimplemented
1629 BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput,
1630 LPCHAR_INFO lpBuffer,
1631 COORD dwBufferSize,
1632 COORD dwBufferCoord,
1633 LPSMALL_RECT lpReadRegion )
1635 FIXME("(%d,%p,%dx%d,%dx%d,%p): stub\n", hConsoleOutput, lpBuffer,
1636 dwBufferSize.X, dwBufferSize.Y, dwBufferSize.X, dwBufferSize.Y,
1637 lpReadRegion);
1639 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1640 return FALSE;
1643 /******************************************************************************
1644 * ReadConsoleOutputAttribute [KERNEL32.@]
1646 * BUGS
1647 * Unimplemented
1649 BOOL WINAPI ReadConsoleOutputAttribute( HANDLE hConsoleOutput,
1650 LPWORD lpAttribute,
1651 DWORD nLength,
1652 COORD dwReadCoord,
1653 LPDWORD lpNumberOfAttrsRead)
1655 FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput, lpAttribute,
1656 nLength, dwReadCoord.X, dwReadCoord.Y, lpNumberOfAttrsRead);
1658 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1659 return FALSE;
1662 /******************************************************************************
1663 * SetConsoleCP [KERNEL32.@]
1665 * BUGS
1666 * Unimplemented
1668 BOOL WINAPI SetConsoleCP( UINT cp )
1670 FIXME("(%d): stub\n", cp);
1672 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1673 return FALSE;
1676 /******************************************************************************
1677 * SetConsoleInputExeNameW [KERNEL32.@]
1679 * BUGS
1680 * Unimplemented
1682 BOOL WINAPI SetConsoleInputExeNameW( LPCWSTR name )
1684 FIXME("(%s): stub!\n", debugstr_w(name));
1686 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1687 return TRUE;
1690 /******************************************************************************
1691 * SetConsoleInputExeNameA [KERNEL32.@]
1693 * BUGS
1694 * Unimplemented
1696 BOOL WINAPI SetConsoleInputExeNameA( LPCSTR name )
1698 FIXME("(%s): stub!\n", name);
1700 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1701 return TRUE;
1704 /******************************************************************************
1705 * WriteConsoleOutputAttribute [KERNEL32.@] Sets attributes for some cells in
1706 * the console screen buffer
1708 * PARAMS
1709 * hConsoleOutput [I] Handle to screen buffer
1710 * lpAttribute [I] Pointer to buffer with write attributes
1711 * nLength [I] Number of cells to write to
1712 * dwCoord [I] Coords of first cell
1713 * lpNumAttrsWritten [O] Pointer to number of cells written
1715 * RETURNS
1716 * Success: TRUE
1717 * Failure: FALSE
1719 * BUGS
1720 * Unimplemented
1722 BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput,
1723 CONST WORD *lpAttribute, DWORD nLength, COORD dwCoord,
1724 LPDWORD lpNumAttrsWritten)
1726 FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1727 lpAttribute,nLength,dwCoord.X,dwCoord.Y,lpNumAttrsWritten);
1728 *lpNumAttrsWritten = nLength;
1729 return TRUE;
1732 /******************************************************************************
1733 * WriteConsoleOutputCharacterA [KERNEL32.@] Copies character to consecutive
1734 * cells in the console screen buffer
1736 * PARAMS
1737 * hConsoleOutput [I] Handle to screen buffer
1738 * lpCharacter [I] Pointer to buffer with chars to write
1739 * nLength [I] Number of cells to write to
1740 * dwCoord [I] Coords of first cell
1741 * lpNumCharsWritten [O] Pointer to number of cells written
1743 * BUGS
1744 * Unimplemented
1746 BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput,
1747 LPCSTR lpCharacter, DWORD nLength, COORD dwCoord,
1748 LPDWORD lpNumCharsWritten)
1750 FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1751 lpCharacter,nLength,dwCoord.X,dwCoord.Y,lpNumCharsWritten);
1752 *lpNumCharsWritten = nLength;
1753 return TRUE;
1756 /******************************************************************************
1757 * WriteConsoleOutputCharacterW [KERNEL32.@] Copies character to consecutive
1758 * cells in the console screen buffer
1760 * PARAMS
1761 * hConsoleOutput [I] Handle to screen buffer
1762 * lpCharacter [I] Pointer to buffer with chars to write
1763 * nLength [I] Number of cells to write to
1764 * dwCoord [I] Coords of first cell
1765 * lpNumCharsWritten [O] Pointer to number of cells written
1767 * RETURNS
1768 * Success: TRUE
1769 * Failure: FALSE
1771 * BUGS
1772 * Unimplemented
1774 BOOL WINAPI WriteConsoleOutputCharacterW( HANDLE hConsoleOutput,
1775 LPCWSTR lpCharacter, DWORD nLength, COORD dwCoord,
1776 LPDWORD lpNumCharsWritten)
1778 FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1779 lpCharacter,nLength,dwCoord.X,dwCoord.Y,lpNumCharsWritten);
1780 *lpNumCharsWritten = nLength;
1781 return TRUE;