Release 980927
[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  */
8
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <termios.h>
12 #include <sys/ioctl.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <errno.h>
17 #include <sys/errno.h>
18 #include <signal.h>
19 #include <assert.h>
20 #include "windows.h"
21 #include "k32obj.h"
22 #include "file.h"
23 #include "process.h"
24 #include "winerror.h"
25 #include "wincon.h"
26 #include "heap.h"
27 #include "debug.h"
28
29 static CONSOLE_SCREEN_BUFFER_INFO dummyinfo =
30 {
31     {80, 24},
32     {0, 0},
33     0,
34     {0, 0, 79, 23},
35     {80, 24}
36 };
37
38 /* The console -- I chose to keep the master and slave
39  * (UNIX) file descriptors around in case they are needed for
40  * ioctls later.  The pid is needed to destroy the xterm on close
41  */
42 typedef struct _CONSOLE {
43         K32OBJ  header;
44         int     master;                 /* xterm side of pty */
45         int     slave;                  /* wine side of pty */
46         int     pid;                    /* xterm's pid, -1 if no xterm */
47         LPSTR   title;                  /* title of console */
48 } CONSOLE;
49
50
51 /* This probably belongs somewhere else */
52 typedef struct _CONSOLE_CURSOR_INFO {
53     DWORD  dwSize;   /* Between 1 & 100 for percentage of cell filled */
54     BOOL32 bVisible; /* Visibility of cursor */
55 } CONSOLE_CURSOR_INFO, *LPCONSOLE_CURSOR_INFO;
56
57
58
59 static void CONSOLE_Destroy( K32OBJ *obj );
60 static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer, 
61                             DWORD nNumberOfChars,  LPDWORD lpNumberOfChars, 
62                             LPOVERLAPPED lpOverlapped);
63 static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer, 
64                            DWORD nNumberOfChars, LPDWORD lpNumberOfChars, 
65                            LPOVERLAPPED lpOverlapped);
66 static int wine_openpty(int *master, int *slave, char *name, 
67                      struct termios *term, struct winsize *winsize);
68 static BOOL32 wine_createConsole(int *master, int *slave, int *pid);
69
70 const K32OBJ_OPS CONSOLE_Ops =
71 {
72         NULL,                   /* signaled */
73         NULL,                   /* satisfied */
74         NULL,                   /* add_wait */
75         NULL,                   /* remove_wait */
76         CONSOLE_Read,           /* read */
77         CONSOLE_Write,          /* write */
78         CONSOLE_Destroy         /* destroy */
79 };
80
81
82
83 /***********************************************************************
84  * CONSOLE_Destroy
85  */
86 static void CONSOLE_Destroy(K32OBJ *obj)
87 {
88         CONSOLE *console = (CONSOLE *)obj;
89         assert(obj->type == K32OBJ_CONSOLE);
90
91         obj->type = K32OBJ_UNKNOWN;
92
93         if (console->title)
94                   HeapFree( SystemHeap, 0, console->title );
95         console->title = NULL;
96         /* make sure a xterm exists to kill */
97         if (console->pid != -1) {
98                 kill(console->pid, SIGTERM);
99         }
100         HeapFree(SystemHeap, 0, console);
101 }
102
103
104 /***********************************************************************
105  * CONSOLE_Read
106  *
107  * NOTES
108  *    lpOverlapped is ignored
109  */
110 static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
111                         LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
112 {
113         CONSOLE *console = (CONSOLE *)ptr;
114         int result;
115
116         TRACE(console, "%p %p %ld\n", ptr, lpBuffer,
117                      nNumberOfChars);
118
119         *lpNumberOfChars = 0; 
120
121         if ((result = read(console->slave, lpBuffer, nNumberOfChars)) == -1) {
122                 FILE_SetDosError();
123                 return FALSE;
124         }
125         *lpNumberOfChars = result;
126         return TRUE;
127 }
128
129
130 /***********************************************************************
131  * CONSOLE_Write
132  *
133  * NOTES
134  *    lpOverlapped is ignored
135  */
136 static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer, 
137                             DWORD nNumberOfChars,
138                             LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
139 {
140         CONSOLE *console = (CONSOLE *)ptr;
141         int result;
142
143         TRACE(console, "%p %p %ld\n", ptr, lpBuffer,
144                      nNumberOfChars);
145
146         *lpNumberOfChars = 0; 
147
148         /* 
149          * I assume this loop around EAGAIN is here because
150          * win32 doesn't have interrupted system calls 
151          */
152
153         for (;;)
154         {
155                 result = write(console->slave, lpBuffer, nNumberOfChars);
156                 if (result != -1) {
157                         *lpNumberOfChars = result;
158                         return TRUE;
159                 }
160                 if (errno != EINTR) {
161                         FILE_SetDosError();
162                         return FALSE;
163                 }
164         }
165 }
166
167
168 /******************************************************************************
169  * SetConsoleCtrlHandler [KERNEL32.459]  Adds function to calling process list
170  *
171  * PARAMS
172  *    func [I] Address of handler function
173  *    add  [I] Handler to add or remove
174  *
175  * RETURNS
176  *    Success: TRUE
177  *    Failure: FALSE
178  */
179 BOOL32 WINAPI SetConsoleCtrlHandler( HANDLER_ROUTINE *func, BOOL32 add )
180 {
181     FIXME(console, "(%p,%i): stub\n",func,add);
182     return TRUE;
183 }
184
185
186 /******************************************************************************
187  * CreateConsoleScreenBuffer [KERNEL32.151]  Creates a console screen buffer
188  *
189  * PARAMS
190  *    dwDesiredAccess    [I] Access flag
191  *    dwShareMode        [I] Buffer share mode
192  *    sa                 [I] Security attributes
193  *    dwFlags            [I] Type of buffer to create
194  *    lpScreenBufferData [I] Reserved
195  *
196  * NOTES
197  *    Should call SetLastError
198  *
199  * RETURNS
200  *    Success: Handle to new console screen buffer
201  *    Failure: INVALID_HANDLE_VALUE
202  */
203 HANDLE32 WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
204                 DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa,
205                 DWORD dwFlags, LPVOID lpScreenBufferData )
206 {
207     FIXME(console, "(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess,
208           dwShareMode, sa, dwFlags, lpScreenBufferData);
209     return 1;
210 }
211
212
213 /***********************************************************************
214  *           GetConsoleScreenBufferInfo   (KERNEL32.190)
215  */
216 BOOL32 WINAPI GetConsoleScreenBufferInfo( HANDLE32 hConsoleOutput,
217                                           LPCONSOLE_SCREEN_BUFFER_INFO csbi )
218 {
219     csbi->dwSize.x = 80;
220     csbi->dwSize.y = 24;
221     csbi->dwCursorPosition.x = 0;
222     csbi->dwCursorPosition.y = 0;
223     csbi->wAttributes = 0;
224     csbi->srWindow.Left = 0;
225     csbi->srWindow.Right        = 79;
226     csbi->srWindow.Top  = 0;
227     csbi->srWindow.Bottom       = 23;
228     csbi->dwMaximumWindowSize.x = 80;
229     csbi->dwMaximumWindowSize.y = 24;
230     return TRUE;
231 }
232
233
234 /******************************************************************************
235  * SetConsoleActiveScreenBuffer [KERNEL32.623]  Sets buffer to current console
236  *
237  * RETURNS
238  *    Success: TRUE
239  *    Failure: FALSE
240  */
241 BOOL32 WINAPI SetConsoleActiveScreenBuffer(
242     HANDLE32 hConsoleOutput) /* [in] Handle to console screen buffer */
243 {
244     FIXME(console, "(%x): stub\n", hConsoleOutput);
245     return FALSE;
246 }
247
248
249 /***********************************************************************
250  *            GetLargestConsoleWindowSize   (KERNEL32.226)
251  */
252 DWORD WINAPI GetLargestConsoleWindowSize( HANDLE32 hConsoleOutput )
253 {
254     return (DWORD)MAKELONG(dummyinfo.dwMaximumWindowSize.x,dummyinfo.dwMaximumWindowSize.y);
255 }
256
257 /***********************************************************************
258  *            FreeConsole (KERNEL32.267)
259  */
260 BOOL32 WINAPI FreeConsole(VOID)
261 {
262
263         PDB32 *pdb = PROCESS_Current();
264         CONSOLE *console;
265
266         SYSTEM_LOCK();
267
268         console = (CONSOLE *)pdb->console;
269
270         if (console == NULL) {
271                 SetLastError(ERROR_INVALID_PARAMETER);
272                 return FALSE;
273         }
274
275         HANDLE_CloseAll( pdb, &console->header );
276
277         K32OBJ_DecCount( &console->header );
278         pdb->console = NULL;
279         SYSTEM_UNLOCK();
280         return TRUE;
281 }
282
283
284 /** 
285  *  It looks like the openpty that comes with glibc in RedHat 5.0
286  *  is buggy (second call returns what looks like a dup of 0 and 1
287  *  instead of a new pty), this is a generic replacement.
288  */
289 static int wine_openpty(int *master, int *slave, char *name, 
290                         struct termios *term, struct winsize *winsize)
291 {
292         int fdm, fds;
293         char *ptr1, *ptr2;
294         char pts_name[512];
295
296         strcpy (pts_name, "/dev/ptyXY");
297
298         for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
299                 pts_name[8] = *ptr1;
300                 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
301                         pts_name[9] = *ptr2;
302
303                         if ((fdm = open(pts_name, O_RDWR)) < 0) {
304                                 if (errno == ENOENT)
305                                         return -1;
306                                 else
307                                         continue;
308                         }
309                         pts_name[5] = 't';
310                         if ((fds = open(pts_name, O_RDWR)) < 0) {
311                                 pts_name[5] = 'p';
312                                 continue;
313                         }
314                         *master = fdm;
315                         *slave = fds;
316                         
317                         if (term != NULL)
318                                 tcsetattr(*slave, TCSANOW, term);
319                         if (winsize != NULL)
320                                 ioctl(*slave, TIOCSWINSZ, winsize);
321                         if (name != NULL)
322                                 strcpy(name, pts_name);
323                         return fds;
324                 }
325         }
326         return -1;
327 }
328
329 static BOOL32 wine_createConsole(int *master, int *slave, int *pid)
330 {
331         struct termios term;
332         char buf[1024];
333         char c = '\0';
334         int status = 0;
335         int i;
336
337         if (tcgetattr(0, &term) < 0) return FALSE;
338         term.c_lflag |= ICANON;
339         term.c_lflag &= ~ECHO;
340         if (wine_openpty(master, slave, NULL, &term, NULL) < 0) return FALSE;
341
342         if ((*pid=fork()) == 0) {
343                 tcsetattr(*slave, TCSADRAIN, &term);
344                 sprintf(buf, "-Sxx%d", *master);
345                 execlp("xterm", "xterm", buf, NULL);
346                 ERR(console, "error creating AllocConsole xterm\n");
347                 exit(1);
348         }
349
350         /* most xterms like to print their window ID when used with -S;
351          * read it and continue before the user has a chance...
352          * NOTE: this is the reason we started xterm with ECHO off, 
353          * we'll turn it back on below
354          */
355
356         for (i=0; c!='\n'; (status=read(*slave, &c, 1)), i++) {
357                 if (status == -1 && c == '\0') {
358                                 /* wait for xterm to be created */
359                         usleep(100);
360                 }
361                 if (i > 10000) {
362                         WARN(console, "can't read xterm WID\n");
363                         kill(*pid, SIGKILL);
364                         return FALSE;
365                 }
366         }
367         term.c_lflag |= ECHO;
368         tcsetattr(*master, TCSADRAIN, &term);
369
370         return TRUE;
371
372 }
373
374 /***********************************************************************
375  *              CONSOLE_GetConsoleHandle
376  *       returns a 16-bit style console handle
377  * note: only called from _lopen
378  */
379 HFILE32 CONSOLE_GetConsoleHandle(VOID)
380 {
381         PDB32 *pdb = PROCESS_Current();
382         HFILE32 handle = HFILE_ERROR32;
383
384         SYSTEM_LOCK();
385         if (pdb->console != NULL) {
386                 CONSOLE *console = (CONSOLE *)pdb->console;
387                 handle = (HFILE32)HANDLE_Alloc(pdb, &console->header, 0, TRUE, -1);
388         }
389         SYSTEM_UNLOCK();
390         return handle;
391 }
392
393 /***********************************************************************
394  *            AllocConsole (KERNEL32.103)
395  *
396  * creates an xterm with a pty to our program
397  */
398 BOOL32 WINAPI AllocConsole(VOID)
399 {
400
401         int master;
402         int slave;
403         int pid;
404         PDB32 *pdb = PROCESS_Current();
405         CONSOLE *console;
406         HANDLE32 hIn, hOut, hErr;
407
408         SYSTEM_LOCK();          /* FIXME: really only need to lock the process */
409
410         SetLastError(ERROR_CANNOT_MAKE);  /* this might not be the right 
411                                              error, but it's a good guess :) */
412
413         console = (CONSOLE *)pdb->console;
414
415         /* don't create a console if we already have one */
416         if (console != NULL) {
417                 SetLastError(ERROR_ACCESS_DENIED);
418                 SYSTEM_UNLOCK();
419                 return FALSE;
420         }
421
422         if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console))))
423         {
424             SYSTEM_UNLOCK();
425             return FALSE;
426         }
427
428         console->header.type     = K32OBJ_CONSOLE;
429         console->header.refcount = 1;
430         console->pid             = -1;
431         console->title           = NULL;
432
433         if (wine_createConsole(&master, &slave, &pid) == FALSE) {
434                 K32OBJ_DecCount(&console->header);
435                 SYSTEM_UNLOCK();
436                 return FALSE;
437         }
438
439         /* save the pid and other info for future use */
440         console->master = master;
441         console->slave = slave;
442         console->pid = pid;
443
444         if ((hIn = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
445         {
446             K32OBJ_DecCount(&console->header);
447             SYSTEM_UNLOCK();
448             return FALSE;
449         }
450
451         if ((hOut = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
452         {
453             CloseHandle(hIn);
454             K32OBJ_DecCount(&console->header);
455             SYSTEM_UNLOCK();
456             return FALSE;
457         }
458
459
460         if ((hErr = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
461         {
462             CloseHandle(hIn);
463             CloseHandle(hOut);
464             K32OBJ_DecCount(&console->header);
465             SYSTEM_UNLOCK();
466             return FALSE;
467         }
468
469         /* associate this console with the process */
470         if (pdb->console) K32OBJ_DecCount( pdb->console );
471         pdb->console = (K32OBJ *)console;
472
473         /* NT resets the STD_*_HANDLEs on console alloc */
474         SetStdHandle(STD_INPUT_HANDLE, hIn);
475         SetStdHandle(STD_OUTPUT_HANDLE, hOut);
476         SetStdHandle(STD_ERROR_HANDLE, hErr);
477
478         SetLastError(ERROR_SUCCESS);
479         SYSTEM_UNLOCK();
480         SetConsoleTitle32A("Wine Console");
481         return TRUE;
482 }
483
484
485 /******************************************************************************
486  * GetConsoleCP [KERNEL32.295]  Returns the OEM code page for the console
487  *
488  * RETURNS
489  *    Code page code
490  */
491 UINT32 WINAPI GetConsoleCP(VOID)
492 {
493     return GetACP();
494 }
495
496
497 /***********************************************************************
498  *            GetConsoleOutputCP   (KERNEL32.189)
499  */
500 UINT32 WINAPI GetConsoleOutputCP(VOID)
501 {
502     return GetConsoleCP();
503 }
504
505 /***********************************************************************
506  *            GetConsoleMode   (KERNEL32.188)
507  */
508 BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode)
509 {
510         *mode =         ENABLE_PROCESSED_INPUT  |
511                         ENABLE_LINE_INPUT       |
512                         ENABLE_ECHO_INPUT;
513         return TRUE;
514 }
515
516
517 /******************************************************************************
518  * SetConsoleMode [KERNEL32.628]  Sets input mode of console's input buffer
519  *
520  * PARAMS
521  *    hcon [I] Handle to console input or screen buffer
522  *    mode [I] Input or output mode to set
523  *
524  * RETURNS
525  *    Success: TRUE
526  *    Failure: FALSE
527  */
528 BOOL32 WINAPI SetConsoleMode( HANDLE32 hcon, DWORD mode )
529 {
530     FIXME(console,"(0x%08x,0x%08lx): stub\n",hcon,mode);
531     return TRUE;
532 }
533
534
535 /***********************************************************************
536  *            GetConsoleTitleA   (KERNEL32.191)
537  */
538 DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size)
539 {
540         PDB32 *pdb = PROCESS_Current();
541         CONSOLE *console= (CONSOLE *)pdb->console;
542
543         if(console && console->title) 
544           {
545             lstrcpyn32A(title,console->title,size);
546             return strlen(title);
547           }
548         return 0;
549 }
550
551
552 /******************************************************************************
553  * GetConsoleTitle32W [KERNEL32.192]  Retrieves title string for console
554  *
555  * PARAMS
556  *    title [O] Address of buffer for title
557  *    size  [I] Size of buffer
558  *
559  * RETURNS
560  *    Success: Length of string copied
561  *    Failure: 0
562  */
563 DWORD WINAPI GetConsoleTitle32W( LPWSTR title, DWORD size )
564 {
565     PDB32 *pdb = PROCESS_Current();
566     CONSOLE *console= (CONSOLE *)pdb->console;
567     if(console && console->title) 
568     {
569         lstrcpynAtoW(title,console->title,size);
570         return (lstrlen32W(title));
571     }
572     return 0;
573 }
574
575
576 /***********************************************************************
577  *            WriteConsoleA   (KERNEL32.729)
578  */
579 BOOL32 WINAPI WriteConsole32A( HANDLE32 hConsoleOutput,
580                                LPCVOID lpBuffer,
581                                DWORD nNumberOfCharsToWrite,
582                                LPDWORD lpNumberOfCharsWritten,
583                                LPVOID lpReserved )
584 {
585         /* FIXME: should I check if this is a console handle? */
586         return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
587                          lpNumberOfCharsWritten, NULL);
588 }
589
590
591 /***********************************************************************
592  *            WriteConsoleOutputA   (KERNEL32.732)
593  */
594 BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
595                                      LPCHAR_INFO lpBuffer,
596                                      COORD dwBufferSize,
597                                      COORD dwBufferCoord,
598                                      LPSMALL_RECT lpWriteRegion)
599 {
600     FIXME(console, "(...):stub\n");
601     return FALSE;
602 }
603
604 /***********************************************************************
605  *            WriteConsoleW   (KERNEL32.577)
606  */
607 BOOL32 WINAPI WriteConsole32W( HANDLE32 hConsoleOutput,
608                                LPCVOID lpBuffer,
609                                DWORD nNumberOfCharsToWrite,
610                                LPDWORD lpNumberOfCharsWritten,
611                                LPVOID lpReserved )
612 {
613         BOOL32 ret;
614         LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite );
615
616         lstrcpynWtoA( xstring,  lpBuffer,nNumberOfCharsToWrite);
617
618         /* FIXME: should I check if this is a console handle? */
619         ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite,
620                          lpNumberOfCharsWritten, NULL);
621         HeapFree( GetProcessHeap(), 0, xstring );
622         return ret;
623 }
624
625
626 /***********************************************************************
627  *            ReadConsoleA   (KERNEL32.419)
628  */
629 BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput,
630                               LPVOID lpBuffer,
631                               DWORD nNumberOfCharsToRead,
632                               LPDWORD lpNumberOfCharsRead,
633                               LPVOID lpReserved )
634 {
635         return ReadFile(hConsoleInput, lpBuffer, nNumberOfCharsToRead,
636                         lpNumberOfCharsRead, NULL);
637
638 #ifdef OLD
639         fgets(lpBuffer,nNumberOfCharsToRead, CONSOLE_console.conIO);
640         if (ferror(CONSOLE_console.conIO) {
641                 clearerr();
642                 return FALSE;
643         }
644         *lpNumberOfCharsRead = strlen(lpBuffer);
645         return TRUE;
646 #endif
647
648 }
649
650 /***********************************************************************
651  *            ReadConsoleW   (KERNEL32.427)
652  */
653 BOOL32 WINAPI ReadConsole32W( HANDLE32 hConsoleInput,
654                               LPVOID lpBuffer,
655                               DWORD nNumberOfCharsToRead,
656                               LPDWORD lpNumberOfCharsRead,
657                               LPVOID lpReserved )
658 {
659         BOOL32 ret;
660         LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 
661                                        nNumberOfCharsToRead);
662         ret = ReadFile(hConsoleInput, buf, nNumberOfCharsToRead,
663                         lpNumberOfCharsRead, NULL);
664         lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
665         *lpNumberOfCharsRead = strlen(buf);
666         HeapFree( GetProcessHeap(), 0, buf );
667         return ret;
668
669 #ifdef OLD
670         LPSTR buf = (LPSTR)HEAP_xalloc(GetProcessHeap(), 0, 
671                                        nNumberOfCharsToRead);
672         fgets(buf, nNumberOfCharsToRead, CONSOLE_console.conIO);
673
674         if (ferror(CONSOLE_console.conIO) {
675                 HeapFree( GetProcessHeap(), 0, buf );
676                 clearerr();
677                 return FALSE;
678         }
679
680         lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
681         *lpNumberOfCharsRead = strlen(buf);
682         HeapFree( GetProcessHeap(), 0, buf );
683         return TRUE;
684 #endif
685
686 }
687
688
689 /******************************************************************************
690  * ReadConsoleInputA [KERNEL32.569]  Reads data from a console
691  *
692  * PARAMS
693  *    hConsoleInput        [I] Handle to console input buffer
694  *    lpBuffer             [O] Address of buffer for read data
695  *    nLength              [I] Number of records to read
696  *    lpNumberOfEventsRead [O] Address of number of records read
697  *
698  * RETURNS
699  *    Success: TRUE
700  *    Failure: FALSE
701  */
702 BOOL32 WINAPI ReadConsoleInputA( HANDLE32 hConsoleInput,
703                                  LPINPUT_RECORD lpBuffer,
704                                  DWORD nLength, LPDWORD lpNumberOfEventsRead)
705 {
706     FIXME(console, "(%d,%p,%ld,%p): stub\n",hConsoleInput, lpBuffer, nLength,
707           lpNumberOfEventsRead);
708     return ReadConsole32A(hConsoleInput, lpBuffer, nLength, 
709                           lpNumberOfEventsRead, 0);
710 }
711
712
713 /***********************************************************************
714  *            SetConsoleTitle32A   (KERNEL32.476)
715  */
716 BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
717 {
718         PDB32 *pdb = PROCESS_Current();
719         CONSOLE *console;
720         DWORD written;
721         char titleformat[]="\033]2;%s\a"; /*this should work for xterms*/
722         LPSTR titlestring; 
723         BOOL32 ret=FALSE;
724
725         TRACE(console,"(%s)\n",title);
726         
727         console = (CONSOLE *)pdb->console;
728         if (!console)
729           return FALSE;
730         if(console->title) /* Free old title, if there is one */
731           HeapFree( SystemHeap, 0, console->title );
732         console->title = (LPSTR)HeapAlloc(SystemHeap, 0,strlen(title)+1);
733         if(console->title) strcpy(console->title,title);
734
735         titlestring = HeapAlloc(GetProcessHeap(), 0,strlen(title)+strlen(titleformat)+1);
736         if (!titlestring)
737           return FALSE;
738         
739         sprintf(titlestring,titleformat,title);
740         /* Ugly casting */
741         CONSOLE_Write((K32OBJ *)console,titlestring,strlen(titlestring),&written,NULL);
742         if (written == strlen(titlestring))
743           ret =TRUE;
744         HeapFree( GetProcessHeap(), 0, titlestring );
745         return ret;
746 }
747
748
749 /******************************************************************************
750  * SetConsoleTitle32W [KERNEL32.477]  Sets title bar string for console
751  *
752  * PARAMS
753  *    title [I] Address of new title
754  *
755  * NOTES
756  *    This should not be calling the A version
757  *
758  * RETURNS
759  *    Success: TRUE
760  *    Failure: FALSE
761  */
762 BOOL32 WINAPI SetConsoleTitle32W( LPCWSTR title )
763 {
764     BOOL32 ret;
765
766     LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
767     ret = SetConsoleTitle32A(titleA);
768     HeapFree( GetProcessHeap(), 0, titleA );
769     return ret;
770 }
771
772
773 /***********************************************************************
774  *            FlushConsoleInputBuffer   (KERNEL32.132)
775  */
776 BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput)
777 {
778     FIXME(console,"(%d): stub\n",hConsoleInput);
779     return TRUE;
780 }
781
782
783 /******************************************************************************
784  * SetConsoleCursorPosition [KERNEL32.627]
785  * Sets the cursor position in console
786  *
787  * PARAMS
788  *    hConsoleOutput   [I] Handle of console screen buffer
789  *    dwCursorPosition [I] New cursor position coordinates
790  *
791  * RETURNS STD
792  */
793 BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hConsoleOutput, 
794                                         COORD dwCursorPosition )
795 {
796     TRACE(console, "%d (%d x %d)\n", hConsoleOutput, dwCursorPosition.x, 
797           dwCursorPosition.y);
798     /* x are columns, y rows */
799         fprintf(stderr,"\r");
800             /* note: 0x1B == ESC */
801     fprintf(stdout,"%c[%d;%dH", 0x1B, dwCursorPosition.y, dwCursorPosition.x);
802         return TRUE;
803 }
804
805
806 /***********************************************************************
807  *            GetNumberOfConsoleInputEvents   (KERNEL32.246)
808  */
809 BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents)
810 {
811     *nrofevents = 0;
812     FIXME(console,"(%x): stub\n", hcon);
813     return TRUE;
814 }
815
816 /***********************************************************************
817  *            GetNumberOfConsoleMouseButtons   (KERNEL32.358)
818  */
819 BOOL32 WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
820 {
821     FIXME(console,"(%p): stub\n", nrofbuttons);
822     *nrofbuttons = 2;
823     return TRUE;
824 }
825
826
827 /***********************************************************************
828  *            PeekConsoleInputA   (KERNEL32.550)
829  */
830 BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
831                                   LPINPUT_RECORD pirBuffer,
832                                   DWORD cInRecords,
833                                   LPDWORD lpcRead)
834 {
835     pirBuffer = NULL;
836     cInRecords = 0;
837     *lpcRead = 0;
838     FIXME(console,"(%d,%p,%ld,%p): stub\n",hConsoleInput, pirBuffer,
839           cInRecords, lpcRead);
840     return TRUE;
841 }
842
843
844 /***********************************************************************
845  *            PeekConsoleInputW   (KERNEL32.551)
846  */
847 BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
848                                   LPINPUT_RECORD pirBuffer,
849                                   DWORD cInRecords,
850                                   LPDWORD lpcRead)
851 {
852     pirBuffer = NULL;
853     cInRecords = 0;
854     *lpcRead = 0;
855     FIXME(console,"(%d,%p,%ld,%p): stub\n", hConsoleInput, pirBuffer,
856           cInRecords, lpcRead);
857     return TRUE;
858 }
859
860
861 /******************************************************************************
862  * GetConsoleCursorInfo32 [KERNEL32.296]  Gets size and visibility of console
863  *
864  * PARAMS
865  *    hcon  [I] Handle to console screen buffer
866  *    cinfo [O] Address of cursor information
867  *
868  * RETURNS
869  *    Success: TRUE
870  *    Failure: FALSE
871  */
872 BOOL32 WINAPI GetConsoleCursorInfo32( HANDLE32 hcon,
873                                       LPCONSOLE_CURSOR_INFO cinfo )
874 {
875     FIXME(console, "(%x,%p): stub\n", hcon, cinfo);
876     if (!cinfo) return FALSE;
877     cinfo->dwSize = 10;      /* 10% of character box is cursor.  */
878     cinfo->bVisible = TRUE;  /* Cursor is visible.  */
879     return TRUE;
880 }
881
882
883 /******************************************************************************
884  * SetConsoleCursorInfo32 [KERNEL32.626]  Sets size and visibility of cursor
885  *
886  * RETURNS
887  *    Success: TRUE
888  *    Failure: FALSE
889  */
890 BOOL32 WINAPI SetConsoleCursorInfo32( 
891     HANDLE32 hcon,                /* [in] Handle to console screen buffer */
892     LPCONSOLE_CURSOR_INFO cinfo)  /* [in] Address of cursor information */
893 {
894     FIXME(console, "(%x,%ld,%i): stub\n", hcon,cinfo->dwSize,cinfo->bVisible);
895     return TRUE;
896 }
897
898
899 /******************************************************************************
900  * SetConsoleWindowInfo [KERNEL32.634]  Sets size and position of console
901  *
902  * RETURNS
903  *    Success: TRUE
904  *    Failure: FALSE
905  */
906 BOOL32 WINAPI SetConsoleWindowInfo(
907     HANDLE32 hcon,       /* [in] Handle to console screen buffer */
908     BOOL32 bAbsolute,    /* [in] Coordinate type flag */
909     LPSMALL_RECT window) /* [in] Address of new window rectangle */
910 {
911     FIXME(console, "(%x,%d,%p): stub\n", hcon, bAbsolute, window);
912     return TRUE;
913 }
914
915
916 /******************************************************************************
917  * SetConsoleTextAttribute32 [KERNEL32.631]  Sets colors for text
918  *
919  * Sets the foreground and background color attributes of characters
920  * written to the screen buffer.
921  *
922  * RETURNS
923  *    Success: TRUE
924  *    Failure: FALSE
925  */
926 BOOL32 WINAPI SetConsoleTextAttribute32(HANDLE32 hConsoleOutput,WORD wAttr)
927 {
928     int forecolor = 0;
929     int backcolor = 0;
930     int boldtext = 0;
931     unsigned int attrib;
932     
933     attrib = wAttr;
934     if( attrib >= BACKGROUND_INTENSITY )
935         attrib -= BACKGROUND_INTENSITY; /* Background intensity is ignored */
936     if( attrib >= BACKGROUND_RED )
937     {
938         attrib -= BACKGROUND_RED;
939         if( attrib >= BACKGROUND_GREEN )
940         {
941             attrib -= BACKGROUND_GREEN;
942             if( attrib >= BACKGROUND_BLUE )
943             {
944                 attrib -= BACKGROUND_BLUE;
945                 backcolor = 47; /* White background */
946             }
947             else
948                 backcolor = 43; /* Yellow background */
949         }
950         else if( attrib >= BACKGROUND_BLUE )
951         {
952             attrib -= BACKGROUND_BLUE;
953             backcolor = 45; /* Magenta background */
954         }
955         else
956             backcolor = 41; /* Red Background */
957     }
958     else if( attrib >= BACKGROUND_GREEN )
959     {
960         attrib -= BACKGROUND_GREEN;
961         if( attrib >= BACKGROUND_BLUE )
962         {
963             attrib -= BACKGROUND_BLUE;
964             backcolor = 46; /* Cyan background */
965         }
966         else
967             backcolor = 42; /* Green background */
968     }
969     else if( attrib >= BACKGROUND_BLUE )
970     {
971         attrib -= BACKGROUND_BLUE;
972         backcolor = 44; /* Blue background */
973     }
974     else
975         backcolor = 40; /* Black background */
976     if( attrib >= FOREGROUND_INTENSITY )
977     {
978         attrib -= FOREGROUND_INTENSITY;
979         boldtext = 1;   /* Bold attribute is on */
980     }
981     if( attrib >= FOREGROUND_RED )
982     {
983         attrib -= FOREGROUND_RED;
984         if( attrib >= FOREGROUND_GREEN )
985         {
986             attrib -= FOREGROUND_GREEN;
987             if( attrib >= FOREGROUND_BLUE )
988             {
989                 attrib -= FOREGROUND_BLUE;
990                 forecolor = 37; /* White foreground */
991             }
992             else
993                 forecolor = 33; /* Yellow foreground */
994         }
995         else if( attrib >= FOREGROUND_BLUE )
996         {
997             attrib -= FOREGROUND_BLUE;
998             forecolor = 35; /* Magenta foreground */
999         }
1000         else
1001             forecolor = 31; /* Red foreground */
1002     }
1003     else if( attrib >= FOREGROUND_GREEN )
1004     {
1005         attrib -= FOREGROUND_GREEN;
1006         if( attrib >= FOREGROUND_BLUE )
1007         {
1008             attrib -= FOREGROUND_BLUE;
1009             forecolor = 36; /* Cyan foreground */
1010         }
1011         else
1012             forecolor = 32; /* Green foreground */
1013     }
1014     else if( attrib >= FOREGROUND_BLUE )
1015     {
1016         attrib -= FOREGROUND_BLUE;
1017         forecolor = 34; /* Blue foreground */
1018     }
1019     else
1020         forecolor = 30; /* Black foreground */
1021
1022     fprintf(stdout,"%c[%d;%d;%dm",0x1B,boldtext,forecolor,backcolor);
1023     return TRUE;
1024 }
1025
1026
1027 /******************************************************************************
1028  * SetConsoleScreenBufferSize [KERNEL32.630]  Changes size of console 
1029  *
1030  * PARAMS
1031  *    hConsoleOutput [I] Handle to console screen buffer
1032  *    dwSize         [I] New size in character rows and cols
1033  *
1034  * RETURNS
1035  *    Success: TRUE
1036  *    Failure: FALSE
1037  */
1038 BOOL32 WINAPI SetConsoleScreenBufferSize( HANDLE32 hConsoleOutput, 
1039                                           COORD dwSize )
1040 {
1041     FIXME(console, "(%d,%dx%d): stub\n",hConsoleOutput,dwSize.x,dwSize.y);
1042     return TRUE;
1043 }
1044
1045
1046 /******************************************************************************
1047  * FillConsoleOutputCharacterA [KERNEL32.242]
1048  *
1049  * PARAMS
1050  *    hConsoleOutput    [I] Handle to screen buffer
1051  *    cCharacter        [I] Character to write
1052  *    nLength           [I] Number of cells to write to
1053  *    dwCoord           [I] Coords of first cell
1054  *    lpNumCharsWritten [O] Pointer to number of cells written
1055  *
1056  * RETURNS
1057  *    Success: TRUE
1058  *    Failure: FALSE
1059  */
1060 BOOL32 WINAPI FillConsoleOutputCharacterA(
1061     HANDLE32 hConsoleOutput,
1062     BYTE cCharacter,
1063     DWORD nLength,
1064     COORD dwCoord,
1065     LPDWORD lpNumCharsWritten)
1066 {
1067     long count;
1068     SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1069     for(count=0;count<nLength;count++)
1070         putc(cCharacter,stdout);
1071     *lpNumCharsWritten = nLength;
1072     return TRUE;
1073 }
1074
1075
1076 /******************************************************************************
1077  * FillConsoleOutputCharacterW [KERNEL32.243]  Writes characters to console
1078  *
1079  * PARAMS
1080  *    hConsoleOutput    [I] Handle to screen buffer
1081  *    cCharacter        [I] Character to write
1082  *    nLength           [I] Number of cells to write to
1083  *    dwCoord           [I] Coords of first cell
1084  *    lpNumCharsWritten [O] Pointer to number of cells written
1085  *
1086  * RETURNS
1087  *    Success: TRUE
1088  *    Failure: FALSE
1089  */
1090 BOOL32 WINAPI FillConsoleOutputCharacterW(HANDLE32 hConsoleOutput,
1091                                             WCHAR cCharacter,
1092                                             DWORD nLength,
1093                                            COORD dwCoord, 
1094                                             LPDWORD lpNumCharsWritten)
1095 {
1096     long count;
1097     SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1098     for(count=0;count<nLength;count++)
1099         putc(cCharacter,stdout);
1100     *lpNumCharsWritten = nLength;
1101     return TRUE;
1102 }
1103
1104
1105 /******************************************************************************
1106  * FillConsoleOutputAttribute [KERNEL32.241]  Sets attributes for console
1107  *
1108  * PARAMS
1109  *    hConsoleOutput    [I] Handle to screen buffer
1110  *    wAttribute        [I] Color attribute to write
1111  *    nLength           [I] Number of cells to write to
1112  *    dwCoord           [I] Coords of first cell
1113  *    lpNumAttrsWritten [O] Pointer to number of cells written
1114  *
1115  * RETURNS
1116  *    Success: TRUE
1117  *    Failure: FALSE
1118  */
1119 BOOL32 WINAPI FillConsoleOutputAttribute( HANDLE32 hConsoleOutput, 
1120               WORD wAttribute, DWORD nLength, COORD dwCoord, 
1121               LPDWORD lpNumAttrsWritten)
1122 {
1123     FIXME(console, "(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1124           wAttribute,nLength,dwCoord.x,dwCoord.y,lpNumAttrsWritten);
1125     *lpNumAttrsWritten = nLength;
1126     return TRUE;
1127 }
1128
1129 /******************************************************************************
1130  * ReadConsoleOutputCharacter32A [KERNEL32.573]
1131  * 
1132  * BUGS
1133  *   Unimplemented
1134  */
1135 BOOL32 WINAPI ReadConsoleOutputCharacter32A(HANDLE32 hConsoleOutput, 
1136               LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1137 {
1138     FIXME(console, "(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1139           dword,coord.x,coord.y,lpdword);
1140     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1141     return FALSE;
1142 }
1143
1144
1145 /******************************************************************************
1146  * ScrollConsoleScreenBuffer [KERNEL32.612]
1147  * 
1148  * BUGS
1149  *   Unimplemented
1150  */
1151 BOOL32 WINAPI ScrollConsoleScreenBuffer( HANDLE32 hConsoleOutput, 
1152               LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1153               COORD dwDestOrigin, LPCHAR_INFO lpFill)
1154 {
1155     FIXME(console, "(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1156           lpClipRect,dwDestOrigin.x,dwDestOrigin.y,lpFill);
1157     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1158     return FALSE;
1159 }