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