Add a note about WinPrinters.
[wine.git] / win32 / console.c
blob20152209b1f315b19aa156a8e668b494c90cfe8a
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 * Copyright 1997 Karl Garrison
6 * Copyright 1998 John Richardson
7 */
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"
31 static CONSOLE_SCREEN_BUFFER_INFO dummyinfo =
33 {80, 24},
34 {0, 0},
36 {0, 0, 79, 23},
37 {80, 24}
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
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;
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;
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);
72 const K32OBJ_OPS CONSOLE_Ops =
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 */
85 /***********************************************************************
86 * CONSOLE_Destroy
88 static void CONSOLE_Destroy(K32OBJ *obj)
90 CONSOLE *console = (CONSOLE *)obj;
91 assert(obj->type == K32OBJ_CONSOLE);
93 obj->type = K32OBJ_UNKNOWN;
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);
102 HeapFree(SystemHeap, 0, console);
106 /***********************************************************************
107 * CONSOLE_Read
109 * NOTES
110 * lpOverlapped is ignored
112 static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
113 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
115 CONSOLE *console = (CONSOLE *)ptr;
116 int result;
118 TRACE(console, "%p %p %ld\n", ptr, lpBuffer,
119 nNumberOfChars);
121 *lpNumberOfChars = 0;
123 if ((result = read(console->slave, lpBuffer, nNumberOfChars)) == -1) {
124 FILE_SetDosError();
125 return FALSE;
127 *lpNumberOfChars = result;
128 return TRUE;
132 /***********************************************************************
133 * CONSOLE_Write
135 * NOTES
136 * lpOverlapped is ignored
138 static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer,
139 DWORD nNumberOfChars,
140 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
142 CONSOLE *console = (CONSOLE *)ptr;
143 int result;
145 TRACE(console, "%p %p %ld\n", ptr, lpBuffer,
146 nNumberOfChars);
148 *lpNumberOfChars = 0;
151 * I assume this loop around EAGAIN is here because
152 * win32 doesn't have interrupted system calls
155 for (;;)
157 result = write(console->slave, lpBuffer, nNumberOfChars);
158 if (result != -1) {
159 *lpNumberOfChars = result;
160 return TRUE;
162 if (errno != EINTR) {
163 FILE_SetDosError();
164 return FALSE;
170 /******************************************************************************
171 * SetConsoleCtrlHandler [KERNEL32.459] Adds function to calling process list
173 * PARAMS
174 * func [I] Address of handler function
175 * add [I] Handler to add or remove
177 * RETURNS
178 * Success: TRUE
179 * Failure: FALSE
181 * CHANGED
182 * James Sutherland (JamesSutherland@gmx.de)
183 * Added global variables console_ignore_ctrl_c and handlers[]
184 * Does not yet do any error checking, or set LastError if failed.
185 * This doesn't yet matter, since these handlers are not yet called...!
187 static unsigned int console_ignore_ctrl_c = 0;
188 static HANDLER_ROUTINE *handlers[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
189 BOOL32 WINAPI SetConsoleCtrlHandler( HANDLER_ROUTINE *func, BOOL32 add )
191 unsigned int alloc_loop = sizeof(handlers)/sizeof(HANDLER_ROUTINE *);
192 unsigned int done = 0;
193 FIXME(console, "(%p,%i) - no error checking or testing yet\n", func, add);
194 if (!func)
196 console_ignore_ctrl_c = add;
197 return TRUE;
199 if (add)
201 for (;alloc_loop--;)
202 if (!handlers[alloc_loop] && !done)
204 handlers[alloc_loop] = func;
205 done++;
207 if (!done)
208 FIXME(console, "Out of space on CtrlHandler table\n");
209 return(done);
211 else
213 for (;alloc_loop--;)
214 if (handlers[alloc_loop] == func && !done)
216 handlers[alloc_loop] = 0;
217 done++;
219 if (!done)
220 WARN(console, "Attempt to remove non-installed CtrlHandler %p\n",
221 func);
222 return (done);
224 return (done);
228 /******************************************************************************
229 * GenerateConsoleCtrlEvent [KERNEL32.275] Simulate a CTRL-C or CTRL-BREAK
231 * PARAMS
232 * dwCtrlEvent [I] Type of event
233 * dwProcessGroupID [I] Process group ID to send event to
235 * NOTES
236 * Doesn't yet work...!
238 * RETURNS
239 * Success: True
240 * Failure: False (and *should* [but doesn't] set LastError)
242 BOOL32 WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent,
243 DWORD dwProcessGroupID )
245 if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
247 ERR( console, "invalid event %d for PGID %d\n",
248 (unsigned short)dwCtrlEvent, dwProcessGroupID );
249 return FALSE;
251 if (dwProcessGroupID == GetCurrentProcessId() )
253 FIXME( console, "Attempt to send event %d to self - stub\n",
254 (unsigned short)dwCtrlEvent );
255 return FALSE;
257 FIXME( console,"event %d to external PGID %d - not implemented yet\n",
258 (unsigned short)dwCtrlEvent, dwProcessGroupID );
259 return FALSE;
263 /******************************************************************************
264 * CreateConsoleScreenBuffer [KERNEL32.151] Creates a console screen buffer
266 * PARAMS
267 * dwDesiredAccess [I] Access flag
268 * dwShareMode [I] Buffer share mode
269 * sa [I] Security attributes
270 * dwFlags [I] Type of buffer to create
271 * lpScreenBufferData [I] Reserved
273 * NOTES
274 * Should call SetLastError
276 * RETURNS
277 * Success: Handle to new console screen buffer
278 * Failure: INVALID_HANDLE_VALUE
280 HANDLE32 WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
281 DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa,
282 DWORD dwFlags, LPVOID lpScreenBufferData )
284 FIXME(console, "(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess,
285 dwShareMode, sa, dwFlags, lpScreenBufferData);
286 return 1;
290 /***********************************************************************
291 * GetConsoleScreenBufferInfo (KERNEL32.190)
293 BOOL32 WINAPI GetConsoleScreenBufferInfo( HANDLE32 hConsoleOutput,
294 LPCONSOLE_SCREEN_BUFFER_INFO csbi )
296 csbi->dwSize.x = 80;
297 csbi->dwSize.y = 24;
298 csbi->dwCursorPosition.x = 0;
299 csbi->dwCursorPosition.y = 0;
300 csbi->wAttributes = 0;
301 csbi->srWindow.Left = 0;
302 csbi->srWindow.Right = 79;
303 csbi->srWindow.Top = 0;
304 csbi->srWindow.Bottom = 23;
305 csbi->dwMaximumWindowSize.x = 80;
306 csbi->dwMaximumWindowSize.y = 24;
307 return TRUE;
311 /******************************************************************************
312 * SetConsoleActiveScreenBuffer [KERNEL32.623] Sets buffer to current console
314 * RETURNS
315 * Success: TRUE
316 * Failure: FALSE
318 BOOL32 WINAPI SetConsoleActiveScreenBuffer(
319 HANDLE32 hConsoleOutput) /* [in] Handle to console screen buffer */
321 FIXME(console, "(%x): stub\n", hConsoleOutput);
322 return FALSE;
326 /***********************************************************************
327 * GetLargestConsoleWindowSize (KERNEL32.226)
329 DWORD WINAPI GetLargestConsoleWindowSize( HANDLE32 hConsoleOutput )
331 return (DWORD)MAKELONG(dummyinfo.dwMaximumWindowSize.x,dummyinfo.dwMaximumWindowSize.y);
334 /***********************************************************************
335 * FreeConsole (KERNEL32.267)
337 BOOL32 WINAPI FreeConsole(VOID)
340 PDB32 *pdb = PROCESS_Current();
341 CONSOLE *console;
343 SYSTEM_LOCK();
345 console = (CONSOLE *)pdb->console;
347 if (console == NULL) {
348 SetLastError(ERROR_INVALID_PARAMETER);
349 return FALSE;
352 HANDLE_CloseAll( pdb, &console->header );
354 K32OBJ_DecCount( &console->header );
355 pdb->console = NULL;
356 SYSTEM_UNLOCK();
357 return TRUE;
361 /**
362 * It looks like the openpty that comes with glibc in RedHat 5.0
363 * is buggy (second call returns what looks like a dup of 0 and 1
364 * instead of a new pty), this is a generic replacement.
366 static int wine_openpty(int *master, int *slave, char *name,
367 struct termios *term, struct winsize *winsize)
369 int fdm, fds;
370 char *ptr1, *ptr2;
371 char pts_name[512];
373 strcpy (pts_name, "/dev/ptyXY");
375 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
376 pts_name[8] = *ptr1;
377 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
378 pts_name[9] = *ptr2;
380 if ((fdm = open(pts_name, O_RDWR)) < 0) {
381 if (errno == ENOENT)
382 return -1;
383 else
384 continue;
386 pts_name[5] = 't';
387 if ((fds = open(pts_name, O_RDWR)) < 0) {
388 pts_name[5] = 'p';
389 continue;
391 *master = fdm;
392 *slave = fds;
394 if (term != NULL)
395 tcsetattr(*slave, TCSANOW, term);
396 if (winsize != NULL)
397 ioctl(*slave, TIOCSWINSZ, winsize);
398 if (name != NULL)
399 strcpy(name, pts_name);
400 return fds;
403 return -1;
406 static BOOL32 wine_createConsole(int *master, int *slave, int *pid)
408 struct termios term;
409 char buf[1024];
410 char c = '\0';
411 int status = 0;
412 int i;
414 if (tcgetattr(0, &term) < 0) return FALSE;
415 term.c_lflag |= ICANON;
416 term.c_lflag &= ~ECHO;
417 if (wine_openpty(master, slave, NULL, &term, NULL) < 0) return FALSE;
419 if ((*pid=fork()) == 0) {
420 tcsetattr(*slave, TCSADRAIN, &term);
421 sprintf(buf, "-Sxx%d", *master);
422 execlp("xterm", "xterm", buf, NULL);
423 ERR(console, "error creating AllocConsole xterm\n");
424 exit(1);
427 /* most xterms like to print their window ID when used with -S;
428 * read it and continue before the user has a chance...
429 * NOTE: this is the reason we started xterm with ECHO off,
430 * we'll turn it back on below
433 for (i=0; c!='\n'; (status=read(*slave, &c, 1)), i++) {
434 if (status == -1 && c == '\0') {
435 /* wait for xterm to be created */
436 usleep(100);
438 if (i > 10000) {
439 WARN(console, "can't read xterm WID\n");
440 kill(*pid, SIGKILL);
441 return FALSE;
444 term.c_lflag |= ECHO;
445 tcsetattr(*master, TCSADRAIN, &term);
447 return TRUE;
451 /***********************************************************************
452 * CONSOLE_GetConsoleHandle
453 * returns a 16-bit style console handle
454 * note: only called from _lopen
456 HFILE32 CONSOLE_GetConsoleHandle(VOID)
458 PDB32 *pdb = PROCESS_Current();
459 HFILE32 handle = HFILE_ERROR32;
461 SYSTEM_LOCK();
462 if (pdb->console != NULL) {
463 CONSOLE *console = (CONSOLE *)pdb->console;
464 handle = (HFILE32)HANDLE_Alloc(pdb, &console->header, 0, TRUE, -1);
466 SYSTEM_UNLOCK();
467 return handle;
470 /***********************************************************************
471 * AllocConsole (KERNEL32.103)
473 * creates an xterm with a pty to our program
475 BOOL32 WINAPI AllocConsole(VOID)
478 int master;
479 int slave;
480 int pid;
481 PDB32 *pdb = PROCESS_Current();
482 CONSOLE *console;
483 HANDLE32 hIn, hOut, hErr;
485 SYSTEM_LOCK(); /* FIXME: really only need to lock the process */
487 SetLastError(ERROR_CANNOT_MAKE); /* this might not be the right
488 error, but it's a good guess :) */
490 console = (CONSOLE *)pdb->console;
492 /* don't create a console if we already have one */
493 if (console != NULL) {
494 SetLastError(ERROR_ACCESS_DENIED);
495 SYSTEM_UNLOCK();
496 return FALSE;
499 if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console))))
501 SYSTEM_UNLOCK();
502 return FALSE;
505 console->header.type = K32OBJ_CONSOLE;
506 console->header.refcount = 1;
507 console->pid = -1;
508 console->title = NULL;
510 if (wine_createConsole(&master, &slave, &pid) == FALSE) {
511 K32OBJ_DecCount(&console->header);
512 SYSTEM_UNLOCK();
513 return FALSE;
516 /* save the pid and other info for future use */
517 console->master = master;
518 console->slave = slave;
519 console->pid = pid;
521 if ((hIn = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
523 K32OBJ_DecCount(&console->header);
524 SYSTEM_UNLOCK();
525 return FALSE;
528 if ((hOut = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
530 CloseHandle(hIn);
531 K32OBJ_DecCount(&console->header);
532 SYSTEM_UNLOCK();
533 return FALSE;
537 if ((hErr = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
539 CloseHandle(hIn);
540 CloseHandle(hOut);
541 K32OBJ_DecCount(&console->header);
542 SYSTEM_UNLOCK();
543 return FALSE;
546 /* associate this console with the process */
547 if (pdb->console) K32OBJ_DecCount( pdb->console );
548 pdb->console = (K32OBJ *)console;
550 /* NT resets the STD_*_HANDLEs on console alloc */
551 SetStdHandle(STD_INPUT_HANDLE, hIn);
552 SetStdHandle(STD_OUTPUT_HANDLE, hOut);
553 SetStdHandle(STD_ERROR_HANDLE, hErr);
555 SetLastError(ERROR_SUCCESS);
556 SYSTEM_UNLOCK();
557 SetConsoleTitle32A("Wine Console");
558 return TRUE;
562 /******************************************************************************
563 * GetConsoleCP [KERNEL32.295] Returns the OEM code page for the console
565 * RETURNS
566 * Code page code
568 UINT32 WINAPI GetConsoleCP(VOID)
570 return GetACP();
574 /***********************************************************************
575 * GetConsoleOutputCP (KERNEL32.189)
577 UINT32 WINAPI GetConsoleOutputCP(VOID)
579 return GetConsoleCP();
582 /***********************************************************************
583 * GetConsoleMode (KERNEL32.188)
585 BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode)
587 *mode = ENABLE_PROCESSED_INPUT |
588 ENABLE_LINE_INPUT |
589 ENABLE_ECHO_INPUT;
590 return TRUE;
594 /******************************************************************************
595 * SetConsoleMode [KERNEL32.628] Sets input mode of console's input buffer
597 * PARAMS
598 * hcon [I] Handle to console input or screen buffer
599 * mode [I] Input or output mode to set
601 * RETURNS
602 * Success: TRUE
603 * Failure: FALSE
605 BOOL32 WINAPI SetConsoleMode( HANDLE32 hcon, DWORD mode )
607 FIXME(console,"(0x%08x,0x%08lx): stub\n",hcon,mode);
608 return TRUE;
612 /***********************************************************************
613 * GetConsoleTitleA (KERNEL32.191)
615 DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size)
617 PDB32 *pdb = PROCESS_Current();
618 CONSOLE *console= (CONSOLE *)pdb->console;
620 if(console && console->title)
622 lstrcpyn32A(title,console->title,size);
623 return strlen(title);
625 return 0;
629 /******************************************************************************
630 * GetConsoleTitle32W [KERNEL32.192] Retrieves title string for console
632 * PARAMS
633 * title [O] Address of buffer for title
634 * size [I] Size of buffer
636 * RETURNS
637 * Success: Length of string copied
638 * Failure: 0
640 DWORD WINAPI GetConsoleTitle32W( LPWSTR title, DWORD size )
642 PDB32 *pdb = PROCESS_Current();
643 CONSOLE *console= (CONSOLE *)pdb->console;
644 if(console && console->title)
646 lstrcpynAtoW(title,console->title,size);
647 return (lstrlen32W(title));
649 return 0;
653 /***********************************************************************
654 * WriteConsoleA (KERNEL32.729)
656 BOOL32 WINAPI WriteConsole32A( HANDLE32 hConsoleOutput,
657 LPCVOID lpBuffer,
658 DWORD nNumberOfCharsToWrite,
659 LPDWORD lpNumberOfCharsWritten,
660 LPVOID lpReserved )
662 /* FIXME: should I check if this is a console handle? */
663 return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
664 lpNumberOfCharsWritten, NULL);
668 /***********************************************************************
669 * WriteConsoleOutputA (KERNEL32.732)
671 BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
672 LPCHAR_INFO lpBuffer,
673 COORD dwBufferSize,
674 COORD dwBufferCoord,
675 LPSMALL_RECT lpWriteRegion)
677 int i,j,off=0,lastattr=-1;
678 char buffer[200];
679 DWORD res;
680 static int colormap[8] = {
681 0,4,2,6,
682 1,5,3,7,
685 TRACE(console,"wr: top = %d, bottom=%d, left=%d,right=%d\n",
686 lpWriteRegion->Top,
687 lpWriteRegion->Bottom,
688 lpWriteRegion->Left,
689 lpWriteRegion->Right
692 for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) {
693 sprintf(buffer,"%c[%d;%dH",27,i,lpWriteRegion->Left);
694 WriteFile(hConsoleOutput,buffer,strlen(buffer),&res,NULL);
695 if (lastattr != lpBuffer[off].Attributes) {
696 lastattr = lpBuffer[off].Attributes;
697 sprintf(buffer,"%c[0;3%d;4%d",27,colormap[lastattr&7],colormap[(lastattr&0x70)>>4]);
698 if (lastattr & FOREGROUND_INTENSITY)
699 strcat(buffer,";1");
700 /* BACKGROUND_INTENSITY */
701 strcat(buffer,"m");
702 WriteFile(hConsoleOutput,buffer,strlen(buffer),&res,NULL);
704 for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++)
705 WriteFile(hConsoleOutput,&(lpBuffer[off++].Char.AsciiChar),1,&res,NULL);
707 sprintf(buffer,"%c[0m",27);
708 WriteFile(hConsoleOutput,buffer,strlen(buffer),&res,NULL);
709 return TRUE;
712 /***********************************************************************
713 * WriteConsoleW (KERNEL32.577)
715 BOOL32 WINAPI WriteConsole32W( HANDLE32 hConsoleOutput,
716 LPCVOID lpBuffer,
717 DWORD nNumberOfCharsToWrite,
718 LPDWORD lpNumberOfCharsWritten,
719 LPVOID lpReserved )
721 BOOL32 ret;
722 LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite );
724 lstrcpynWtoA( xstring, lpBuffer,nNumberOfCharsToWrite);
726 /* FIXME: should I check if this is a console handle? */
727 ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite,
728 lpNumberOfCharsWritten, NULL);
729 HeapFree( GetProcessHeap(), 0, xstring );
730 return ret;
734 /***********************************************************************
735 * ReadConsoleA (KERNEL32.419)
737 BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput,
738 LPVOID lpBuffer,
739 DWORD nNumberOfCharsToRead,
740 LPDWORD lpNumberOfCharsRead,
741 LPVOID lpReserved )
743 return ReadFile(hConsoleInput, lpBuffer, nNumberOfCharsToRead,
744 lpNumberOfCharsRead, NULL);
746 #ifdef OLD
747 fgets(lpBuffer,nNumberOfCharsToRead, CONSOLE_console.conIO);
748 if (ferror(CONSOLE_console.conIO) {
749 clearerr();
750 return FALSE;
752 *lpNumberOfCharsRead = strlen(lpBuffer);
753 return TRUE;
754 #endif
758 /***********************************************************************
759 * ReadConsoleW (KERNEL32.427)
761 BOOL32 WINAPI ReadConsole32W( HANDLE32 hConsoleInput,
762 LPVOID lpBuffer,
763 DWORD nNumberOfCharsToRead,
764 LPDWORD lpNumberOfCharsRead,
765 LPVOID lpReserved )
767 BOOL32 ret;
768 LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0,
769 nNumberOfCharsToRead);
770 ret = ReadFile(hConsoleInput, buf, nNumberOfCharsToRead,
771 lpNumberOfCharsRead, NULL);
772 lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
773 *lpNumberOfCharsRead = strlen(buf);
774 HeapFree( GetProcessHeap(), 0, buf );
775 return ret;
777 #ifdef OLD
778 LPSTR buf = (LPSTR)HEAP_xalloc(GetProcessHeap(), 0,
779 nNumberOfCharsToRead);
780 fgets(buf, nNumberOfCharsToRead, CONSOLE_console.conIO);
782 if (ferror(CONSOLE_console.conIO) {
783 HeapFree( GetProcessHeap(), 0, buf );
784 clearerr();
785 return FALSE;
788 lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
789 *lpNumberOfCharsRead = strlen(buf);
790 HeapFree( GetProcessHeap(), 0, buf );
791 return TRUE;
792 #endif
797 /******************************************************************************
798 * ReadConsoleInputA [KERNEL32.569] Reads data from a console
800 * PARAMS
801 * hConsoleInput [I] Handle to console input buffer
802 * lpBuffer [O] Address of buffer for read data
803 * nLength [I] Number of records to read
804 * lpNumberOfEventsRead [O] Address of number of records read
806 * RETURNS
807 * Success: TRUE
808 * Failure: FALSE
810 BOOL32 WINAPI ReadConsoleInputA( HANDLE32 hConsoleInput,
811 LPINPUT_RECORD lpBuffer,
812 DWORD nLength, LPDWORD lpNumberOfEventsRead)
814 FIXME(console, "(%d,%p,%ld,%p): stub\n",hConsoleInput, lpBuffer, nLength,
815 lpNumberOfEventsRead);
816 return ReadConsole32A(hConsoleInput, lpBuffer, nLength,
817 lpNumberOfEventsRead, 0);
821 /***********************************************************************
822 * SetConsoleTitle32A (KERNEL32.476)
824 BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
826 PDB32 *pdb = PROCESS_Current();
827 CONSOLE *console;
828 DWORD written;
829 char titleformat[]="\033]2;%s\a"; /*this should work for xterms*/
830 LPSTR titlestring;
831 BOOL32 ret=FALSE;
833 TRACE(console,"(%s)\n",title);
835 console = (CONSOLE *)pdb->console;
836 if (!console)
837 return FALSE;
838 if(console->title) /* Free old title, if there is one */
839 HeapFree( SystemHeap, 0, console->title );
840 console->title = (LPSTR)HeapAlloc(SystemHeap, 0,strlen(title)+1);
841 if(console->title) strcpy(console->title,title);
843 titlestring = HeapAlloc(GetProcessHeap(), 0,strlen(title)+strlen(titleformat)+1);
844 if (!titlestring)
845 return FALSE;
847 sprintf(titlestring,titleformat,title);
848 /* Ugly casting */
849 CONSOLE_Write((K32OBJ *)console,titlestring,strlen(titlestring),&written,NULL);
850 if (written == strlen(titlestring))
851 ret =TRUE;
852 HeapFree( GetProcessHeap(), 0, titlestring );
853 return ret;
857 /******************************************************************************
858 * SetConsoleTitle32W [KERNEL32.477] Sets title bar string for console
860 * PARAMS
861 * title [I] Address of new title
863 * NOTES
864 * This should not be calling the A version
866 * RETURNS
867 * Success: TRUE
868 * Failure: FALSE
870 BOOL32 WINAPI SetConsoleTitle32W( LPCWSTR title )
872 BOOL32 ret;
874 LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
875 ret = SetConsoleTitle32A(titleA);
876 HeapFree( GetProcessHeap(), 0, titleA );
877 return ret;
881 /***********************************************************************
882 * FlushConsoleInputBuffer (KERNEL32.132)
884 BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput)
886 FIXME(console,"(%d): stub\n",hConsoleInput);
887 return TRUE;
891 /******************************************************************************
892 * SetConsoleCursorPosition [KERNEL32.627]
893 * Sets the cursor position in console
895 * PARAMS
896 * hConsoleOutput [I] Handle of console screen buffer
897 * dwCursorPosition [I] New cursor position coordinates
899 * RETURNS STD
901 BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hConsoleOutput,
902 COORD dwCursorPosition )
904 TRACE(console, "%d (%d x %d)\n", hConsoleOutput, dwCursorPosition.x,
905 dwCursorPosition.y);
906 /* x are columns, y rows */
907 fprintf(stderr,"\r");
908 /* note: 0x1B == ESC */
909 fprintf(stdout,"%c[%d;%dH", 0x1B, dwCursorPosition.y, dwCursorPosition.x);
910 return TRUE;
914 /***********************************************************************
915 * GetNumberOfConsoleInputEvents (KERNEL32.246)
917 BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents)
919 *nrofevents = 0;
920 FIXME(console,"(%x): stub\n", hcon);
921 return TRUE;
924 /***********************************************************************
925 * GetNumberOfConsoleMouseButtons (KERNEL32.358)
927 BOOL32 WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
929 FIXME(console,"(%p): stub\n", nrofbuttons);
930 *nrofbuttons = 2;
931 return TRUE;
935 /***********************************************************************
936 * PeekConsoleInputA (KERNEL32.550)
938 BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
939 LPINPUT_RECORD pirBuffer,
940 DWORD cInRecords,
941 LPDWORD lpcRead)
943 fd_set infds;
944 int i,fd = FILE_GetUnixHandle(hConsoleInput);
945 struct timeval tv;
946 char inchar;
947 DWORD res;
948 static int keystate[256];
949 LPINPUT_RECORD ir = pirBuffer;
951 TRACE(console,"(%d,%p,%ld,%p): stub\n",hConsoleInput, pirBuffer, cInRecords, lpcRead);
953 memset(&tv,0,sizeof(tv));
954 FD_ZERO(&infds);
955 FD_SET(fd,&infds);
956 select(fd+1,&infds,NULL,NULL,&tv);
958 if (FD_ISSET(fd,&infds)) {
959 ReadFile(hConsoleInput,&inchar,1,&res,NULL);
960 for (i=0;i<256;i++) {
961 if (keystate[i] && i!=inchar) {
962 ir->EventType = 1;
963 ir->Event.KeyEvent.bKeyDown = 0;
964 ir->Event.KeyEvent.wRepeatCount = 0;
965 ir->Event.KeyEvent.wVirtualKeyCode = 0;
966 ir->Event.KeyEvent.wVirtualScanCode = 0;
967 ir->Event.KeyEvent.uChar.AsciiChar = i;
968 ir->Event.KeyEvent.dwControlKeyState = 0;
969 ir++;
970 keystate[i]=0;
974 ir->EventType = 1; /* Key_event */
975 ir->Event.KeyEvent.bKeyDown = 1;
976 ir->Event.KeyEvent.wRepeatCount = 0;
977 ir->Event.KeyEvent.wVirtualKeyCode = 0;
978 ir->Event.KeyEvent.wVirtualScanCode = 0;
979 ir->Event.KeyEvent.uChar.AsciiChar = inchar;
980 ir->Event.KeyEvent.dwControlKeyState = 0;
981 keystate[inchar]=1;
982 ir++;
983 *lpcRead = ir-pirBuffer;
984 } else {
985 *lpcRead = 0;
987 return TRUE;
991 /***********************************************************************
992 * PeekConsoleInputW (KERNEL32.551)
994 BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
995 LPINPUT_RECORD pirBuffer,
996 DWORD cInRecords,
997 LPDWORD lpcRead)
999 pirBuffer = NULL;
1000 cInRecords = 0;
1001 *lpcRead = 0;
1002 FIXME(console,"(%d,%p,%ld,%p): stub\n", hConsoleInput, pirBuffer,
1003 cInRecords, lpcRead);
1004 return TRUE;
1008 /******************************************************************************
1009 * GetConsoleCursorInfo32 [KERNEL32.296] Gets size and visibility of console
1011 * PARAMS
1012 * hcon [I] Handle to console screen buffer
1013 * cinfo [O] Address of cursor information
1015 * RETURNS
1016 * Success: TRUE
1017 * Failure: FALSE
1019 BOOL32 WINAPI GetConsoleCursorInfo32( HANDLE32 hcon,
1020 LPCONSOLE_CURSOR_INFO cinfo )
1022 FIXME(console, "(%x,%p): stub\n", hcon, cinfo);
1023 if (!cinfo) return FALSE;
1024 cinfo->dwSize = 10; /* 10% of character box is cursor. */
1025 cinfo->bVisible = TRUE; /* Cursor is visible. */
1026 return TRUE;
1030 /******************************************************************************
1031 * SetConsoleCursorInfo32 [KERNEL32.626] Sets size and visibility of cursor
1033 * RETURNS
1034 * Success: TRUE
1035 * Failure: FALSE
1037 BOOL32 WINAPI SetConsoleCursorInfo32(
1038 HANDLE32 hcon, /* [in] Handle to console screen buffer */
1039 LPCONSOLE_CURSOR_INFO cinfo) /* [in] Address of cursor information */
1041 FIXME(console, "(%x,%ld,%i): stub\n", hcon,cinfo->dwSize,cinfo->bVisible);
1042 return TRUE;
1046 /******************************************************************************
1047 * SetConsoleWindowInfo [KERNEL32.634] Sets size and position of console
1049 * RETURNS
1050 * Success: TRUE
1051 * Failure: FALSE
1053 BOOL32 WINAPI SetConsoleWindowInfo(
1054 HANDLE32 hcon, /* [in] Handle to console screen buffer */
1055 BOOL32 bAbsolute, /* [in] Coordinate type flag */
1056 LPSMALL_RECT window) /* [in] Address of new window rectangle */
1058 FIXME(console, "(%x,%d,%p): stub\n", hcon, bAbsolute, window);
1059 return TRUE;
1063 /******************************************************************************
1064 * SetConsoleTextAttribute32 [KERNEL32.631] Sets colors for text
1066 * Sets the foreground and background color attributes of characters
1067 * written to the screen buffer.
1069 * RETURNS
1070 * Success: TRUE
1071 * Failure: FALSE
1073 BOOL32 WINAPI SetConsoleTextAttribute32(HANDLE32 hConsoleOutput,WORD wAttr)
1075 int forecolor = 0;
1076 int backcolor = 0;
1077 int boldtext = 0;
1078 unsigned int attrib;
1080 attrib = wAttr;
1081 if( attrib >= BACKGROUND_INTENSITY )
1082 attrib -= BACKGROUND_INTENSITY; /* Background intensity is ignored */
1083 if( attrib >= BACKGROUND_RED )
1085 attrib -= BACKGROUND_RED;
1086 if( attrib >= BACKGROUND_GREEN )
1088 attrib -= BACKGROUND_GREEN;
1089 if( attrib >= BACKGROUND_BLUE )
1091 attrib -= BACKGROUND_BLUE;
1092 backcolor = 47; /* White background */
1094 else
1095 backcolor = 43; /* Yellow background */
1097 else if( attrib >= BACKGROUND_BLUE )
1099 attrib -= BACKGROUND_BLUE;
1100 backcolor = 45; /* Magenta background */
1102 else
1103 backcolor = 41; /* Red Background */
1105 else if( attrib >= BACKGROUND_GREEN )
1107 attrib -= BACKGROUND_GREEN;
1108 if( attrib >= BACKGROUND_BLUE )
1110 attrib -= BACKGROUND_BLUE;
1111 backcolor = 46; /* Cyan background */
1113 else
1114 backcolor = 42; /* Green background */
1116 else if( attrib >= BACKGROUND_BLUE )
1118 attrib -= BACKGROUND_BLUE;
1119 backcolor = 44; /* Blue background */
1121 else
1122 backcolor = 40; /* Black background */
1123 if( attrib >= FOREGROUND_INTENSITY )
1125 attrib -= FOREGROUND_INTENSITY;
1126 boldtext = 1; /* Bold attribute is on */
1128 if( attrib >= FOREGROUND_RED )
1130 attrib -= FOREGROUND_RED;
1131 if( attrib >= FOREGROUND_GREEN )
1133 attrib -= FOREGROUND_GREEN;
1134 if( attrib >= FOREGROUND_BLUE )
1136 attrib -= FOREGROUND_BLUE;
1137 forecolor = 37; /* White foreground */
1139 else
1140 forecolor = 33; /* Yellow foreground */
1142 else if( attrib >= FOREGROUND_BLUE )
1144 attrib -= FOREGROUND_BLUE;
1145 forecolor = 35; /* Magenta foreground */
1147 else
1148 forecolor = 31; /* Red foreground */
1150 else if( attrib >= FOREGROUND_GREEN )
1152 attrib -= FOREGROUND_GREEN;
1153 if( attrib >= FOREGROUND_BLUE )
1155 attrib -= FOREGROUND_BLUE;
1156 forecolor = 36; /* Cyan foreground */
1158 else
1159 forecolor = 32; /* Green foreground */
1161 else if( attrib >= FOREGROUND_BLUE )
1163 attrib -= FOREGROUND_BLUE;
1164 forecolor = 34; /* Blue foreground */
1166 else
1167 forecolor = 30; /* Black foreground */
1169 fprintf(stdout,"%c[%d;%d;%dm",0x1B,boldtext,forecolor,backcolor);
1170 return TRUE;
1174 /******************************************************************************
1175 * SetConsoleScreenBufferSize [KERNEL32.630] Changes size of console
1177 * PARAMS
1178 * hConsoleOutput [I] Handle to console screen buffer
1179 * dwSize [I] New size in character rows and cols
1181 * RETURNS
1182 * Success: TRUE
1183 * Failure: FALSE
1185 BOOL32 WINAPI SetConsoleScreenBufferSize( HANDLE32 hConsoleOutput,
1186 COORD dwSize )
1188 FIXME(console, "(%d,%dx%d): stub\n",hConsoleOutput,dwSize.x,dwSize.y);
1189 return TRUE;
1193 /******************************************************************************
1194 * FillConsoleOutputCharacterA [KERNEL32.242]
1196 * PARAMS
1197 * hConsoleOutput [I] Handle to screen buffer
1198 * cCharacter [I] Character to write
1199 * nLength [I] Number of cells to write to
1200 * dwCoord [I] Coords of first cell
1201 * lpNumCharsWritten [O] Pointer to number of cells written
1203 * RETURNS
1204 * Success: TRUE
1205 * Failure: FALSE
1207 BOOL32 WINAPI FillConsoleOutputCharacterA(
1208 HANDLE32 hConsoleOutput,
1209 BYTE cCharacter,
1210 DWORD nLength,
1211 COORD dwCoord,
1212 LPDWORD lpNumCharsWritten)
1214 long count;
1215 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1216 for(count=0;count<nLength;count++)
1217 putc(cCharacter,stdout);
1218 *lpNumCharsWritten = nLength;
1219 return TRUE;
1223 /******************************************************************************
1224 * FillConsoleOutputCharacterW [KERNEL32.243] Writes characters to console
1226 * PARAMS
1227 * hConsoleOutput [I] Handle to screen buffer
1228 * cCharacter [I] Character to write
1229 * nLength [I] Number of cells to write to
1230 * dwCoord [I] Coords of first cell
1231 * lpNumCharsWritten [O] Pointer to number of cells written
1233 * RETURNS
1234 * Success: TRUE
1235 * Failure: FALSE
1237 BOOL32 WINAPI FillConsoleOutputCharacterW(HANDLE32 hConsoleOutput,
1238 WCHAR cCharacter,
1239 DWORD nLength,
1240 COORD dwCoord,
1241 LPDWORD lpNumCharsWritten)
1243 long count;
1244 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1245 for(count=0;count<nLength;count++)
1246 putc(cCharacter,stdout);
1247 *lpNumCharsWritten = nLength;
1248 return TRUE;
1252 /******************************************************************************
1253 * FillConsoleOutputAttribute [KERNEL32.241] Sets attributes for console
1255 * PARAMS
1256 * hConsoleOutput [I] Handle to screen buffer
1257 * wAttribute [I] Color attribute to write
1258 * nLength [I] Number of cells to write to
1259 * dwCoord [I] Coords of first cell
1260 * lpNumAttrsWritten [O] Pointer to number of cells written
1262 * RETURNS
1263 * Success: TRUE
1264 * Failure: FALSE
1266 BOOL32 WINAPI FillConsoleOutputAttribute( HANDLE32 hConsoleOutput,
1267 WORD wAttribute, DWORD nLength, COORD dwCoord,
1268 LPDWORD lpNumAttrsWritten)
1270 FIXME(console, "(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1271 wAttribute,nLength,dwCoord.x,dwCoord.y,lpNumAttrsWritten);
1272 *lpNumAttrsWritten = nLength;
1273 return TRUE;
1276 /******************************************************************************
1277 * ReadConsoleOutputCharacter32A [KERNEL32.573]
1279 * BUGS
1280 * Unimplemented
1282 BOOL32 WINAPI ReadConsoleOutputCharacter32A(HANDLE32 hConsoleOutput,
1283 LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1285 FIXME(console, "(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1286 dword,coord.x,coord.y,lpdword);
1287 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1288 return FALSE;
1292 /******************************************************************************
1293 * ScrollConsoleScreenBuffer [KERNEL32.612]
1295 * BUGS
1296 * Unimplemented
1298 BOOL32 WINAPI ScrollConsoleScreenBuffer( HANDLE32 hConsoleOutput,
1299 LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1300 COORD dwDestOrigin, LPCHAR_INFO lpFill)
1302 FIXME(console, "(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1303 lpClipRect,dwDestOrigin.x,dwDestOrigin.y,lpFill);
1304 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1305 return FALSE;