Small fixes.
[wine/multimedia.git] / win32 / console.c
blob48aba956220f28963889fc9bff92c6309eab3c12
1 /*
2 * Win32 kernel functions
4 * Copyright 1995 Martin von Loewis and Cameron Heide
5 * Copyright 1997 Karl Garrison
6 * Copyright 1998 John Richardson
7 * Copyright 1998 Marcus Meissner
8 */
10 /* FIXME:
11 * - Completely lacks SCREENBUFFER interface.
12 * - No abstraction for something other than xterm.
13 * - Key input translation shouldn't use VkKeyScan and MapVirtualKey, since
14 * they are window (USER) driver dependend.
15 * - Output sometimes is buffered (We switched off buffering by ~ICANON ?)
17 /* Reference applications:
18 * - IDA (interactive disassembler) full version 3.75. Works.
19 * - LYNX/W32. Works mostly, some keys crash it.
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <termios.h>
25 #include <strings.h>
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <sys/errno.h>
33 #include <signal.h>
34 #include <assert.h>
36 #include "windows.h"
37 #include "k32obj.h"
38 #include "thread.h"
39 #include "async.h"
40 #include "file.h"
41 #include "process.h"
42 #include "winerror.h"
43 #include "wincon.h"
44 #include "heap.h"
45 #include "debug.h"
47 /* The CONSOLE kernel32 Object */
48 typedef struct _CONSOLE {
49 K32OBJ header;
50 DWORD mode;
51 CONSOLE_CURSOR_INFO cinfo;
53 int master; /* xterm side of pty */
54 int infd,outfd;
55 int pid; /* xterm's pid, -1 if no xterm */
56 LPSTR title; /* title of console */
57 INPUT_RECORD *irs; /* buffered input records */
58 int nrofirs;/* nr of buffered input records */
59 THREAD_QUEUE wait_queue;
60 } CONSOLE;
62 static void CONSOLE_AddWait(K32OBJ *ptr, DWORD thread_id);
63 static void CONSOLE_RemoveWait(K32OBJ *ptr, DWORD thread_id);
64 static BOOL32 CONSOLE_Satisfied(K32OBJ *ptr, DWORD thread_id);
65 static BOOL32 CONSOLE_Signaled(K32OBJ *ptr, DWORD thread_id);
66 static void CONSOLE_Destroy( K32OBJ *obj );
67 static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer,
68 DWORD nNumberOfChars, LPDWORD lpNumberOfChars,
69 LPOVERLAPPED lpOverlapped);
70 static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer,
71 DWORD nNumberOfChars, LPDWORD lpNumberOfChars,
72 LPOVERLAPPED lpOverlapped);
74 const K32OBJ_OPS CONSOLE_Ops =
76 CONSOLE_Signaled, /* signaled */
77 CONSOLE_Satisfied, /* satisfied */
78 CONSOLE_AddWait, /* add_wait */
79 CONSOLE_RemoveWait, /* remove_wait */
80 CONSOLE_Read, /* read */
81 CONSOLE_Write, /* write */
82 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 /* if there is a xterm, kill it. */
99 if (console->pid != -1)
100 kill(console->pid, SIGTERM);
101 HeapFree(SystemHeap, 0, console);
105 /***********************************************************************
106 * CONSOLE_Read
108 * NOTES
109 * lpOverlapped is ignored
111 static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
112 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
114 CONSOLE *console = (CONSOLE *)ptr;
115 int result;
117 TRACE(console, "%p %p %ld\n", ptr, lpBuffer, nNumberOfChars);
118 *lpNumberOfChars = 0;
119 if ((result = read(console->infd, lpBuffer, nNumberOfChars)) == -1) {
120 FILE_SetDosError();
121 return FALSE;
123 *lpNumberOfChars = result;
124 return TRUE;
128 /***********************************************************************
129 * CONSOLE_Write
131 * NOTES
132 * lpOverlapped is ignored
134 static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer,
135 DWORD nNumberOfChars,
136 LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
138 CONSOLE *console = (CONSOLE *)ptr;
139 int result;
141 TRACE(console, "%p %p %ld\n", ptr, lpBuffer, nNumberOfChars);
142 *lpNumberOfChars = 0;
144 * I assume this loop around EAGAIN is here because
145 * win32 doesn't have interrupted system calls
148 for (;;)
150 result = write(console->outfd, lpBuffer, nNumberOfChars);
151 if (result != -1) {
152 *lpNumberOfChars = result;
153 return TRUE;
155 if (errno != EINTR) {
156 FILE_SetDosError();
157 return FALSE;
162 /****************************************************************************
163 * CONSOLE_add_input_record [internal]
165 * Adds an INPUT_RECORD to the CONSOLEs input queue.
167 static void
168 CONSOLE_add_input_record(CONSOLE *console,INPUT_RECORD *inp) {
169 console->irs = HeapReAlloc(GetProcessHeap(),0,console->irs,sizeof(INPUT_RECORD)*(console->nrofirs+1));
170 console->irs[console->nrofirs++]=*inp;
173 /****************************************************************************
174 * XTERM_string_to_IR [internal]
176 * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the
177 * queue. Does translation of vt100 style function keys and xterm-mouse clicks.
179 static void
180 CONSOLE_string_to_IR(CONSOLE *console,unsigned char *buf,int len) {
181 int j,k;
182 INPUT_RECORD ir;
184 for (j=0;j<len;j++) {
185 unsigned char inchar = buf[j];
187 if (inchar!=27) { /* no escape -> 'normal' keyboard event */
188 ir.EventType = 1; /* Key_event */
190 ir.Event.KeyEvent.bKeyDown = 1;
191 ir.Event.KeyEvent.wRepeatCount = 0;
193 ir.Event.KeyEvent.dwControlKeyState = 0;
194 if (inchar & 0x80) {
195 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
196 inchar &= ~0x80;
198 ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(inchar);
199 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100)
200 ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED;
201 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200)
202 ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED;
203 if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400)
204 ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
205 ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
206 ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff,
207 0 /* VirtualKeyCodes to ScanCode */
209 if (inchar=='\n') {
210 ir.Event.KeyEvent.uChar.AsciiChar = '\r';
211 ir.Event.KeyEvent.wVirtualKeyCode = 0x0d;
212 ir.Event.KeyEvent.wVirtualScanCode = 0x1c;
213 } else {
214 ir.Event.KeyEvent.uChar.AsciiChar = inchar;
215 if (inchar<' ') {
216 /* FIXME: find good values for ^X */
217 ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;
218 ir.Event.KeyEvent.wVirtualScanCode = 0xbeef;
222 CONSOLE_add_input_record(console,&ir);
223 ir.Event.KeyEvent.bKeyDown = 0;
224 CONSOLE_add_input_record(console,&ir);
225 continue;
227 /* inchar is ESC */
228 if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */
229 ir.EventType = 1; /* Key_event */
230 ir.Event.KeyEvent.bKeyDown = 1;
231 ir.Event.KeyEvent.wRepeatCount = 0;
233 ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(27);
234 ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16(
235 ir.Event.KeyEvent.wVirtualKeyCode,0
237 ir.Event.KeyEvent.dwControlKeyState = 0;
238 ir.Event.KeyEvent.uChar.AsciiChar = 27;
239 CONSOLE_add_input_record(console,&ir);
240 ir.Event.KeyEvent.bKeyDown = 0;
241 CONSOLE_add_input_record(console,&ir);
242 continue;
244 for (k=j;k<len;k++) {
245 if (((buf[k]>='A') && (buf[k]<='Z')) ||
246 ((buf[k]>='a') && (buf[k]<='z')) ||
247 (buf[k]=='~')
249 break;
251 if (k<len) {
252 int subid,scancode=0;
254 ir.EventType = 1; /* Key_event */
255 ir.Event.KeyEvent.bKeyDown = 1;
256 ir.Event.KeyEvent.wRepeatCount = 0;
257 ir.Event.KeyEvent.dwControlKeyState = 0;
259 ir.Event.KeyEvent.wVirtualKeyCode = 0xad; /* FIXME */
260 ir.Event.KeyEvent.wVirtualScanCode = 0xad; /* FIXME */
261 ir.Event.KeyEvent.uChar.AsciiChar = 0;
263 switch (buf[k]) {
264 case '~':
265 sscanf(&buf[j+2],"%d",&subid);
266 switch (subid) {
267 case 2:/*INS */scancode = 0xe052;break;
268 case 3:/*DEL */scancode = 0xe053;break;
269 case 6:/*PGDW*/scancode = 0xe051;break;
270 case 5:/*PGUP*/scancode = 0xe049;break;
271 case 11:/*F1 */scancode = 0x003b;break;
272 case 12:/*F2 */scancode = 0x003c;break;
273 case 13:/*F3 */scancode = 0x003d;break;
274 case 14:/*F4 */scancode = 0x003e;break;
275 case 15:/*F5 */scancode = 0x003f;break;
276 case 17:/*F6 */scancode = 0x0040;break;
277 case 18:/*F7 */scancode = 0x0041;break;
278 case 19:/*F8 */scancode = 0x0042;break;
279 case 20:/*F9 */scancode = 0x0043;break;
280 case 21:/*F10 */scancode = 0x0044;break;
281 case 23:/*F11 */scancode = 0x00d9;break;
282 case 24:/*F12 */scancode = 0x00da;break;
283 /* FIXME: Shift-Fx */
284 default:
285 FIXME(console,"parse ESC[%d~\n",subid);
286 break;
288 break;
289 case 'A': /* Cursor Up */scancode = 0xe048;break;
290 case 'B': /* Cursor Down */scancode = 0xe050;break;
291 case 'D': /* Cursor Left */scancode = 0xe04b;break;
292 case 'C': /* Cursor Right */scancode = 0xe04d;break;
293 case 'F': /* End */scancode = 0xe04f;break;
294 case 'H': /* Home */scancode = 0xe047;break;
295 case 'M':
296 /* Mouse Button Press (ESCM<button+'!'><x+'!'><y+'!'>) or
297 * Release (ESCM#<x+'!'><y+'!'>
299 if (k<len-3) {
300 ir.EventType = MOUSE_EVENT;
301 ir.Event.MouseEvent.dwMousePosition.x = buf[k+2]-'!';
302 ir.Event.MouseEvent.dwMousePosition.y = buf[k+3]-'!';
303 if (buf[k+1]=='#')
304 ir.Event.MouseEvent.dwButtonState = 0;
305 else
306 ir.Event.MouseEvent.dwButtonState = 1<<(buf[k+1]-' ');
307 ir.Event.MouseEvent.dwEventFlags = 0; /* FIXME */
308 CONSOLE_add_input_record(console,&ir);
309 j=k+3;
311 break;
314 if (scancode) {
315 ir.Event.KeyEvent.wVirtualScanCode = scancode;
316 ir.Event.KeyEvent.wVirtualKeyCode = MapVirtualKey16(scancode,1);
317 CONSOLE_add_input_record(console,&ir);
318 ir.Event.KeyEvent.bKeyDown = 0;
319 CONSOLE_add_input_record(console,&ir);
320 j=k;
321 continue;
326 /****************************************************************************
327 * CONSOLE_get_input (internal)
329 * Reads (nonblocking) as much input events as possible and stores them
330 * in an internal queue.
331 * (not necessarily XTERM dependend, but UNIX filedescriptor...)
333 static void
334 CONSOLE_get_input(CONSOLE *console) {
335 char *buf = HeapAlloc(GetProcessHeap(),0,1);
336 int len = 0;
338 while (1) {
339 fd_set infds;
340 DWORD res;
341 struct timeval tv;
342 char inchar;
344 FD_ZERO(&infds);
345 FD_SET(console->infd,&infds);
346 memset(&tv,0,sizeof(tv));
347 if (select(console->infd+1,&infds,NULL,NULL,&tv)<1)
348 break; /* no input there */
350 if (!FD_ISSET(console->infd,&infds))
351 break;
352 if (!CONSOLE_Read((K32OBJ*)console,&inchar,1,&res,NULL))
353 break;
354 buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1);
355 buf[len++]=inchar;
357 CONSOLE_string_to_IR(console,buf,len);
358 HeapFree(GetProcessHeap(),0,buf);
361 /****************************************************************************
362 * CONSOLE_drain_input (internal)
364 * Drains 'n' console input events from the queue.
366 static void
367 CONSOLE_drain_input(CONSOLE *console,int n) {
368 assert(n<=console->nrofirs);
369 if (n) {
370 console->nrofirs-=n;
371 memcpy( &console->irs[0],
372 &console->irs[n],
373 console->nrofirs*sizeof(INPUT_RECORD)
375 console->irs = HeapReAlloc(
376 GetProcessHeap(),
378 console->irs,
379 console->nrofirs*sizeof(INPUT_RECORD)
384 /***********************************************************************
385 * CONSOLE_async_handler [internal]
387 static void
388 CONSOLE_async_handler(int unixfd,void *private) {
389 CONSOLE *console = (CONSOLE*)private;
391 SYNC_WakeUp(&console->wait_queue,INFINITE32);
394 /***********************************************************************
395 * CONSOLE_Signaled [internal]
397 * Checks if we can read something. (Hmm, what about writing ?)
399 static BOOL32
400 CONSOLE_Signaled(K32OBJ *ptr,DWORD tid) {
401 CONSOLE *console =(CONSOLE*)ptr;
403 if (ptr->type!= K32OBJ_CONSOLE)
404 return FALSE;
405 CONSOLE_get_input(console);
406 if (console->nrofirs!=0)
407 return TRUE;
408 /* addref console */
409 return FALSE;
412 /***********************************************************************
413 * CONSOLE_AddWait [internal]
415 * Add thread to our waitqueue (so we can signal it if we have input).
417 static void CONSOLE_AddWait(K32OBJ *ptr, DWORD thread_id)
419 CONSOLE *console = (CONSOLE *)ptr;
421 /* register our unix filedescriptors for async IO */
422 if (!console->wait_queue)
423 ASYNC_RegisterFD(console->infd,CONSOLE_async_handler,console);
424 THREAD_AddQueue( &console->wait_queue, THREAD_ID_TO_THDB(thread_id) );
427 /***********************************************************************
428 * CONSOLE_RemoveWait [internal]
430 * Remove thread from our waitqueue.
432 static void CONSOLE_RemoveWait(K32OBJ *ptr, DWORD thread_id)
434 CONSOLE *console = (CONSOLE *)ptr;
436 THREAD_RemoveQueue( &console->wait_queue, THREAD_ID_TO_THDB(thread_id) );
437 if (!console->wait_queue)
438 ASYNC_UnregisterFD(console->infd,CONSOLE_async_handler);
441 /***********************************************************************
442 * CONSOLE_Satisfied [internal]
444 * Condition from last Signaled is satisfied and will be used now.
446 static BOOL32 CONSOLE_Satisfied(K32OBJ *ptr, DWORD thread_id)
448 return FALSE;
452 /******************************************************************************
453 * SetConsoleCtrlHandler [KERNEL32.459] Adds function to calling process list
455 * PARAMS
456 * func [I] Address of handler function
457 * add [I] Handler to add or remove
459 * RETURNS
460 * Success: TRUE
461 * Failure: FALSE
463 * CHANGED
464 * James Sutherland (JamesSutherland@gmx.de)
465 * Added global variables console_ignore_ctrl_c and handlers[]
466 * Does not yet do any error checking, or set LastError if failed.
467 * This doesn't yet matter, since these handlers are not yet called...!
469 static unsigned int console_ignore_ctrl_c = 0;
470 static HANDLER_ROUTINE *handlers[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
471 BOOL32 WINAPI SetConsoleCtrlHandler( HANDLER_ROUTINE *func, BOOL32 add )
473 unsigned int alloc_loop = sizeof(handlers)/sizeof(HANDLER_ROUTINE *);
474 unsigned int done = 0;
475 FIXME(console, "(%p,%i) - no error checking or testing yet\n", func, add);
476 if (!func)
478 console_ignore_ctrl_c = add;
479 return TRUE;
481 if (add)
483 for (;alloc_loop--;)
484 if (!handlers[alloc_loop] && !done)
486 handlers[alloc_loop] = func;
487 done++;
489 if (!done)
490 FIXME(console, "Out of space on CtrlHandler table\n");
491 return(done);
493 else
495 for (;alloc_loop--;)
496 if (handlers[alloc_loop] == func && !done)
498 handlers[alloc_loop] = 0;
499 done++;
501 if (!done)
502 WARN(console, "Attempt to remove non-installed CtrlHandler %p\n",
503 func);
504 return (done);
506 return (done);
510 /******************************************************************************
511 * GenerateConsoleCtrlEvent [KERNEL32.275] Simulate a CTRL-C or CTRL-BREAK
513 * PARAMS
514 * dwCtrlEvent [I] Type of event
515 * dwProcessGroupID [I] Process group ID to send event to
517 * NOTES
518 * Doesn't yet work...!
520 * RETURNS
521 * Success: True
522 * Failure: False (and *should* [but doesn't] set LastError)
524 BOOL32 WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent,
525 DWORD dwProcessGroupID )
527 if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
529 ERR( console, "invalid event %d for PGID %ld\n",
530 (unsigned short)dwCtrlEvent, dwProcessGroupID );
531 return FALSE;
533 if (dwProcessGroupID == GetCurrentProcessId() )
535 FIXME( console, "Attempt to send event %d to self - stub\n",
536 (unsigned short)dwCtrlEvent );
537 return FALSE;
539 FIXME( console,"event %d to external PGID %ld - not implemented yet\n",
540 (unsigned short)dwCtrlEvent, dwProcessGroupID );
541 return FALSE;
545 /******************************************************************************
546 * CreateConsoleScreenBuffer [KERNEL32.151] Creates a console screen buffer
548 * PARAMS
549 * dwDesiredAccess [I] Access flag
550 * dwShareMode [I] Buffer share mode
551 * sa [I] Security attributes
552 * dwFlags [I] Type of buffer to create
553 * lpScreenBufferData [I] Reserved
555 * NOTES
556 * Should call SetLastError
558 * RETURNS
559 * Success: Handle to new console screen buffer
560 * Failure: INVALID_HANDLE_VALUE
562 HANDLE32 WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
563 DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa,
564 DWORD dwFlags, LPVOID lpScreenBufferData )
566 FIXME(console, "(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess,
567 dwShareMode, sa, dwFlags, lpScreenBufferData);
568 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
569 return INVALID_HANDLE_VALUE32;
573 /***********************************************************************
574 * GetConsoleScreenBufferInfo (KERNEL32.190)
576 BOOL32 WINAPI GetConsoleScreenBufferInfo( HANDLE32 hConsoleOutput,
577 LPCONSOLE_SCREEN_BUFFER_INFO csbi )
579 csbi->dwSize.x = 80;
580 csbi->dwSize.y = 24;
581 csbi->dwCursorPosition.x = 0;
582 csbi->dwCursorPosition.y = 0;
583 csbi->wAttributes = 0;
584 csbi->srWindow.Left = 0;
585 csbi->srWindow.Right = 79;
586 csbi->srWindow.Top = 0;
587 csbi->srWindow.Bottom = 23;
588 csbi->dwMaximumWindowSize.x = 80;
589 csbi->dwMaximumWindowSize.y = 24;
590 return TRUE;
594 /******************************************************************************
595 * SetConsoleActiveScreenBuffer [KERNEL32.623] Sets buffer to current console
597 * RETURNS
598 * Success: TRUE
599 * Failure: FALSE
601 BOOL32 WINAPI SetConsoleActiveScreenBuffer(
602 HANDLE32 hConsoleOutput) /* [in] Handle to console screen buffer */
604 FIXME(console, "(%x): stub\n", hConsoleOutput);
605 return FALSE;
609 /***********************************************************************
610 * GetLargestConsoleWindowSize (KERNEL32.226)
612 DWORD WINAPI GetLargestConsoleWindowSize( HANDLE32 hConsoleOutput )
614 return (DWORD)MAKELONG(80,24);
617 /***********************************************************************
618 * FreeConsole (KERNEL32.267)
620 BOOL32 WINAPI FreeConsole(VOID)
623 PDB32 *pdb = PROCESS_Current();
624 CONSOLE *console;
626 SYSTEM_LOCK();
628 console = (CONSOLE *)pdb->console;
630 if (console == NULL) {
631 SetLastError(ERROR_INVALID_PARAMETER);
632 return FALSE;
635 HANDLE_CloseAll( pdb, &console->header );
637 K32OBJ_DecCount( &console->header );
638 pdb->console = NULL;
639 SYSTEM_UNLOCK();
640 return TRUE;
644 /**
645 * It looks like the openpty that comes with glibc in RedHat 5.0
646 * is buggy (second call returns what looks like a dup of 0 and 1
647 * instead of a new pty), this is a generic replacement.
649 static int CONSOLE_openpty(CONSOLE *console, char *name,
650 struct termios *term, struct winsize *winsize)
652 int fdm, fds;
653 char *ptr1, *ptr2;
654 char pts_name[512];
656 strcpy (pts_name, "/dev/ptyXY");
658 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
659 pts_name[8] = *ptr1;
660 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
661 pts_name[9] = *ptr2;
663 if ((fdm = open(pts_name, O_RDWR)) < 0) {
664 if (errno == ENOENT)
665 return -1;
666 else
667 continue;
669 pts_name[5] = 't';
670 if ((fds = open(pts_name, O_RDWR)) < 0) {
671 pts_name[5] = 'p';
672 continue;
674 console->master = fdm;
675 console->infd = console->outfd = fds;
677 if (term != NULL)
678 tcsetattr(console->infd, TCSANOW, term);
679 if (winsize != NULL)
680 ioctl(console->outfd, TIOCSWINSZ, winsize);
681 if (name != NULL)
682 strcpy(name, pts_name);
683 return fds;
686 return -1;
689 /*************************************************************************
690 * CONSOLE_make_complex [internal]
692 * Turns a CONSOLE kernel object into a complex one.
693 * (switches from output/input using the terminal where WINE was started to
694 * its own xterm).
696 * This makes simple commandline tools pipeable, while complex commandline
697 * tools work without getting messed up by debugoutput.
699 * All other functions should work indedependend from this call.
701 * To test for complex console: pid == -1 -> simple, otherwise complex.
703 static BOOL32 CONSOLE_make_complex(CONSOLE *console)
705 struct termios term;
706 char buf[30];
707 char c = '\0';
708 int status = 0;
709 int i,xpid;
710 DWORD xlen;
712 if (console->pid != -1)
713 return TRUE; /* already complex */
715 MSG("Console: Making console complex (creating an xterm)...\n");
717 if (tcgetattr(0, &term) < 0) return FALSE;
718 term.c_lflag = ~(ECHO|ICANON);
719 if (CONSOLE_openpty(console, NULL, &term, NULL) < 0) return FALSE;
721 if ((xpid=fork()) == 0) {
722 tcsetattr(console->infd, TCSADRAIN, &term);
723 sprintf(buf, "-Sxx%d", console->master);
724 /* "-fn vga" for VGA font. Harmless if vga is not present:
725 * xterm: unable to open font "vga", trying "fixed"....
727 execlp("xterm", "xterm", buf, "-fn","vga",NULL);
728 ERR(console, "error creating AllocConsole xterm\n");
729 exit(1);
731 console->pid = xpid;
733 /* most xterms like to print their window ID when used with -S;
734 * read it and continue before the user has a chance...
736 for (i=0; c!='\n'; (status=read(console->infd, &c, 1)), i++) {
737 if (status == -1 && c == '\0') {
738 /* wait for xterm to be created */
739 usleep(100);
741 if (i > 10000) {
742 ERR(console, "can't read xterm WID\n");
743 kill(console->pid, SIGKILL);
744 return FALSE;
747 /* enable mouseclicks */
748 sprintf(buf,"%c[?1001s%c[?1000h",27,27);
749 CONSOLE_Write(&console->header,buf,strlen(buf),&xlen,NULL);
750 return TRUE;
754 /***********************************************************************
755 * CONSOLE_GetConsoleHandle
756 * returns a 16-bit style console handle
757 * note: only called from _lopen
759 HFILE32 CONSOLE_GetConsoleHandle(VOID)
761 PDB32 *pdb = PROCESS_Current();
762 HFILE32 handle = HFILE_ERROR32;
764 SYSTEM_LOCK();
765 if (pdb->console != NULL) {
766 CONSOLE *console = (CONSOLE *)pdb->console;
767 handle = (HFILE32)HANDLE_Alloc(pdb, &console->header, 0, TRUE, -1);
769 SYSTEM_UNLOCK();
770 return handle;
773 /***********************************************************************
774 * AllocConsole (KERNEL32.103)
776 * creates an xterm with a pty to our program
778 BOOL32 WINAPI AllocConsole(VOID)
781 PDB32 *pdb = PROCESS_Current();
782 CONSOLE *console;
783 HANDLE32 hIn, hOut, hErr;
785 SYSTEM_LOCK(); /* FIXME: really only need to lock the process */
787 SetLastError(ERROR_CANNOT_MAKE); /* this might not be the right
788 error, but it's a good guess :) */
790 console = (CONSOLE *)pdb->console;
792 /* don't create a console if we already have one */
793 if (console != NULL) {
794 SetLastError(ERROR_ACCESS_DENIED);
795 SYSTEM_UNLOCK();
796 return FALSE;
799 if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console))))
801 SYSTEM_UNLOCK();
802 return FALSE;
805 console->header.type = K32OBJ_CONSOLE;
806 console->header.refcount = 1;
807 console->pid = -1;
808 console->title = NULL;
809 console->nrofirs = 0;
810 console->wait_queue = NULL;
811 console->irs = HeapAlloc(GetProcessHeap(),0,1);;
812 console->mode = ENABLE_PROCESSED_INPUT
813 | ENABLE_LINE_INPUT
814 | ENABLE_ECHO_INPUT;
815 /* FIXME: we shouldn't probably use hardcoded UNIX values here. */
816 console->infd = 0;
817 console->outfd = 1;
819 if ((hIn = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
821 K32OBJ_DecCount(&console->header);
822 SYSTEM_UNLOCK();
823 return FALSE;
826 if ((hOut = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
828 CloseHandle(hIn);
829 K32OBJ_DecCount(&console->header);
830 SYSTEM_UNLOCK();
831 return FALSE;
835 if ((hErr = HANDLE_Alloc(pdb,&console->header, 0, TRUE,-1)) == INVALID_HANDLE_VALUE32)
837 CloseHandle(hIn);
838 CloseHandle(hOut);
839 K32OBJ_DecCount(&console->header);
840 SYSTEM_UNLOCK();
841 return FALSE;
844 if (pdb->console) K32OBJ_DecCount( pdb->console );
845 pdb->console = (K32OBJ *)console;
846 K32OBJ_IncCount( pdb->console );
848 /* NT resets the STD_*_HANDLEs on console alloc */
849 SetStdHandle(STD_INPUT_HANDLE, hIn);
850 SetStdHandle(STD_OUTPUT_HANDLE, hOut);
851 SetStdHandle(STD_ERROR_HANDLE, hErr);
853 SetLastError(ERROR_SUCCESS);
854 SYSTEM_UNLOCK();
855 SetConsoleTitle32A("Wine Console");
856 return TRUE;
860 /******************************************************************************
861 * GetConsoleCP [KERNEL32.295] Returns the OEM code page for the console
863 * RETURNS
864 * Code page code
866 UINT32 WINAPI GetConsoleCP(VOID)
868 return GetACP();
872 /***********************************************************************
873 * GetConsoleOutputCP (KERNEL32.189)
875 UINT32 WINAPI GetConsoleOutputCP(VOID)
877 return GetConsoleCP();
880 /***********************************************************************
881 * GetConsoleMode (KERNEL32.188)
883 BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode)
885 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
887 if (!console) {
888 FIXME(console,"(%d,%p), no console handle passed!\n",hcon,mode);
889 return FALSE;
891 *mode = console->mode;
892 K32OBJ_DecCount(&console->header);
893 return TRUE;
897 /******************************************************************************
898 * SetConsoleMode [KERNEL32.628] Sets input mode of console's input buffer
900 * PARAMS
901 * hcon [I] Handle to console input or screen buffer
902 * mode [I] Input or output mode to set
904 * RETURNS
905 * Success: TRUE
906 * Failure: FALSE
908 BOOL32 WINAPI SetConsoleMode( HANDLE32 hcon, DWORD mode )
910 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
912 if (!console) {
913 FIXME(console,"(%d,%ld), no console handle passed!\n",hcon,mode);
914 return FALSE;
916 FIXME(console,"(0x%08x,0x%08lx): stub\n",hcon,mode);
917 console->mode = mode;
918 K32OBJ_DecCount(&console->header);
919 return TRUE;
923 /***********************************************************************
924 * GetConsoleTitleA (KERNEL32.191)
926 DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size)
928 PDB32 *pdb = PROCESS_Current();
929 CONSOLE *console= (CONSOLE *)pdb->console;
931 if(console && console->title) {
932 lstrcpyn32A(title,console->title,size);
933 return strlen(title);
935 return 0;
939 /******************************************************************************
940 * GetConsoleTitle32W [KERNEL32.192] Retrieves title string for console
942 * PARAMS
943 * title [O] Address of buffer for title
944 * size [I] Size of buffer
946 * RETURNS
947 * Success: Length of string copied
948 * Failure: 0
950 DWORD WINAPI GetConsoleTitle32W( LPWSTR title, DWORD size )
952 PDB32 *pdb = PROCESS_Current();
953 CONSOLE *console= (CONSOLE *)pdb->console;
954 if(console && console->title)
956 lstrcpynAtoW(title,console->title,size);
957 return (lstrlen32W(title));
959 return 0;
963 /***********************************************************************
964 * WriteConsoleA (KERNEL32.729)
966 BOOL32 WINAPI WriteConsole32A( HANDLE32 hConsoleOutput,
967 LPCVOID lpBuffer,
968 DWORD nNumberOfCharsToWrite,
969 LPDWORD lpNumberOfCharsWritten,
970 LPVOID lpReserved )
972 /* FIXME: should I check if this is a console handle? */
973 return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
974 lpNumberOfCharsWritten, NULL);
978 #define CADD(c) \
979 if (bufused==curbufsize-1) \
980 buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\
981 buffer[bufused++]=c;
982 #define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}}
984 /***********************************************************************
985 * WriteConsoleOutputA (KERNEL32.732)
987 BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
988 LPCHAR_INFO lpBuffer,
989 COORD dwBufferSize,
990 COORD dwBufferCoord,
991 LPSMALL_RECT lpWriteRegion)
993 int i,j,off=0,lastattr=-1;
994 char sbuf[20],*buffer=NULL;
995 int bufused=0,curbufsize = 100;
996 DWORD res;
997 const int colormap[8] = {
998 0,4,2,6,
999 1,5,3,7,
1001 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleOutput, K32OBJ_CONSOLE, 0, NULL);
1003 if (!console) {
1004 FIXME(console,"(%d,...): no console handle!\n",hConsoleOutput);
1005 return FALSE;
1007 CONSOLE_make_complex(console);
1008 buffer = HeapAlloc(GetProcessHeap(),0,100);;
1009 curbufsize = 100;
1011 TRACE(console,"wr: top = %d, bottom=%d, left=%d,right=%d\n",
1012 lpWriteRegion->Top,
1013 lpWriteRegion->Bottom,
1014 lpWriteRegion->Left,
1015 lpWriteRegion->Right
1018 for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) {
1019 sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1);
1020 SADD(sbuf);
1021 for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) {
1022 if (lastattr!=lpBuffer[off].Attributes) {
1023 lastattr = lpBuffer[off].Attributes;
1024 sprintf(sbuf,"%c[0;%s3%d;4%dm",
1026 (lastattr & FOREGROUND_INTENSITY)?"1;":"",
1027 colormap[lastattr&7],
1028 colormap[(lastattr&0x70)>>4]
1030 /* FIXME: BACKGROUND_INTENSITY */
1031 SADD(sbuf);
1033 CADD(lpBuffer[off].Char.AsciiChar);
1034 off++;
1037 sprintf(sbuf,"%c[0m",27);SADD(sbuf);
1038 WriteFile(hConsoleOutput,buffer,bufused,&res,NULL);
1039 HeapFree(GetProcessHeap(),0,buffer);
1040 K32OBJ_DecCount(&console->header);
1041 return TRUE;
1044 /***********************************************************************
1045 * WriteConsoleW (KERNEL32.577)
1047 BOOL32 WINAPI WriteConsole32W( HANDLE32 hConsoleOutput,
1048 LPCVOID lpBuffer,
1049 DWORD nNumberOfCharsToWrite,
1050 LPDWORD lpNumberOfCharsWritten,
1051 LPVOID lpReserved )
1053 BOOL32 ret;
1054 LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite );
1056 lstrcpynWtoA( xstring, lpBuffer,nNumberOfCharsToWrite);
1058 /* FIXME: should I check if this is a console handle? */
1059 ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite,
1060 lpNumberOfCharsWritten, NULL);
1061 HeapFree( GetProcessHeap(), 0, xstring );
1062 return ret;
1066 /***********************************************************************
1067 * ReadConsoleA (KERNEL32.419)
1069 BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput,
1070 LPVOID lpBuffer,
1071 DWORD nNumberOfCharsToRead,
1072 LPDWORD lpNumberOfCharsRead,
1073 LPVOID lpReserved )
1075 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
1076 int i,charsread = 0;
1077 LPSTR xbuf = (LPSTR)lpBuffer;
1079 if (!console) {
1080 SetLastError(ERROR_INVALID_HANDLE);
1081 FIXME(console,"(%d,...), no console handle!\n",hConsoleInput);
1082 return FALSE;
1084 TRACE(console,"(%d,%p,%ld,%p,%p)\n",
1085 hConsoleInput,lpBuffer,nNumberOfCharsToRead,
1086 lpNumberOfCharsRead,lpReserved
1088 CONSOLE_get_input(console);
1090 /* FIXME: should this drain everything from the input queue and just
1091 * put the keypresses in the buffer? Needs further thought.
1093 for (i=0;(i<console->nrofirs)&&(charsread<nNumberOfCharsToRead);i++) {
1094 if (console->irs[i].EventType != KEY_EVENT)
1095 continue;
1096 if (!console->irs[i].Event.KeyEvent.bKeyDown)
1097 continue;
1098 *xbuf++ = console->irs[i].Event.KeyEvent.uChar.AsciiChar;
1099 charsread++;
1101 CONSOLE_drain_input(console,i);
1102 if (lpNumberOfCharsRead)
1103 *lpNumberOfCharsRead = charsread;
1104 K32OBJ_DecCount(&console->header);
1105 return TRUE;
1108 /***********************************************************************
1109 * ReadConsoleW (KERNEL32.427)
1111 BOOL32 WINAPI ReadConsole32W( HANDLE32 hConsoleInput,
1112 LPVOID lpBuffer,
1113 DWORD nNumberOfCharsToRead,
1114 LPDWORD lpNumberOfCharsRead,
1115 LPVOID lpReserved )
1117 BOOL32 ret;
1118 LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead);
1120 ret = ReadConsole32A(
1121 hConsoleInput,
1122 buf,
1123 nNumberOfCharsToRead,
1124 lpNumberOfCharsRead,
1125 lpReserved
1127 if (ret)
1128 lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
1129 HeapFree( GetProcessHeap(), 0, buf );
1130 return ret;
1134 /******************************************************************************
1135 * ReadConsoleInput32A [KERNEL32.569] Reads data from a console
1137 * PARAMS
1138 * hConsoleInput [I] Handle to console input buffer
1139 * lpBuffer [O] Address of buffer for read data
1140 * nLength [I] Number of records to read
1141 * lpNumberOfEventsRead [O] Address of number of records read
1143 * RETURNS
1144 * Success: TRUE
1145 * Failure: FALSE
1147 BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput,
1148 LPINPUT_RECORD lpBuffer,
1149 DWORD nLength, LPDWORD lpNumberOfEventsRead)
1151 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
1153 TRACE(console, "(%d,%p,%ld,%p)\n",hConsoleInput, lpBuffer, nLength,
1154 lpNumberOfEventsRead);
1155 if (!console) {
1156 FIXME(console, "(%d,%p,%ld,%p), No console handle!\n",hConsoleInput,
1157 lpBuffer, nLength, lpNumberOfEventsRead);
1158 return FALSE;
1160 CONSOLE_get_input(console);
1161 if (nLength>console->nrofirs)
1162 nLength = console->nrofirs;
1163 memcpy(lpBuffer,console->irs,sizeof(INPUT_RECORD)*nLength);
1164 if (lpNumberOfEventsRead)
1165 *lpNumberOfEventsRead = nLength;
1166 CONSOLE_drain_input(console,nLength);
1167 K32OBJ_DecCount(&console->header);
1168 return TRUE;
1171 /***********************************************************************
1172 * SetConsoleTitle32A (KERNEL32.476)
1174 * Sets the console title.
1176 * We do not necessarily need to create a complex console for that,
1177 * but should remember the title and set it on creation of the latter.
1178 * (not fixed at this time).
1180 BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
1182 PDB32 *pdb = PROCESS_Current();
1183 CONSOLE *console;
1184 DWORD written;
1185 char titleformat[]="\033]2;%s\a"; /*this should work for xterms*/
1186 LPSTR titlestring;
1187 BOOL32 ret=FALSE;
1189 TRACE(console,"(%s)\n",title);
1191 console = (CONSOLE *)pdb->console;
1192 if (!console)
1193 return FALSE;
1194 if(console->title) /* Free old title, if there is one */
1195 HeapFree( SystemHeap, 0, console->title );
1196 console->title = (LPSTR)HeapAlloc(SystemHeap, 0,strlen(title)+1);
1197 if(console->title) strcpy(console->title,title);
1198 titlestring = HeapAlloc(GetProcessHeap(), 0,strlen(title)+strlen(titleformat)+1);
1199 if (!titlestring) {
1200 K32OBJ_DecCount(&console->header);
1201 return FALSE;
1204 sprintf(titlestring,titleformat,title);
1205 /* FIXME: hmm, should use WriteFile probably... */
1206 CONSOLE_Write(&console->header,titlestring,strlen(titlestring),&written,NULL);
1207 if (written == strlen(titlestring))
1208 ret =TRUE;
1209 HeapFree( GetProcessHeap(), 0, titlestring );
1210 K32OBJ_DecCount(&console->header);
1211 return ret;
1215 /******************************************************************************
1216 * SetConsoleTitle32W [KERNEL32.477] Sets title bar string for console
1218 * PARAMS
1219 * title [I] Address of new title
1221 * NOTES
1222 * This should not be calling the A version
1224 * RETURNS
1225 * Success: TRUE
1226 * Failure: FALSE
1228 BOOL32 WINAPI SetConsoleTitle32W( LPCWSTR title )
1230 BOOL32 ret;
1232 LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1233 ret = SetConsoleTitle32A(titleA);
1234 HeapFree( GetProcessHeap(), 0, titleA );
1235 return ret;
1238 /***********************************************************************
1239 * ReadConsoleInput32W (KERNEL32.570)
1241 BOOL32 WINAPI ReadConsoleInput32W(HANDLE32 hConsoleInput,
1242 LPINPUT_RECORD lpBuffer,
1243 DWORD nLength, LPDWORD lpNumberOfEventsRead)
1245 FIXME(console, "(%d,%p,%ld,%p): stub\n",hConsoleInput, lpBuffer, nLength,
1246 lpNumberOfEventsRead);
1247 return 0;
1250 /***********************************************************************
1251 * FlushConsoleInputBuffer (KERNEL32.132)
1253 BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput)
1255 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
1257 if (!console)
1258 return FALSE;
1259 CONSOLE_drain_input(console,console->nrofirs);
1260 K32OBJ_DecCount(&console->header);
1261 return TRUE;
1265 /******************************************************************************
1266 * SetConsoleCursorPosition [KERNEL32.627]
1267 * Sets the cursor position in console
1269 * PARAMS
1270 * hConsoleOutput [I] Handle of console screen buffer
1271 * dwCursorPosition [I] New cursor position coordinates
1273 * RETURNS STD
1275 BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hcon, COORD pos )
1277 char xbuf[20];
1278 DWORD xlen;
1279 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
1281 if (!console) {
1282 FIXME(console,"(%d,...), no console handle!\n",hcon);
1283 return FALSE;
1285 CONSOLE_make_complex(console);
1286 TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y );
1287 /* x are columns, y rows */
1288 sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1);
1289 /* FIXME: store internal if we start using own console buffers */
1290 WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL);
1291 K32OBJ_DecCount(&console->header);
1292 return TRUE;
1295 /***********************************************************************
1296 * GetNumberOfConsoleInputEvents (KERNEL32.246)
1298 BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents)
1300 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
1302 if (!console) {
1303 FIXME(console,"(%d,%p), no console handle!\n",hcon,nrofevents);
1304 return FALSE;
1306 CONSOLE_get_input(console);
1307 *nrofevents = console->nrofirs;
1308 K32OBJ_DecCount(&console->header);
1309 return TRUE;
1312 /***********************************************************************
1313 * GetNumberOfConsoleMouseButtons (KERNEL32.358)
1315 BOOL32 WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
1317 FIXME(console,"(%p): stub\n", nrofbuttons);
1318 *nrofbuttons = 2;
1319 return TRUE;
1322 /***********************************************************************
1323 * PeekConsoleInputA (KERNEL32.550)
1325 * Gets 'cInRecords' first events (or less) from input queue.
1327 * Does not need a complex console.
1329 BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
1330 LPINPUT_RECORD pirBuffer,
1331 DWORD cInRecords,
1332 LPDWORD lpcRead)
1334 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
1336 if (!console) {
1337 FIXME(console,"(%d,%p,%ld,%p), No console handle passed!\n",hConsoleInput, pirBuffer, cInRecords, lpcRead);
1338 return FALSE;
1340 TRACE(console,"(%d,%p,%ld,%p)\n",hConsoleInput, pirBuffer, cInRecords, lpcRead);
1341 CONSOLE_get_input(console);
1342 if (cInRecords>console->nrofirs)
1343 cInRecords = console->nrofirs;
1344 if (pirBuffer)
1345 memcpy(pirBuffer,console->irs,cInRecords*sizeof(INPUT_RECORD));
1346 if (lpcRead)
1347 *lpcRead = cInRecords;
1348 K32OBJ_DecCount(&console->header);
1349 return TRUE;
1352 /***********************************************************************
1353 * PeekConsoleInputW (KERNEL32.551)
1355 BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
1356 LPINPUT_RECORD pirBuffer,
1357 DWORD cInRecords,
1358 LPDWORD lpcRead)
1360 /* FIXME: Hmm. Fix this if we get UNICODE input. */
1361 return PeekConsoleInput32A(hConsoleInput,pirBuffer,cInRecords,lpcRead);
1365 /******************************************************************************
1366 * GetConsoleCursorInfo32 [KERNEL32.296] Gets size and visibility of console
1368 * PARAMS
1369 * hcon [I] Handle to console screen buffer
1370 * cinfo [O] Address of cursor information
1372 * RETURNS
1373 * Success: TRUE
1374 * Failure: FALSE
1376 BOOL32 WINAPI GetConsoleCursorInfo32( HANDLE32 hcon,
1377 LPCONSOLE_CURSOR_INFO cinfo )
1379 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
1381 if (!console) {
1382 FIXME(console, "(%x,%p), no console handle!\n", hcon, cinfo);
1383 return FALSE;
1385 TRACE(console, "(%x,%p)\n", hcon, cinfo);
1386 if (!cinfo)
1387 return FALSE;
1388 *cinfo = console->cinfo;
1389 K32OBJ_DecCount(&console->header);
1390 return TRUE;
1394 /******************************************************************************
1395 * SetConsoleCursorInfo32 [KERNEL32.626] Sets size and visibility of cursor
1397 * RETURNS
1398 * Success: TRUE
1399 * Failure: FALSE
1401 BOOL32 WINAPI SetConsoleCursorInfo32(
1402 HANDLE32 hcon, /* [in] Handle to console screen buffer */
1403 LPCONSOLE_CURSOR_INFO cinfo) /* [in] Address of cursor information */
1405 char buf[8];
1406 DWORD xlen;
1407 CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
1409 TRACE(console, "(%x,%ld,%i): stub\n", hcon,cinfo->dwSize,cinfo->bVisible);
1410 if (!console)
1411 return FALSE;
1412 CONSOLE_make_complex(console);
1413 sprintf(buf,"%c[?25%c",27,cinfo->bVisible?'h':'l');
1414 WriteFile(hcon,buf,strlen(buf),&xlen,NULL);
1415 console->cinfo = *cinfo;
1416 K32OBJ_DecCount(&console->header);
1417 return TRUE;
1421 /******************************************************************************
1422 * SetConsoleWindowInfo [KERNEL32.634] Sets size and position of console
1424 * RETURNS
1425 * Success: TRUE
1426 * Failure: FALSE
1428 BOOL32 WINAPI SetConsoleWindowInfo(
1429 HANDLE32 hcon, /* [in] Handle to console screen buffer */
1430 BOOL32 bAbsolute, /* [in] Coordinate type flag */
1431 LPSMALL_RECT window) /* [in] Address of new window rectangle */
1433 FIXME(console, "(%x,%d,%p): stub\n", hcon, bAbsolute, window);
1434 return TRUE;
1438 /******************************************************************************
1439 * SetConsoleTextAttribute32 [KERNEL32.631] Sets colors for text
1441 * Sets the foreground and background color attributes of characters
1442 * written to the screen buffer.
1444 * RETURNS
1445 * Success: TRUE
1446 * Failure: FALSE
1448 BOOL32 WINAPI SetConsoleTextAttribute32(HANDLE32 hConsoleOutput,WORD wAttr)
1450 const int colormap[8] = {
1451 0,4,2,6,
1452 1,5,3,7,
1454 DWORD xlen;
1455 char buffer[20];
1457 TRACE(console,"(%d,%d)\n",hConsoleOutput,wAttr);
1458 sprintf(buffer,"%c[0;%s3%d;4%dm",
1460 (wAttr & FOREGROUND_INTENSITY)?"1;":"",
1461 colormap[wAttr&7],
1462 colormap[(wAttr&0x70)>>4]
1464 WriteFile(hConsoleOutput,buffer,strlen(buffer),&xlen,NULL);
1465 return TRUE;
1469 /******************************************************************************
1470 * SetConsoleScreenBufferSize [KERNEL32.630] Changes size of console
1472 * PARAMS
1473 * hConsoleOutput [I] Handle to console screen buffer
1474 * dwSize [I] New size in character rows and cols
1476 * RETURNS
1477 * Success: TRUE
1478 * Failure: FALSE
1480 BOOL32 WINAPI SetConsoleScreenBufferSize( HANDLE32 hConsoleOutput,
1481 COORD dwSize )
1483 FIXME(console, "(%d,%dx%d): stub\n",hConsoleOutput,dwSize.x,dwSize.y);
1484 return TRUE;
1488 /******************************************************************************
1489 * FillConsoleOutputCharacterA [KERNEL32.242]
1491 * PARAMS
1492 * hConsoleOutput [I] Handle to screen buffer
1493 * cCharacter [I] Character to write
1494 * nLength [I] Number of cells to write to
1495 * dwCoord [I] Coords of first cell
1496 * lpNumCharsWritten [O] Pointer to number of cells written
1498 * RETURNS
1499 * Success: TRUE
1500 * Failure: FALSE
1502 BOOL32 WINAPI FillConsoleOutputCharacterA(
1503 HANDLE32 hConsoleOutput,
1504 BYTE cCharacter,
1505 DWORD nLength,
1506 COORD dwCoord,
1507 LPDWORD lpNumCharsWritten)
1509 long count;
1510 DWORD xlen;
1512 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1513 for(count=0;count<nLength;count++)
1514 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
1515 *lpNumCharsWritten = nLength;
1516 return TRUE;
1520 /******************************************************************************
1521 * FillConsoleOutputCharacterW [KERNEL32.243] Writes characters to console
1523 * PARAMS
1524 * hConsoleOutput [I] Handle to screen buffer
1525 * cCharacter [I] Character to write
1526 * nLength [I] Number of cells to write to
1527 * dwCoord [I] Coords of first cell
1528 * lpNumCharsWritten [O] Pointer to number of cells written
1530 * RETURNS
1531 * Success: TRUE
1532 * Failure: FALSE
1534 BOOL32 WINAPI FillConsoleOutputCharacterW(HANDLE32 hConsoleOutput,
1535 WCHAR cCharacter,
1536 DWORD nLength,
1537 COORD dwCoord,
1538 LPDWORD lpNumCharsWritten)
1540 long count;
1541 DWORD xlen;
1543 SetConsoleCursorPosition(hConsoleOutput,dwCoord);
1544 /* FIXME: not quite correct ... but the lower part of UNICODE char comes
1545 * first
1547 for(count=0;count<nLength;count++)
1548 WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL);
1549 *lpNumCharsWritten = nLength;
1550 return TRUE;
1554 /******************************************************************************
1555 * FillConsoleOutputAttribute [KERNEL32.241] Sets attributes for console
1557 * PARAMS
1558 * hConsoleOutput [I] Handle to screen buffer
1559 * wAttribute [I] Color attribute to write
1560 * nLength [I] Number of cells to write to
1561 * dwCoord [I] Coords of first cell
1562 * lpNumAttrsWritten [O] Pointer to number of cells written
1564 * RETURNS
1565 * Success: TRUE
1566 * Failure: FALSE
1568 BOOL32 WINAPI FillConsoleOutputAttribute( HANDLE32 hConsoleOutput,
1569 WORD wAttribute, DWORD nLength, COORD dwCoord,
1570 LPDWORD lpNumAttrsWritten)
1572 FIXME(console, "(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput,
1573 wAttribute,nLength,dwCoord.x,dwCoord.y,lpNumAttrsWritten);
1574 *lpNumAttrsWritten = nLength;
1575 return TRUE;
1578 /******************************************************************************
1579 * ReadConsoleOutputCharacter32A [KERNEL32.573]
1581 * BUGS
1582 * Unimplemented
1584 BOOL32 WINAPI ReadConsoleOutputCharacter32A(HANDLE32 hConsoleOutput,
1585 LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword)
1587 FIXME(console, "(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr,
1588 dword,coord.x,coord.y,lpdword);
1589 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1590 return FALSE;
1594 /******************************************************************************
1595 * ScrollConsoleScreenBuffer [KERNEL32.612]
1597 * BUGS
1598 * Unimplemented
1600 BOOL32 WINAPI ScrollConsoleScreenBuffer( HANDLE32 hConsoleOutput,
1601 LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect,
1602 COORD dwDestOrigin, LPCHAR_INFO lpFill)
1604 FIXME(console, "(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect,
1605 lpClipRect,dwDestOrigin.x,dwDestOrigin.y,lpFill);
1606 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1607 return FALSE;