Large-scale renaming of all Win32 functions and types to use the
[wine] / win32 / console.c
1 /*
2  * Win32 kernel functions
3  *
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  */
9
10 /* FIXME:
11  * - 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.
20  */
21
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <termios.h>
25 #include <strings.h>
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <sys/errno.h>
33 #include <signal.h>
34 #include <assert.h>
35
36 #include "winbase.h"
37 #include "wine/winuser16.h"
38 #include "wine/keyboard16.h"
39 #include "k32obj.h"
40 #include "thread.h"
41 #include "async.h"
42 #include "file.h"
43 #include "process.h"
44 #include "winerror.h"
45 #include "wincon.h"
46 #include "heap.h"
47 #include "debug.h"
48
49 #include "server/request.h"
50 #include "server.h"
51
52 /* The CONSOLE kernel32 Object */
53 typedef struct _CONSOLE {
54         K32OBJ                  header;
55 } CONSOLE;
56
57 /* FIXME:  Should be in an internal header file.  OK, so which one?
58    Used by CONSOLE_makecomplex. */
59 FILE *wine_openpty(int *master, int *slave, char *name,
60                    struct termios *term, struct winsize *winsize);
61
62 /****************************************************************************
63  *              CONSOLE_GetInfo
64  */
65 static BOOL CONSOLE_GetInfo( HANDLE handle, struct get_console_info_reply *reply )
66 {
67     struct get_console_info_request req;
68
69     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
70                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
71         return FALSE;
72     CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
73     return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
74 }
75
76 /****************************************************************************
77  *              XTERM_string_to_IR                      [internal]
78  *
79  * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the
80  * queue. Does translation of vt100 style function keys and xterm-mouse clicks.
81  */
82 static void
83 CONSOLE_string_to_IR( HANDLE hConsoleInput,unsigned char *buf,int len) {
84     int                 j,k;
85     INPUT_RECORD        ir;
86     DWORD               junk;
87
88     for (j=0;j<len;j++) {
89         unsigned char inchar = buf[j];
90
91         if (inchar!=27) { /* no escape -> 'normal' keyboard event */
92             ir.EventType = 1; /* Key_event */
93
94             ir.Event.KeyEvent.bKeyDown          = 1;
95             ir.Event.KeyEvent.wRepeatCount      = 0;
96
97             ir.Event.KeyEvent.dwControlKeyState = 0;
98             if (inchar & 0x80) {
99                 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
100                 inchar &= ~0x80;
101             }
102             ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(inchar);
103             if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100)
104                 ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED;
105             if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200)
106                 ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED;
107             if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400)
108                 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
109             ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
110                 ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff,
111                 0 /* VirtualKeyCodes to ScanCode */
112             );
113             ir.Event.KeyEvent.uChar.AsciiChar = inchar;
114
115             if (inchar==127) { /* backspace */
116                 ir.Event.KeyEvent.uChar.AsciiChar = '\b'; /* FIXME: hmm */
117                 ir.Event.KeyEvent.wVirtualScanCode = 0x0e;
118                 ir.Event.KeyEvent.wVirtualKeyCode = VK_BACK;
119             } else {
120                 if (inchar=='\n') {
121                     ir.Event.KeyEvent.uChar.AsciiChar   = '\r';
122                     ir.Event.KeyEvent.wVirtualKeyCode   = VK_RETURN;
123                     ir.Event.KeyEvent.wVirtualScanCode  = 0x1c;
124                 } else {
125                     if (inchar<' ') {
126                         /* FIXME: find good values for ^X */
127                         ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;
128                         ir.Event.KeyEvent.wVirtualScanCode = 0xbeef;
129                     } 
130                 }
131             }
132
133             assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
134             ir.Event.KeyEvent.bKeyDown = 0;
135             assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
136             continue;
137         }
138         /* inchar is ESC */
139         if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */
140             ir.EventType = 1; /* Key_event */
141             ir.Event.KeyEvent.bKeyDown          = 1;
142             ir.Event.KeyEvent.wRepeatCount      = 0;
143
144             ir.Event.KeyEvent.wVirtualKeyCode   = VkKeyScan16(27);
145             ir.Event.KeyEvent.wVirtualScanCode  = MapVirtualKey16(
146                 ir.Event.KeyEvent.wVirtualKeyCode,0
147             );
148             ir.Event.KeyEvent.dwControlKeyState = 0;
149             ir.Event.KeyEvent.uChar.AsciiChar   = 27;
150             assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
151             ir.Event.KeyEvent.bKeyDown = 0;
152             assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
153             continue;
154         }
155         for (k=j;k<len;k++) {
156             if (((buf[k]>='A') && (buf[k]<='Z')) ||
157                 ((buf[k]>='a') && (buf[k]<='z')) ||
158                  (buf[k]=='~')
159             )
160                 break;
161         }
162         if (k<len) {
163             int subid,scancode=0;
164
165             ir.EventType                        = 1; /* Key_event */
166             ir.Event.KeyEvent.bKeyDown          = 1;
167             ir.Event.KeyEvent.wRepeatCount      = 0;
168             ir.Event.KeyEvent.dwControlKeyState = 0;
169
170             ir.Event.KeyEvent.wVirtualKeyCode   = 0xad; /* FIXME */
171             ir.Event.KeyEvent.wVirtualScanCode  = 0xad; /* FIXME */
172             ir.Event.KeyEvent.uChar.AsciiChar   = 0;
173
174             switch (buf[k]) {
175             case '~':
176                 sscanf(&buf[j+2],"%d",&subid);
177                 switch (subid) {
178                 case  2:/*INS */scancode = 0xe052;break;
179                 case  3:/*DEL */scancode = 0xe053;break;
180                 case  6:/*PGDW*/scancode = 0xe051;break;
181                 case  5:/*PGUP*/scancode = 0xe049;break;
182                 case 11:/*F1  */scancode = 0x003b;break;
183                 case 12:/*F2  */scancode = 0x003c;break;
184                 case 13:/*F3  */scancode = 0x003d;break;
185                 case 14:/*F4  */scancode = 0x003e;break;
186                 case 15:/*F5  */scancode = 0x003f;break;
187                 case 17:/*F6  */scancode = 0x0040;break;
188                 case 18:/*F7  */scancode = 0x0041;break;
189                 case 19:/*F8  */scancode = 0x0042;break;
190                 case 20:/*F9  */scancode = 0x0043;break;
191                 case 21:/*F10 */scancode = 0x0044;break;
192                 case 23:/*F11 */scancode = 0x00d9;break;
193                 case 24:/*F12 */scancode = 0x00da;break;
194                 /* FIXME: Shift-Fx */
195                 default:
196                         FIXME(console,"parse ESC[%d~\n",subid);
197                         break;
198                 }
199                 break;
200             case 'A': /* Cursor Up    */scancode = 0xe048;break;
201             case 'B': /* Cursor Down  */scancode = 0xe050;break;
202             case 'D': /* Cursor Left  */scancode = 0xe04b;break;
203             case 'C': /* Cursor Right */scancode = 0xe04d;break;
204             case 'F': /* End          */scancode = 0xe04f;break;
205             case 'H': /* Home         */scancode = 0xe047;break;
206             case 'M':
207                 /* Mouse Button Press  (ESCM<button+'!'><x+'!'><y+'!'>) or
208                  *              Release (ESCM#<x+'!'><y+'!'>
209                  */
210                 if (k<len-3) {
211                     ir.EventType                        = MOUSE_EVENT;
212                     ir.Event.MouseEvent.dwMousePosition.x = buf[k+2]-'!';
213                     ir.Event.MouseEvent.dwMousePosition.y = buf[k+3]-'!';
214                     if (buf[k+1]=='#')
215                         ir.Event.MouseEvent.dwButtonState = 0;
216                     else
217                         ir.Event.MouseEvent.dwButtonState = 1<<(buf[k+1]-' ');
218                     ir.Event.MouseEvent.dwEventFlags      = 0; /* FIXME */
219                     assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk));
220                     j=k+3;
221                 }
222                 break;
223                 
224             }
225             if (scancode) {
226                 ir.Event.KeyEvent.wVirtualScanCode = scancode;
227                 ir.Event.KeyEvent.wVirtualKeyCode = MapVirtualKey16(scancode,1);
228                 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
229                 ir.Event.KeyEvent.bKeyDown              = 0;
230                 assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk ));
231                 j=k;
232                 continue;
233             }
234         }
235     }
236 }
237
238 /****************************************************************************
239  *              CONSOLE_get_input               (internal)
240  *
241  * Reads (nonblocking) as much input events as possible and stores them
242  * in an internal queue.
243  */
244 static void
245 CONSOLE_get_input( HANDLE handle, BOOL blockwait )
246 {
247     char        *buf = HeapAlloc(GetProcessHeap(),0,1);
248     int         len = 0;
249
250     while (1)
251     {
252         DWORD res;
253         char inchar;
254         if (WaitForSingleObject( handle, 0 )) break;
255         if (!ReadFile( handle, &inchar, 1, &res, NULL )) break;
256         if (!res) /* res 0 but readable means EOF? Hmm. */
257                 break;
258         buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1);
259         buf[len++]=inchar;
260     }
261     CONSOLE_string_to_IR(handle,buf,len);
262     HeapFree(GetProcessHeap(),0,buf);
263 }
264
265 /******************************************************************************
266  * SetConsoleCtrlHandler [KERNEL32.459]  Adds function to calling process list
267  *
268  * PARAMS
269  *    func [I] Address of handler function
270  *    add  [I] Handler to add or remove
271  *
272  * RETURNS
273  *    Success: TRUE
274  *    Failure: FALSE
275  *
276  * CHANGED
277  * James Sutherland (JamesSutherland@gmx.de)
278  * Added global variables console_ignore_ctrl_c and handlers[]
279  * Does not yet do any error checking, or set LastError if failed.
280  * This doesn't yet matter, since these handlers are not yet called...!
281  */
282 static unsigned int console_ignore_ctrl_c = 0;
283 static HANDLER_ROUTINE *handlers[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
284 BOOL WINAPI SetConsoleCtrlHandler( HANDLER_ROUTINE *func, BOOL add )
285 {
286   unsigned int alloc_loop = sizeof(handlers)/sizeof(HANDLER_ROUTINE *);
287   unsigned int done = 0;
288   FIXME(console, "(%p,%i) - no error checking or testing yet\n", func, add);
289   if (!func)
290     {
291       console_ignore_ctrl_c = add;
292       return TRUE;
293     }
294   if (add)
295       {
296         for (;alloc_loop--;)
297           if (!handlers[alloc_loop] && !done)
298             {
299               handlers[alloc_loop] = func;
300               done++;
301             }
302         if (!done)
303            FIXME(console, "Out of space on CtrlHandler table\n");
304         return(done);
305       }
306     else
307       {
308         for (;alloc_loop--;)
309           if (handlers[alloc_loop] == func && !done)
310             {
311               handlers[alloc_loop] = 0;
312               done++;
313             }
314         if (!done)
315            WARN(console, "Attempt to remove non-installed CtrlHandler %p\n",
316                 func);
317         return (done);
318       }
319     return (done);
320 }
321
322
323 /******************************************************************************
324  * GenerateConsoleCtrlEvent [KERNEL32.275] Simulate a CTRL-C or CTRL-BREAK
325  *
326  * PARAMS
327  *    dwCtrlEvent        [I] Type of event
328  *    dwProcessGroupID   [I] Process group ID to send event to
329  *
330  * NOTES
331  *    Doesn't yet work...!
332  *
333  * RETURNS
334  *    Success: True
335  *    Failure: False (and *should* [but doesn't] set LastError)
336  */
337 BOOL WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent,
338                                         DWORD dwProcessGroupID )
339 {
340   if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
341     {
342       ERR( console, "invalid event %d for PGID %ld\n", 
343            (unsigned short)dwCtrlEvent, dwProcessGroupID );
344       return FALSE;
345     }
346   if (dwProcessGroupID == GetCurrentProcessId() )
347     {
348       FIXME( console, "Attempt to send event %d to self - stub\n",
349              (unsigned short)dwCtrlEvent );
350       return FALSE;
351     }
352   FIXME( console,"event %d to external PGID %ld - not implemented yet\n",
353          (unsigned short)dwCtrlEvent, dwProcessGroupID );
354   return FALSE;
355 }
356
357
358 /******************************************************************************
359  * CreateConsoleScreenBuffer [KERNEL32.151]  Creates a console screen buffer
360  *
361  * PARAMS
362  *    dwDesiredAccess    [I] Access flag
363  *    dwShareMode        [I] Buffer share mode
364  *    sa                 [I] Security attributes
365  *    dwFlags            [I] Type of buffer to create
366  *    lpScreenBufferData [I] Reserved
367  *
368  * NOTES
369  *    Should call SetLastError
370  *
371  * RETURNS
372  *    Success: Handle to new console screen buffer
373  *    Failure: INVALID_HANDLE_VALUE
374  */
375 HANDLE WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
376                 DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa,
377                 DWORD dwFlags, LPVOID lpScreenBufferData )
378 {
379     FIXME(console, "(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess,
380           dwShareMode, sa, dwFlags, lpScreenBufferData);
381     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
382     return INVALID_HANDLE_VALUE;
383 }
384
385
386 /***********************************************************************
387  *           GetConsoleScreenBufferInfo   (KERNEL32.190)
388  */
389 BOOL WINAPI GetConsoleScreenBufferInfo( HANDLE hConsoleOutput,
390                                           LPCONSOLE_SCREEN_BUFFER_INFO csbi )
391 {
392     csbi->dwSize.x = 80;
393     csbi->dwSize.y = 24;
394     csbi->dwCursorPosition.x = 0;
395     csbi->dwCursorPosition.y = 0;
396     csbi->wAttributes = 0;
397     csbi->srWindow.Left = 0;
398     csbi->srWindow.Right        = 79;
399     csbi->srWindow.Top  = 0;
400     csbi->srWindow.Bottom       = 23;
401     csbi->dwMaximumWindowSize.x = 80;
402     csbi->dwMaximumWindowSize.y = 24;
403     return TRUE;
404 }
405
406
407 /******************************************************************************
408  * SetConsoleActiveScreenBuffer [KERNEL32.623]  Sets buffer to current console
409  *
410  * RETURNS
411  *    Success: TRUE
412  *    Failure: FALSE
413  */
414 BOOL WINAPI SetConsoleActiveScreenBuffer(
415     HANDLE hConsoleOutput) /* [in] Handle to console screen buffer */
416 {
417     FIXME(console, "(%x): stub\n", hConsoleOutput);
418     return FALSE;
419 }
420
421
422 /***********************************************************************
423  *            GetLargestConsoleWindowSize   (KERNEL32.226)
424  */
425 DWORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput )
426 {
427     return (DWORD)MAKELONG(80,24);
428 }
429
430 /***********************************************************************
431  *            FreeConsole (KERNEL32.267)
432  */
433 BOOL WINAPI FreeConsole(VOID)
434 {
435
436         PDB *pdb = PROCESS_Current();
437         CONSOLE *console;
438
439         SYSTEM_LOCK();
440
441         console = (CONSOLE *)pdb->console;
442
443         if (console == NULL) {
444                 SetLastError(ERROR_INVALID_PARAMETER);
445                 return FALSE;
446         }
447
448         CLIENT_SendRequest( REQ_FREE_CONSOLE, -1, 0 );
449         if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS)
450         {
451             K32OBJ_DecCount(&console->header);
452             SYSTEM_UNLOCK();
453             return FALSE;
454         }
455
456         HANDLE_CloseAll( pdb, &console->header );
457         K32OBJ_DecCount( &console->header );
458         pdb->console = NULL;
459         SYSTEM_UNLOCK();
460         return TRUE;
461 }
462
463
464 /*************************************************************************
465  *              CONSOLE_OpenHandle
466  *
467  * Open a handle to the current process console.
468  */
469 HANDLE CONSOLE_OpenHandle( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES sa )
470 {
471     struct open_console_request req;
472     struct open_console_reply reply;
473     CONSOLE *console;
474     HANDLE handle;
475
476     req.output  = output;
477     req.access  = access;
478     req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
479     CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
480     CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
481     if (reply.handle == -1) return INVALID_HANDLE_VALUE;
482
483     SYSTEM_LOCK();
484     if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console))))
485     {
486         SYSTEM_UNLOCK();
487         return FALSE;
488     }
489     console->header.type     = K32OBJ_CONSOLE;
490     console->header.refcount = 1;
491     handle = HANDLE_Alloc( PROCESS_Current(), &console->header, req.access,
492                            req.inherit, reply.handle );
493     SYSTEM_UNLOCK();
494     K32OBJ_DecCount(&console->header);
495     return handle;
496 }
497
498
499 /*************************************************************************
500  *              CONSOLE_make_complex                    [internal]
501  *
502  * Turns a CONSOLE kernel object into a complex one.
503  * (switches from output/input using the terminal where WINE was started to 
504  * its own xterm).
505  * 
506  * This makes simple commandline tools pipeable, while complex commandline 
507  * tools work without getting messed up by debugoutput.
508  * 
509  * All other functions should work indedependend from this call.
510  *
511  * To test for complex console: pid == 0 -> simple, otherwise complex.
512  */
513 static BOOL CONSOLE_make_complex(HANDLE handle)
514 {
515         struct set_console_fd_request req;
516         struct get_console_info_reply info;
517         struct termios term;
518         char buf[256];
519         char c = '\0';
520         int status = 0;
521         int i,xpid,master,slave;
522         DWORD   xlen;
523
524         if (!CONSOLE_GetInfo( handle, &info )) return FALSE;
525         if (info.pid) return TRUE; /* already complex */
526
527         MSG("Console: Making console complex (creating an xterm)...\n");
528
529         if (tcgetattr(0, &term) < 0) {
530                 /* ignore failure, or we can't run from a script */
531         }
532         term.c_lflag = ~(ECHO|ICANON);
533
534         if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
535                                                   K32OBJ_CONSOLE, 0 )) == -1)
536             return FALSE;
537
538         if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0)
539             return FALSE;
540
541         if ((xpid=fork()) == 0) {
542                 tcsetattr(slave, TCSADRAIN, &term);
543                 sprintf(buf, "-Sxx%d", master);
544                 /* "-fn vga" for VGA font. Harmless if vga is not present:
545                  *  xterm: unable to open font "vga", trying "fixed".... 
546                  */
547                 execlp("xterm", "xterm", buf, "-fn","vga",NULL);
548                 ERR(console, "error creating AllocConsole xterm\n");
549                 exit(1);
550         }
551
552         req.pid = xpid;
553         CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1, &req, sizeof(req) );
554         CLIENT_WaitReply( NULL, NULL, 0 );
555
556         /* most xterms like to print their window ID when used with -S;
557          * read it and continue before the user has a chance...
558          */
559         for (i=0; c!='\n'; (status=read(slave, &c, 1)), i++) {
560                 if (status == -1 && c == '\0') {
561                                 /* wait for xterm to be created */
562                         usleep(100);
563                 }
564                 if (i > 10000) {
565                         ERR(console, "can't read xterm WID\n");
566                         kill(xpid, SIGKILL);
567                         return FALSE;
568                 }
569         }
570         /* enable mouseclicks */
571         sprintf(buf,"%c[?1001s%c[?1000h",27,27);
572         WriteFile(handle,buf,strlen(buf),&xlen,NULL);
573         
574         if (GetConsoleTitleA( buf, sizeof(buf) ))
575         {
576             WriteFile(handle,"\033]2;",4,&xlen,NULL);
577             WriteFile(handle,buf,strlen(buf),&xlen,NULL);
578             WriteFile(handle,"\a",1,&xlen,NULL);
579         }
580         return TRUE;
581
582 }
583
584
585 /***********************************************************************
586  *            AllocConsole (KERNEL32.103)
587  *
588  * creates an xterm with a pty to our program
589  */
590 BOOL WINAPI AllocConsole(VOID)
591 {
592         struct open_console_request req;
593         struct open_console_reply reply;
594         PDB *pdb = PROCESS_Current();
595         CONSOLE *console;
596         HANDLE hIn, hOut, hErr;
597
598         SYSTEM_LOCK();          /* FIXME: really only need to lock the process */
599
600         console = (CONSOLE *)pdb->console;
601
602         /* don't create a console if we already have one */
603         if (console != NULL) {
604                 SetLastError(ERROR_ACCESS_DENIED);
605                 SYSTEM_UNLOCK();
606                 return FALSE;
607         }
608
609         if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console))))
610         {
611             SYSTEM_UNLOCK();
612             return FALSE;
613         }
614
615         console->header.type     = K32OBJ_CONSOLE;
616         console->header.refcount = 1;
617
618         CLIENT_SendRequest( REQ_ALLOC_CONSOLE, -1, 0 );
619         if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS)
620         {
621             K32OBJ_DecCount(&console->header);
622             SYSTEM_UNLOCK();
623             return FALSE;
624         }
625
626         req.output = 0;
627         req.access = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE;
628         req.inherit = FALSE;
629         CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
630         if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
631         {
632             K32OBJ_DecCount(&console->header);
633             SYSTEM_UNLOCK();
634             return FALSE;
635         }
636         if ((hIn = HANDLE_Alloc(pdb,&console->header, req.access,
637                                 FALSE, reply.handle)) == INVALID_HANDLE_VALUE)
638         {
639             K32OBJ_DecCount(&console->header);
640             SYSTEM_UNLOCK();
641             return FALSE;
642         }
643
644         req.output = 1;
645         CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
646         if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
647         {
648             CloseHandle(hIn);
649             K32OBJ_DecCount(&console->header);
650             SYSTEM_UNLOCK();
651             return FALSE;
652         }
653         if ((hOut = HANDLE_Alloc(pdb,&console->header, req.access,
654                                  FALSE, reply.handle)) == INVALID_HANDLE_VALUE)
655         {
656             CloseHandle(hIn);
657             K32OBJ_DecCount(&console->header);
658             SYSTEM_UNLOCK();
659             return FALSE;
660         }
661
662         if (!DuplicateHandle( GetCurrentProcess(), hOut,
663                               GetCurrentProcess(), &hErr,
664                               0, TRUE, DUPLICATE_SAME_ACCESS ))
665         {
666             CloseHandle(hIn);
667             CloseHandle(hOut);
668             K32OBJ_DecCount(&console->header);
669             SYSTEM_UNLOCK();
670             return FALSE;
671         }
672
673         if (pdb->console) K32OBJ_DecCount( pdb->console );
674         pdb->console = (K32OBJ *)console;
675         K32OBJ_IncCount( pdb->console );
676
677         /* NT resets the STD_*_HANDLEs on console alloc */
678         SetStdHandle(STD_INPUT_HANDLE, hIn);
679         SetStdHandle(STD_OUTPUT_HANDLE, hOut);
680         SetStdHandle(STD_ERROR_HANDLE, hErr);
681
682         SetLastError(ERROR_SUCCESS);
683         SYSTEM_UNLOCK();
684         SetConsoleTitleA("Wine Console");
685         return TRUE;
686 }
687
688
689 /******************************************************************************
690  * GetConsoleCP [KERNEL32.295]  Returns the OEM code page for the console
691  *
692  * RETURNS
693  *    Code page code
694  */
695 UINT WINAPI GetConsoleCP(VOID)
696 {
697     return GetACP();
698 }
699
700
701 /***********************************************************************
702  *            GetConsoleOutputCP   (KERNEL32.189)
703  */
704 UINT WINAPI GetConsoleOutputCP(VOID)
705 {
706     return GetConsoleCP();
707 }
708
709 /***********************************************************************
710  *            GetConsoleMode   (KERNEL32.188)
711  */
712 BOOL WINAPI GetConsoleMode(HANDLE hcon,LPDWORD mode)
713 {
714     struct get_console_mode_request req;
715     struct get_console_mode_reply reply;
716
717     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
718                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
719         return FALSE;
720     CLIENT_SendRequest( REQ_GET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
721     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
722     *mode = reply.mode;
723     return TRUE;
724 }
725
726
727 /******************************************************************************
728  * SetConsoleMode [KERNEL32.628]  Sets input mode of console's input buffer
729  *
730  * PARAMS
731  *    hcon [I] Handle to console input or screen buffer
732  *    mode [I] Input or output mode to set
733  *
734  * RETURNS
735  *    Success: TRUE
736  *    Failure: FALSE
737  */
738 BOOL WINAPI SetConsoleMode( HANDLE hcon, DWORD mode )
739 {
740     struct set_console_mode_request req;
741
742     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
743                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
744         return FALSE;
745     req.mode = mode;
746     CLIENT_SendRequest( REQ_SET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
747     return !CLIENT_WaitReply( NULL, NULL, 0 );
748 }
749
750
751 /***********************************************************************
752  *            GetConsoleTitleA   (KERNEL32.191)
753  */
754 DWORD WINAPI GetConsoleTitleA(LPSTR title,DWORD size)
755 {
756     struct get_console_info_request req;
757     struct get_console_info_reply reply;
758     int len;
759     DWORD ret = 0;
760     HANDLE hcon;
761
762     if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ, 0, NULL,
763                                OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
764         return 0;
765     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
766                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
767     {
768         CloseHandle( hcon );
769         return 0;
770     }
771     CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
772     if (!CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), title, size ))
773     {
774         if (len > sizeof(reply)+size) title[size-1] = 0;
775         ret = strlen(title);
776     }
777     CloseHandle( hcon );
778     return ret;
779 }
780
781
782 /******************************************************************************
783  * GetConsoleTitle32W [KERNEL32.192]  Retrieves title string for console
784  *
785  * PARAMS
786  *    title [O] Address of buffer for title
787  *    size  [I] Size of buffer
788  *
789  * RETURNS
790  *    Success: Length of string copied
791  *    Failure: 0
792  */
793 DWORD WINAPI GetConsoleTitleW( LPWSTR title, DWORD size )
794 {
795     char *tmp;
796     DWORD ret;
797
798     if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size ))) return 0;
799     ret = GetConsoleTitleA( tmp, size );
800     lstrcpyAtoW( title, tmp );
801     HeapFree( GetProcessHeap(), 0, tmp );
802     return ret;
803 }
804
805
806 /***********************************************************************
807  *            WriteConsoleA   (KERNEL32.729)
808  */
809 BOOL WINAPI WriteConsoleA( HANDLE hConsoleOutput,
810                                LPCVOID lpBuffer,
811                                DWORD nNumberOfCharsToWrite,
812                                LPDWORD lpNumberOfCharsWritten,
813                                LPVOID lpReserved )
814 {
815         /* FIXME: should I check if this is a console handle? */
816         return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
817                          lpNumberOfCharsWritten, NULL);
818 }
819
820
821 #define CADD(c)                                                         \
822         if (bufused==curbufsize-1)                                      \
823             buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\
824         buffer[bufused++]=c;
825 #define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}}
826
827 /***********************************************************************
828  *            WriteConsoleOutputA   (KERNEL32.732)
829  */
830 BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput,
831                                      LPCHAR_INFO lpBuffer,
832                                      COORD dwBufferSize,
833                                      COORD dwBufferCoord,
834                                      LPSMALL_RECT lpWriteRegion)
835 {
836     int i,j,off=0,lastattr=-1;
837     char        sbuf[20],*buffer=NULL;
838     int         bufused=0,curbufsize = 100;
839     DWORD       res;
840     const int colormap[8] = {
841         0,4,2,6,
842         1,5,3,7,
843     };
844     CONSOLE_make_complex(hConsoleOutput);
845     buffer = HeapAlloc(GetProcessHeap(),0,100);;
846     curbufsize = 100;
847
848     TRACE(console,"wr: top = %d, bottom=%d, left=%d,right=%d\n",
849         lpWriteRegion->Top,
850         lpWriteRegion->Bottom,
851         lpWriteRegion->Left,
852         lpWriteRegion->Right
853     );
854
855     for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) {
856         sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1);
857         SADD(sbuf);
858         for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) {
859             if (lastattr!=lpBuffer[off].Attributes) {
860                 lastattr = lpBuffer[off].Attributes;
861                 sprintf(sbuf,"%c[0;%s3%d;4%dm",
862                         27,
863                         (lastattr & FOREGROUND_INTENSITY)?"1;":"",
864                         colormap[lastattr&7],
865                         colormap[(lastattr&0x70)>>4]
866                 );
867                 /* FIXME: BACKGROUND_INTENSITY */
868                 SADD(sbuf);
869             }
870             CADD(lpBuffer[off].Char.AsciiChar);
871             off++;
872         }
873     }
874     sprintf(sbuf,"%c[0m",27);SADD(sbuf);
875     WriteFile(hConsoleOutput,buffer,bufused,&res,NULL);
876     HeapFree(GetProcessHeap(),0,buffer);
877     return TRUE;
878 }
879
880 /***********************************************************************
881  *            WriteConsoleW   (KERNEL32.577)
882  */
883 BOOL WINAPI WriteConsoleW( HANDLE hConsoleOutput,
884                                LPCVOID lpBuffer,
885                                DWORD nNumberOfCharsToWrite,
886                                LPDWORD lpNumberOfCharsWritten,
887                                LPVOID lpReserved )
888 {
889         BOOL ret;
890         LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite );
891
892         lstrcpynWtoA( xstring,  lpBuffer,nNumberOfCharsToWrite);
893
894         /* FIXME: should I check if this is a console handle? */
895         ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite,
896                          lpNumberOfCharsWritten, NULL);
897         HeapFree( GetProcessHeap(), 0, xstring );
898         return ret;
899 }
900
901
902 /***********************************************************************
903  *            ReadConsoleA   (KERNEL32.419)
904  */
905 BOOL WINAPI ReadConsoleA( HANDLE hConsoleInput,
906                               LPVOID lpBuffer,
907                               DWORD nNumberOfCharsToRead,
908                               LPDWORD lpNumberOfCharsRead,
909                               LPVOID lpReserved )
910 {
911     int         charsread = 0;
912     LPSTR       xbuf = (LPSTR)lpBuffer;
913     struct read_console_input_request req;
914     INPUT_RECORD        ir;
915
916     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hConsoleInput,
917                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
918         return FALSE;
919     TRACE(console,"(%d,%p,%ld,%p,%p)\n",
920             hConsoleInput,lpBuffer,nNumberOfCharsToRead,
921             lpNumberOfCharsRead,lpReserved
922     );
923
924     CONSOLE_get_input(hConsoleInput,FALSE);
925
926     req.count = 1;
927     req.flush = 1;
928
929     /* FIXME: should we read at least 1 char? The SDK does not say */
930     while (charsread<nNumberOfCharsToRead)
931     {
932         int len;
933
934         CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
935         if (CLIENT_WaitReply( &len, NULL, 1, &ir, sizeof(ir) ))
936             return FALSE;
937         assert( !(len % sizeof(ir)) );
938         if (!len) break;
939         if (!ir.Event.KeyEvent.bKeyDown)
940                 continue;
941         if (ir.EventType != KEY_EVENT)
942                 continue;
943         *xbuf++ = ir.Event.KeyEvent.uChar.AsciiChar; 
944         charsread++;
945     }
946     if (lpNumberOfCharsRead)
947         *lpNumberOfCharsRead = charsread;
948     return TRUE;
949 }
950
951 /***********************************************************************
952  *            ReadConsoleW   (KERNEL32.427)
953  */
954 BOOL WINAPI ReadConsoleW( HANDLE hConsoleInput,
955                               LPVOID lpBuffer,
956                               DWORD nNumberOfCharsToRead,
957                               LPDWORD lpNumberOfCharsRead,
958                               LPVOID lpReserved )
959 {
960     BOOL ret;
961     LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead);
962
963     ret = ReadConsoleA(
964         hConsoleInput,
965         buf,
966         nNumberOfCharsToRead,
967         lpNumberOfCharsRead,
968         lpReserved
969     );
970     if (ret)
971         lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
972     HeapFree( GetProcessHeap(), 0, buf );
973     return ret;
974 }
975
976
977 /******************************************************************************
978  * ReadConsoleInput32A [KERNEL32.569]  Reads data from a console
979  *
980  * PARAMS
981  *    hConsoleInput        [I] Handle to console input buffer
982  *    lpBuffer             [O] Address of buffer for read data
983  *    nLength              [I] Number of records to read
984  *    lpNumberOfEventsRead [O] Address of number of records read
985  *
986  * RETURNS
987  *    Success: TRUE
988  *    Failure: FALSE
989  */
990 BOOL WINAPI ReadConsoleInputA(HANDLE hConsoleInput,
991                                   LPINPUT_RECORD lpBuffer,
992                                   DWORD nLength, LPDWORD lpNumberOfEventsRead)
993 {
994     struct read_console_input_request req;
995     int len;
996
997     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hConsoleInput,
998                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
999         return FALSE;
1000     req.count = nLength;
1001     req.flush = 1;
1002
1003     /* loop until we get at least one event */
1004     for (;;)
1005     {
1006         CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
1007         if (CLIENT_WaitReply( &len, NULL, 1, lpBuffer, nLength * sizeof(*lpBuffer) ))
1008             return FALSE;
1009         assert( !(len % sizeof(INPUT_RECORD)) );
1010         if (len) break;
1011         CONSOLE_get_input(hConsoleInput,TRUE);
1012         /*WaitForSingleObject( hConsoleInput, INFINITE32 );*/
1013     }
1014     if (lpNumberOfEventsRead) *lpNumberOfEventsRead = len / sizeof(INPUT_RECORD);
1015     return TRUE;
1016 }
1017
1018
1019 /***********************************************************************
1020  *            ReadConsoleInput32W   (KERNEL32.570)
1021  */
1022 BOOL WINAPI ReadConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer,
1023                                    DWORD count, LPDWORD read )
1024 {
1025     /* FIXME: Fix this if we get UNICODE input. */
1026     return ReadConsoleInputA( handle, buffer, count, read );
1027 }
1028
1029
1030 /***********************************************************************
1031  *            FlushConsoleInputBuffer   (KERNEL32.132)
1032  */
1033 BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
1034 {
1035     struct read_console_input_request req;
1036     int len;
1037
1038     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
1039                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
1040         return FALSE;
1041     req.count = -1;  /* get all records */
1042     req.flush = 1;
1043     CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
1044     return !CLIENT_WaitReply( &len, NULL, 0 );
1045 }
1046
1047
1048 /***********************************************************************
1049  *            PeekConsoleInputA   (KERNEL32.550)
1050  *
1051  * Gets 'count' first events (or less) from input queue.
1052  *
1053  * Does not need a complex console.
1054  */
1055 BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer,
1056                                    DWORD count, LPDWORD read )
1057 {
1058     struct read_console_input_request req;
1059     int len;
1060
1061     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
1062                                               K32OBJ_CONSOLE, GENERIC_READ )) == -1)
1063         return FALSE;
1064
1065     CONSOLE_get_input(handle,FALSE);
1066     req.count = count;
1067     req.flush = 0;
1068
1069     CLIENT_SendRequest( REQ_READ_CONSOLE_INPUT, -1, 1, &req, sizeof(req) );
1070     if (CLIENT_WaitReply( &len, NULL, 1, buffer, count * sizeof(*buffer) ))
1071         return FALSE;
1072     assert( !(len % sizeof(INPUT_RECORD)) );
1073     if (read) *read = len / sizeof(INPUT_RECORD);
1074     return TRUE;
1075 }
1076
1077
1078 /***********************************************************************
1079  *            PeekConsoleInputW   (KERNEL32.551)
1080  */
1081 BOOL WINAPI PeekConsoleInputW(HANDLE hConsoleInput,
1082                                   LPINPUT_RECORD pirBuffer,
1083                                   DWORD cInRecords,
1084                                   LPDWORD lpcRead)
1085 {
1086     /* FIXME: Hmm. Fix this if we get UNICODE input. */
1087     return PeekConsoleInputA(hConsoleInput,pirBuffer,cInRecords,lpcRead);
1088 }
1089
1090
1091 /******************************************************************************
1092  * WriteConsoleInput32A [KERNEL32.730]  Write data to a console input buffer
1093  *
1094  */
1095 BOOL WINAPI WriteConsoleInputA( HANDLE handle, INPUT_RECORD *buffer,
1096                                     DWORD count, LPDWORD written )
1097 {
1098     struct write_console_input_request req;
1099     struct write_console_input_reply reply;
1100
1101     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
1102                                               K32OBJ_CONSOLE, GENERIC_WRITE )) == -1)
1103         return FALSE;
1104     req.count = count;
1105     CLIENT_SendRequest( REQ_WRITE_CONSOLE_INPUT, -1, 2, &req, sizeof(req),
1106                         buffer, count * sizeof(*buffer) );
1107     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
1108     if (written) *written = reply.written;
1109     return TRUE;
1110 }
1111
1112
1113 /***********************************************************************
1114  *            SetConsoleTitle32A   (KERNEL32.476)
1115  *
1116  * Sets the console title.
1117  *
1118  * We do not necessarily need to create a complex console for that,
1119  * but should remember the title and set it on creation of the latter.
1120  * (not fixed at this time).
1121  */
1122 BOOL WINAPI SetConsoleTitleA(LPCSTR title)
1123 {
1124 #if 0
1125     PDB *pdb = PROCESS_Current();
1126     CONSOLE *console;
1127     DWORD written;
1128     char titleformat[]="\033]2;%s\a"; /*this should work for xterms*/
1129     LPSTR titlestring; 
1130     BOOL ret=FALSE;
1131
1132     TRACE(console,"(%s)\n",title);
1133
1134     console = (CONSOLE *)pdb->console;
1135     if (!console)
1136         return FALSE;
1137     if(console->title) /* Free old title, if there is one */
1138         HeapFree( SystemHeap, 0, console->title );
1139     console->title = (LPSTR)HeapAlloc(SystemHeap, 0,strlen(title)+1);
1140     if(console->title) strcpy(console->title,title);
1141     titlestring = HeapAlloc(GetProcessHeap(), 0,strlen(title)+strlen(titleformat)+1);
1142     if (!titlestring) {
1143         K32OBJ_DecCount(&console->header);
1144         return FALSE;
1145     }
1146
1147     sprintf(titlestring,titleformat,title);
1148 #if 0
1149     /* only set title for complex console (own xterm) */
1150     if (console->pid != -1) {
1151         WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),titlestring,strlen(titlestring),&written,NULL);
1152         if (written == strlen(titlestring))
1153             ret =TRUE;
1154     } else
1155         ret = TRUE;
1156 #endif
1157     HeapFree( GetProcessHeap(), 0, titlestring );
1158     K32OBJ_DecCount(&console->header);
1159     return ret;
1160
1161
1162
1163 #endif
1164
1165     struct set_console_info_request req;
1166     struct get_console_info_reply info;
1167     HANDLE hcon;
1168     DWORD written;
1169
1170     if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
1171                                OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
1172         return FALSE;
1173     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
1174                                               K32OBJ_CONSOLE, GENERIC_WRITE )) == -1)
1175         goto error;
1176     req.mask = SET_CONSOLE_INFO_TITLE;
1177     CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 2, &req, sizeof(req),
1178                         title, strlen(title)+1 );
1179     if (CLIENT_WaitReply( NULL, NULL, 0 )) goto error;
1180     if (CONSOLE_GetInfo( hcon, &info ) && info.pid)
1181     {
1182         /* only set title for complex console (own xterm) */
1183         WriteFile( hcon, "\033]2;", 4, &written, NULL );
1184         WriteFile( hcon, title, strlen(title), &written, NULL );
1185         WriteFile( hcon, "\a", 1, &written, NULL );
1186     }
1187     return TRUE;
1188  error:
1189     CloseHandle( hcon );
1190     return FALSE;
1191 }
1192
1193
1194 /******************************************************************************
1195  * SetConsoleTitle32W [KERNEL32.477]  Sets title bar string for console
1196  *
1197  * PARAMS
1198  *    title [I] Address of new title
1199  *
1200  * NOTES
1201  *    This should not be calling the A version
1202  *
1203  * RETURNS
1204  *    Success: TRUE
1205  *    Failure: FALSE
1206  */
1207 BOOL WINAPI SetConsoleTitleW( LPCWSTR title )
1208 {
1209     BOOL ret;
1210
1211     LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1212     ret = SetConsoleTitleA(titleA);
1213     HeapFree( GetProcessHeap(), 0, titleA );
1214     return ret;
1215 }
1216
1217 /******************************************************************************
1218  * SetConsoleCursorPosition [KERNEL32.627]
1219  * Sets the cursor position in console
1220  *
1221  * PARAMS
1222  *    hConsoleOutput   [I] Handle of console screen buffer
1223  *    dwCursorPosition [I] New cursor position coordinates
1224  *
1225  * RETURNS STD
1226  */
1227 BOOL WINAPI SetConsoleCursorPosition( HANDLE hcon, COORD pos )
1228 {
1229     char        xbuf[20];
1230     DWORD       xlen;
1231
1232     /* make console complex only if we change lines, not just in the line */
1233     if (pos.y)
1234         CONSOLE_make_complex(hcon);
1235
1236     TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y );
1237     /* x are columns, y rows */
1238     if (pos.y) 
1239         /* full screen cursor absolute positioning */
1240         sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1);
1241     else
1242         /* relative cursor positioning in line (\r to go to 0) */
1243         sprintf(xbuf,"\r%c[%dC", 0x1B, pos.x);
1244     /* FIXME: store internal if we start using own console buffers */
1245     WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL);
1246     return TRUE;
1247 }
1248
1249 /***********************************************************************
1250  *            GetNumberOfConsoleInputEvents   (KERNEL32.246)
1251  */
1252 BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hcon,LPDWORD nrofevents)
1253 {
1254     CONSOLE_get_input(hcon,FALSE);
1255     *nrofevents = 1; /* UMM */
1256     return TRUE;
1257 }
1258
1259 /***********************************************************************
1260  *            GetNumberOfConsoleMouseButtons   (KERNEL32.358)
1261  */
1262 BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
1263 {
1264     FIXME(console,"(%p): stub\n", nrofbuttons);
1265     *nrofbuttons = 2;
1266     return TRUE;
1267 }
1268
1269 /******************************************************************************
1270  * GetConsoleCursorInfo32 [KERNEL32.296]  Gets size and visibility of console
1271  *
1272  * PARAMS
1273  *    hcon  [I] Handle to console screen buffer
1274  *    cinfo [O] Address of cursor information
1275  *
1276  * RETURNS
1277  *    Success: TRUE
1278  *    Failure: FALSE
1279  */
1280 BOOL WINAPI GetConsoleCursorInfo( HANDLE hcon,
1281                                       LPCONSOLE_CURSOR_INFO cinfo )
1282 {
1283     struct get_console_info_reply reply;
1284
1285     if (!CONSOLE_GetInfo( hcon, &reply )) return FALSE;
1286     if (cinfo)
1287     {
1288         cinfo->dwSize = reply.cursor_size;
1289         cinfo->bVisible = reply.cursor_visible;
1290     }
1291     return TRUE;
1292 }
1293
1294
1295 /******************************************************************************
1296  * SetConsoleCursorInfo32 [KERNEL32.626]  Sets size and visibility of cursor
1297  *
1298  * RETURNS
1299  *    Success: TRUE
1300  *    Failure: FALSE
1301  */
1302 BOOL WINAPI SetConsoleCursorInfo( 
1303     HANDLE hcon,                /* [in] Handle to console screen buffer */
1304     LPCONSOLE_CURSOR_INFO cinfo)  /* [in] Address of cursor information */
1305 {
1306     struct set_console_info_request req;
1307     char        buf[8];
1308     DWORD       xlen;
1309
1310     if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
1311                                               K32OBJ_CONSOLE, GENERIC_WRITE )) == -1)
1312         return FALSE;
1313     CONSOLE_make_complex(hcon);
1314     sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l');
1315     WriteFile(hcon,buf,strlen(buf),&xlen,NULL);
1316
1317     req.cursor_size    = cinfo->dwSize;
1318     req.cursor_visible = cinfo->bVisible;
1319     req.mask           = SET_CONSOLE_INFO_CURSOR;
1320     CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
1321     return !CLIENT_WaitReply( NULL, NULL, 0 );
1322 }
1323
1324
1325 /******************************************************************************
1326  * SetConsoleWindowInfo [KERNEL32.634]  Sets size and position of console
1327  *
1328  * RETURNS
1329  *    Success: TRUE
1330  *    Failure: FALSE
1331  */
1332 BOOL WINAPI SetConsoleWindowInfo(
1333     HANDLE hcon,       /* [in] Handle to console screen buffer */
1334     BOOL bAbsolute,    /* [in] Coordinate type flag */
1335     LPSMALL_RECT window) /* [in] Address of new window rectangle */
1336 {
1337     FIXME(console, "(%x,%d,%p): stub\n", hcon, bAbsolute, window);
1338     return TRUE;
1339 }
1340
1341
1342 /******************************************************************************
1343  * SetConsoleTextAttribute32 [KERNEL32.631]  Sets colors for text
1344  *
1345  * Sets the foreground and background color attributes of characters
1346  * written to the screen buffer.
1347  *
1348  * RETURNS
1349  *    Success: TRUE
1350  *    Failure: FALSE
1351  */
1352 BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttr)
1353 {
1354     const int colormap[8] = {
1355         0,4,2,6,
1356         1,5,3,7,
1357     };
1358     DWORD xlen;
1359     char buffer[20];
1360
1361     TRACE(console,"(%d,%d)\n",hConsoleOutput,wAttr);
1362     sprintf(buffer,"%c[0;%s3%d;4%dm",
1363         27,
1364         (wAttr & FOREGROUND_INTENSITY)?"1;":"",
1365         colormap[wAttr&7],
1366         colormap[(wAttr&0x70)>>4]
1367     );
1368     WriteFile(hConsoleOutput,buffer,strlen(buffer),&xlen,NULL);
1369     return TRUE;
1370 }
1371
1372
1373 /******************************************************************************
1374  * SetConsoleScreenBufferSize [KERNEL32.630]  Changes size of console 
1375  *
1376  * PARAMS
1377  *    hConsoleOutput [I] Handle to console screen buffer
1378  *    dwSize         [I] New size in character rows and cols
1379  *
1380  * RETURNS
1381  *    Success: TRUE
1382  *    Failure: FALSE
1383  */
1384 BOOL WINAPI SetConsoleScreenBufferSize( HANDLE hConsoleOutput, 
1385                                           COORD dwSize )
1386 {
1387     FIXME(console, "(%d,%dx%d): stub\n",hConsoleOutput,dwSize.x,dwSize.y);
1388     return TRUE;
1389 }
1390
1391
1392 /******************************************************************************
1393  * FillConsoleOutputCharacterA [KERNEL32.242]
1394  *
1395  * PARAMS
1396  *    hConsoleOutput    [I] Handle to screen buffer
1397  *    cCharacter        [I] Character to write
1398  *    nLength           [I] Number of cells to write to
1399  *    dwCoord           [I] Coords of first cell
1400  *    lpNumCharsWritten [O] Pointer to number of cells written
1401  *
1402  * RETURNS
1403  *    Success: TRUE
1404  *    Failure: FALSE
1405  */
1406 BOOL WINAPI FillConsoleOutputCharacterA(
1407     HANDLE hConsoleOutput,
1408     BYTE cCharacter,
1409     DWORD nLength,
1410     COORD dwCoord,
1411     LPDWORD lpNumCharsWritten)
1412 {
1413     long        count;
1414     DWORD       xlen;
1415
1416     SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1417     for(count=0;count<nLength;count++)
1418         WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
1419     *lpNumCharsWritten = nLength;
1420     return TRUE;
1421 }
1422
1423
1424 /******************************************************************************
1425  * FillConsoleOutputCharacterW [KERNEL32.243]  Writes characters to console
1426  *
1427  * PARAMS
1428  *    hConsoleOutput    [I] Handle to screen buffer
1429  *    cCharacter        [I] Character to write
1430  *    nLength           [I] Number of cells to write to
1431  *    dwCoord           [I] Coords of first cell
1432  *    lpNumCharsWritten [O] Pointer to number of cells written
1433  *
1434  * RETURNS
1435  *    Success: TRUE
1436  *    Failure: FALSE
1437  */
1438 BOOL WINAPI FillConsoleOutputCharacterW(HANDLE hConsoleOutput,
1439                                             WCHAR cCharacter,
1440                                             DWORD nLength,
1441                                            COORD dwCoord, 
1442                                             LPDWORD lpNumCharsWritten)
1443 {
1444     long        count;
1445     DWORD       xlen;
1446
1447     SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1448     /* FIXME: not quite correct ... but the lower part of UNICODE char comes
1449      * first 
1450      */
1451     for(count=0;count<nLength;count++)
1452         WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
1453     *lpNumCharsWritten = nLength;
1454     return TRUE;
1455 }
1456
1457
1458 /******************************************************************************
1459  * FillConsoleOutputAttribute [KERNEL32.241]  Sets attributes for console
1460  *
1461  * PARAMS
1462  *    hConsoleOutput    [I] Handle to screen buffer
1463  *    wAttribute        [I] Color attribute to write
1464  *    nLength           [I] Number of cells to write to
1465  *    dwCoord           [I] Coords of first cell
1466  *    lpNumAttrsWritten [O] Pointer to number of cells written
1467  *
1468  * RETURNS
1469  *    Success: TRUE
1470  *    Failure: FALSE
1471  */
1472 BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, 
1473               WORD wAttribute, DWORD nLength, COORD dwCoord, 
1474               LPDWORD lpNumAttrsWritten)
1475 {
1476     FIXME(console, "(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1477           wAttribute,nLength,dwCoord.x,dwCoord.y,lpNumAttrsWritten);
1478     *lpNumAttrsWritten = nLength;
1479     return TRUE;
1480 }
1481
1482 /******************************************************************************
1483  * ReadConsoleOutputCharacter32A [KERNEL32.573]
1484  * 
1485  * BUGS
1486  *   Unimplemented
1487  */
1488 BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, 
1489               LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1490 {
1491     FIXME(console, "(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1492           dword,coord.x,coord.y,lpdword);
1493     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1494     return FALSE;
1495 }
1496
1497
1498 /******************************************************************************
1499  * ScrollConsoleScreenBuffer [KERNEL32.612]
1500  * 
1501  * BUGS
1502  *   Unimplemented
1503  */
1504 BOOL WINAPI ScrollConsoleScreenBuffer( HANDLE hConsoleOutput, 
1505               LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1506               COORD dwDestOrigin, LPCHAR_INFO lpFill)
1507 {
1508     FIXME(console, "(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1509           lpClipRect,dwDestOrigin.x,dwDestOrigin.y,lpFill);
1510     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1511     return FALSE;
1512 }