/* * Win32 kernel functions * * Copyright 1995 Martin von Loewis and Cameron Heide * Copyright 1997 Karl Garrison * Copyright 1998 John Richardson * Copyright 1998 Marcus Meissner */ /* FIXME: * - Completely lacks SCREENBUFFER interface. * - No abstraction for something other than xterm. * - Key input translation shouldn't use VkKeyScan and MapVirtualKey, since * they are window (USER) driver dependend. * - Output sometimes is buffered (We switched off buffering by ~ICANON ?) */ /* Reference applications: * - IDA (interactive disassembler) full version 3.75. Works. * - LYNX/W32. Works mostly, some keys crash it. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "winbase.h" #include "wine/winuser16.h" #include "wine/keyboard16.h" #include "k32obj.h" #include "thread.h" #include "async.h" #include "file.h" #include "process.h" #include "winerror.h" #include "wincon.h" #include "heap.h" #include "debug.h" #include "server/request.h" #include "server.h" /* The CONSOLE kernel32 Object */ typedef struct _CONSOLE { K32OBJ header; } CONSOLE; /* FIXME: Should be in an internal header file. OK, so which one? Used by CONSOLE_makecomplex. */ FILE *wine_openpty(int *master, int *slave, char *name, struct termios *term, struct winsize *winsize); /**************************************************************************** * CONSOLE_GetInfo */ static BOOL CONSOLE_GetInfo( HANDLE handle, struct get_console_info_reply *reply ) { struct get_console_info_request req; if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle, K32OBJ_CONSOLE, GENERIC_READ )) == -1) return FALSE; CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) ); return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL ); } /**************************************************************************** * XTERM_string_to_IR [internal] * * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the * queue. Does translation of vt100 style function keys and xterm-mouse clicks. */ static void CONSOLE_string_to_IR( HANDLE hConsoleInput,unsigned char *buf,int len) { int j,k; INPUT_RECORD ir; DWORD junk; for (j=0;j 'normal' keyboard event */ ir.EventType = 1; /* Key_event */ ir.Event.KeyEvent.bKeyDown = 1; ir.Event.KeyEvent.wRepeatCount = 0; ir.Event.KeyEvent.dwControlKeyState = 0; if (inchar & 0x80) { ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED; inchar &= ~0x80; } ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(inchar); if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100) ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED; if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200) ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED; if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400) ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED; ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16( ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff, 0 /* VirtualKeyCodes to ScanCode */ ); ir.Event.KeyEvent.uChar.AsciiChar = inchar; if (inchar==127) { /* backspace */ ir.Event.KeyEvent.uChar.AsciiChar = '\b'; /* FIXME: hmm */ ir.Event.KeyEvent.wVirtualScanCode = 0x0e; ir.Event.KeyEvent.wVirtualKeyCode = VK_BACK; } else { if (inchar=='\n') { ir.Event.KeyEvent.uChar.AsciiChar = '\r'; ir.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; ir.Event.KeyEvent.wVirtualScanCode = 0x1c; } else { if (inchar<' ') { /* FIXME: find good values for ^X */ ir.Event.KeyEvent.wVirtualKeyCode = 0xdead; ir.Event.KeyEvent.wVirtualScanCode = 0xbeef; } } } assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); ir.Event.KeyEvent.bKeyDown = 0; assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); continue; } /* inchar is ESC */ if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */ ir.EventType = 1; /* Key_event */ ir.Event.KeyEvent.bKeyDown = 1; ir.Event.KeyEvent.wRepeatCount = 0; ir.Event.KeyEvent.wVirtualKeyCode = VkKeyScan16(27); ir.Event.KeyEvent.wVirtualScanCode = MapVirtualKey16( ir.Event.KeyEvent.wVirtualKeyCode,0 ); ir.Event.KeyEvent.dwControlKeyState = 0; ir.Event.KeyEvent.uChar.AsciiChar = 27; assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); ir.Event.KeyEvent.bKeyDown = 0; assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); continue; } for (k=j;k='A') && (buf[k]<='Z')) || ((buf[k]>='a') && (buf[k]<='z')) || (buf[k]=='~') ) break; } if (k) or * Release (ESCM# */ if (kdwSize.x = 80; csbi->dwSize.y = 24; csbi->dwCursorPosition.x = 0; csbi->dwCursorPosition.y = 0; csbi->wAttributes = 0; csbi->srWindow.Left = 0; csbi->srWindow.Right = 79; csbi->srWindow.Top = 0; csbi->srWindow.Bottom = 23; csbi->dwMaximumWindowSize.x = 80; csbi->dwMaximumWindowSize.y = 24; return TRUE; } /****************************************************************************** * SetConsoleActiveScreenBuffer [KERNEL32.623] Sets buffer to current console * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI SetConsoleActiveScreenBuffer( HANDLE hConsoleOutput) /* [in] Handle to console screen buffer */ { FIXME(console, "(%x): stub\n", hConsoleOutput); return FALSE; } /*********************************************************************** * GetLargestConsoleWindowSize (KERNEL32.226) */ DWORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput ) { return (DWORD)MAKELONG(80,24); } /*********************************************************************** * FreeConsole (KERNEL32.267) */ BOOL WINAPI FreeConsole(VOID) { PDB *pdb = PROCESS_Current(); CONSOLE *console; SYSTEM_LOCK(); console = (CONSOLE *)pdb->console; if (console == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } CLIENT_SendRequest( REQ_FREE_CONSOLE, -1, 0 ); if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS) { K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } HANDLE_CloseAll( pdb, &console->header ); K32OBJ_DecCount( &console->header ); pdb->console = NULL; SYSTEM_UNLOCK(); return TRUE; } /************************************************************************* * CONSOLE_OpenHandle * * Open a handle to the current process console. */ HANDLE CONSOLE_OpenHandle( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES sa ) { struct open_console_request req; struct open_console_reply reply; CONSOLE *console; HANDLE handle; req.output = output; req.access = access; req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle); CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) ); CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); if (reply.handle == -1) return INVALID_HANDLE_VALUE; SYSTEM_LOCK(); if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console)))) { SYSTEM_UNLOCK(); return FALSE; } console->header.type = K32OBJ_CONSOLE; console->header.refcount = 1; handle = HANDLE_Alloc( PROCESS_Current(), &console->header, req.access, req.inherit, reply.handle ); SYSTEM_UNLOCK(); K32OBJ_DecCount(&console->header); return handle; } /************************************************************************* * CONSOLE_make_complex [internal] * * Turns a CONSOLE kernel object into a complex one. * (switches from output/input using the terminal where WINE was started to * its own xterm). * * This makes simple commandline tools pipeable, while complex commandline * tools work without getting messed up by debugoutput. * * All other functions should work indedependend from this call. * * To test for complex console: pid == 0 -> simple, otherwise complex. */ static BOOL CONSOLE_make_complex(HANDLE handle) { struct set_console_fd_request req; struct get_console_info_reply info; struct termios term; char buf[256]; char c = '\0'; int status = 0; int i,xpid,master,slave; DWORD xlen; if (!CONSOLE_GetInfo( handle, &info )) return FALSE; if (info.pid) return TRUE; /* already complex */ MSG("Console: Making console complex (creating an xterm)...\n"); if (tcgetattr(0, &term) < 0) { /* ignore failure, or we can't run from a script */ } term.c_lflag = ~(ECHO|ICANON); if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle, K32OBJ_CONSOLE, 0 )) == -1) return FALSE; if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0) return FALSE; if ((xpid=fork()) == 0) { tcsetattr(slave, TCSADRAIN, &term); sprintf(buf, "-Sxx%d", master); /* "-fn vga" for VGA font. Harmless if vga is not present: * xterm: unable to open font "vga", trying "fixed".... */ execlp("xterm", "xterm", buf, "-fn","vga",NULL); ERR(console, "error creating AllocConsole xterm\n"); exit(1); } req.pid = xpid; CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1, &req, sizeof(req) ); CLIENT_WaitReply( NULL, NULL, 0 ); /* most xterms like to print their window ID when used with -S; * read it and continue before the user has a chance... */ for (i=0; c!='\n'; (status=read(slave, &c, 1)), i++) { if (status == -1 && c == '\0') { /* wait for xterm to be created */ usleep(100); } if (i > 10000) { ERR(console, "can't read xterm WID\n"); kill(xpid, SIGKILL); return FALSE; } } /* enable mouseclicks */ sprintf(buf,"%c[?1001s%c[?1000h",27,27); WriteFile(handle,buf,strlen(buf),&xlen,NULL); if (GetConsoleTitleA( buf, sizeof(buf) )) { WriteFile(handle,"\033]2;",4,&xlen,NULL); WriteFile(handle,buf,strlen(buf),&xlen,NULL); WriteFile(handle,"\a",1,&xlen,NULL); } return TRUE; } /*********************************************************************** * AllocConsole (KERNEL32.103) * * creates an xterm with a pty to our program */ BOOL WINAPI AllocConsole(VOID) { struct open_console_request req; struct open_console_reply reply; PDB *pdb = PROCESS_Current(); CONSOLE *console; HANDLE hIn, hOut, hErr; SYSTEM_LOCK(); /* FIXME: really only need to lock the process */ console = (CONSOLE *)pdb->console; /* don't create a console if we already have one */ if (console != NULL) { SetLastError(ERROR_ACCESS_DENIED); SYSTEM_UNLOCK(); return FALSE; } if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console)))) { SYSTEM_UNLOCK(); return FALSE; } console->header.type = K32OBJ_CONSOLE; console->header.refcount = 1; CLIENT_SendRequest( REQ_ALLOC_CONSOLE, -1, 0 ); if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS) { K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } req.output = 0; req.access = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE; req.inherit = FALSE; CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) ); if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS) { K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } if ((hIn = HANDLE_Alloc(pdb,&console->header, req.access, FALSE, reply.handle)) == INVALID_HANDLE_VALUE) { K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } req.output = 1; CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) ); if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS) { CloseHandle(hIn); K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } if ((hOut = HANDLE_Alloc(pdb,&console->header, req.access, FALSE, reply.handle)) == INVALID_HANDLE_VALUE) { CloseHandle(hIn); K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } if (!DuplicateHandle( GetCurrentProcess(), hOut, GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS )) { CloseHandle(hIn); CloseHandle(hOut); K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } if (pdb->console) K32OBJ_DecCount( pdb->console ); pdb->console = (K32OBJ *)console; K32OBJ_IncCount( pdb->console ); /* NT resets the STD_*_HANDLEs on console alloc */ SetStdHandle(STD_INPUT_HANDLE, hIn); SetStdHandle(STD_OUTPUT_HANDLE, hOut); SetStdHandle(STD_ERROR_HANDLE, hErr); SetLastError(ERROR_SUCCESS); SYSTEM_UNLOCK(); SetConsoleTitleA("Wine Console"); return TRUE; } /****************************************************************************** * GetConsoleCP [KERNEL32.295] Returns the OEM code page for the console * * RETURNS * Code page code */ UINT WINAPI GetConsoleCP(VOID) { return GetACP(); } /*********************************************************************** * GetConsoleOutputCP (KERNEL32.189) */ UINT WINAPI GetConsoleOutputCP(VOID) { return GetConsoleCP(); } /*********************************************************************** * GetConsoleMode (KERNEL32.188) */ BOOL WINAPI GetConsoleMode(HANDLE hcon,LPDWORD mode) { struct get_console_mode_request req; struct get_console_mode_reply reply; if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, K32OBJ_CONSOLE, GENERIC_READ )) == -1) return FALSE; CLIENT_SendRequest( REQ_GET_CONSOLE_MODE, -1, 1, &req, sizeof(req)); if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE; *mode = reply.mode; return TRUE; } /****************************************************************************** * SetConsoleMode [KERNEL32.628] Sets input mode of console's input buffer * * PARAMS * hcon [I] Handle to console input or screen buffer * mode [I] Input or output mode to set * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI SetConsoleMode( HANDLE hcon, DWORD mode ) { struct set_console_mode_request req; if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, K32OBJ_CONSOLE, GENERIC_READ )) == -1) return FALSE; req.mode = mode; CLIENT_SendRequest( REQ_SET_CONSOLE_MODE, -1, 1, &req, sizeof(req)); return !CLIENT_WaitReply( NULL, NULL, 0 ); } /*********************************************************************** * GetConsoleTitleA (KERNEL32.191) */ DWORD WINAPI GetConsoleTitleA(LPSTR title,DWORD size) { struct get_console_info_request req; struct get_console_info_reply reply; int len; DWORD ret = 0; HANDLE hcon; if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE) return 0; if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, K32OBJ_CONSOLE, GENERIC_READ )) == -1) { CloseHandle( hcon ); return 0; } CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) ); if (!CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), title, size )) { if (len > sizeof(reply)+size) title[size-1] = 0; ret = strlen(title); } CloseHandle( hcon ); return ret; } /****************************************************************************** * GetConsoleTitle32W [KERNEL32.192] Retrieves title string for console * * PARAMS * title [O] Address of buffer for title * size [I] Size of buffer * * RETURNS * Success: Length of string copied * Failure: 0 */ DWORD WINAPI GetConsoleTitleW( LPWSTR title, DWORD size ) { char *tmp; DWORD ret; if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size ))) return 0; ret = GetConsoleTitleA( tmp, size ); lstrcpyAtoW( title, tmp ); HeapFree( GetProcessHeap(), 0, tmp ); return ret; } /*********************************************************************** * WriteConsoleA (KERNEL32.729) */ BOOL WINAPI WriteConsoleA( HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved ) { /* FIXME: should I check if this is a console handle? */ return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, NULL); } #define CADD(c) \ if (bufused==curbufsize-1) \ buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\ buffer[bufused++]=c; #define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}} /*********************************************************************** * WriteConsoleOutputA (KERNEL32.732) */ BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, LPSMALL_RECT lpWriteRegion) { int i,j,off=0,lastattr=-1; char sbuf[20],*buffer=NULL; int bufused=0,curbufsize = 100; DWORD res; const int colormap[8] = { 0,4,2,6, 1,5,3,7, }; CONSOLE_make_complex(hConsoleOutput); buffer = HeapAlloc(GetProcessHeap(),0,100);; curbufsize = 100; TRACE(console,"wr: top = %d, bottom=%d, left=%d,right=%d\n", lpWriteRegion->Top, lpWriteRegion->Bottom, lpWriteRegion->Left, lpWriteRegion->Right ); for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) { sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1); SADD(sbuf); for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) { if (lastattr!=lpBuffer[off].Attributes) { lastattr = lpBuffer[off].Attributes; sprintf(sbuf,"%c[0;%s3%d;4%dm", 27, (lastattr & FOREGROUND_INTENSITY)?"1;":"", colormap[lastattr&7], colormap[(lastattr&0x70)>>4] ); /* FIXME: BACKGROUND_INTENSITY */ SADD(sbuf); } CADD(lpBuffer[off].Char.AsciiChar); off++; } } sprintf(sbuf,"%c[0m",27);SADD(sbuf); WriteFile(hConsoleOutput,buffer,bufused,&res,NULL); HeapFree(GetProcessHeap(),0,buffer); return TRUE; } /*********************************************************************** * WriteConsoleW (KERNEL32.577) */ BOOL WINAPI WriteConsoleW( HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved ) { BOOL ret; LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite ); lstrcpynWtoA( xstring, lpBuffer,nNumberOfCharsToWrite); /* FIXME: should I check if this is a console handle? */ ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite, lpNumberOfCharsWritten, NULL); HeapFree( GetProcessHeap(), 0, xstring ); return ret; } /*********************************************************************** * ReadConsoleA (KERNEL32.419) */ BOOL WINAPI ReadConsoleA( HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved ) { int charsread = 0; LPSTR xbuf = (LPSTR)lpBuffer; struct read_console_input_request req; INPUT_RECORD ir; if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, GENERIC_READ )) == -1) return FALSE; TRACE(console,"(%d,%p,%ld,%p,%p)\n", hConsoleInput,lpBuffer,nNumberOfCharsToRead, lpNumberOfCharsRead,lpReserved ); CONSOLE_get_input(hConsoleInput,FALSE); req.count = 1; req.flush = 1; /* FIXME: should we read at least 1 char? The SDK does not say */ while (charsreadconsole; if (!console) return FALSE; if(console->title) /* Free old title, if there is one */ HeapFree( SystemHeap, 0, console->title ); console->title = (LPSTR)HeapAlloc(SystemHeap, 0,strlen(title)+1); if(console->title) strcpy(console->title,title); titlestring = HeapAlloc(GetProcessHeap(), 0,strlen(title)+strlen(titleformat)+1); if (!titlestring) { K32OBJ_DecCount(&console->header); return FALSE; } sprintf(titlestring,titleformat,title); #if 0 /* only set title for complex console (own xterm) */ if (console->pid != -1) { WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),titlestring,strlen(titlestring),&written,NULL); if (written == strlen(titlestring)) ret =TRUE; } else ret = TRUE; #endif HeapFree( GetProcessHeap(), 0, titlestring ); K32OBJ_DecCount(&console->header); return ret; #endif struct set_console_info_request req; struct get_console_info_reply info; HANDLE hcon; DWORD written; if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE) return FALSE; if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, K32OBJ_CONSOLE, GENERIC_WRITE )) == -1) goto error; req.mask = SET_CONSOLE_INFO_TITLE; CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 2, &req, sizeof(req), title, strlen(title)+1 ); if (CLIENT_WaitReply( NULL, NULL, 0 )) goto error; if (CONSOLE_GetInfo( hcon, &info ) && info.pid) { /* only set title for complex console (own xterm) */ WriteFile( hcon, "\033]2;", 4, &written, NULL ); WriteFile( hcon, title, strlen(title), &written, NULL ); WriteFile( hcon, "\a", 1, &written, NULL ); } return TRUE; error: CloseHandle( hcon ); return FALSE; } /****************************************************************************** * SetConsoleTitle32W [KERNEL32.477] Sets title bar string for console * * PARAMS * title [I] Address of new title * * NOTES * This should not be calling the A version * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI SetConsoleTitleW( LPCWSTR title ) { BOOL ret; LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title ); ret = SetConsoleTitleA(titleA); HeapFree( GetProcessHeap(), 0, titleA ); return ret; } /****************************************************************************** * SetConsoleCursorPosition [KERNEL32.627] * Sets the cursor position in console * * PARAMS * hConsoleOutput [I] Handle of console screen buffer * dwCursorPosition [I] New cursor position coordinates * * RETURNS STD */ BOOL WINAPI SetConsoleCursorPosition( HANDLE hcon, COORD pos ) { char xbuf[20]; DWORD xlen; /* make console complex only if we change lines, not just in the line */ if (pos.y) CONSOLE_make_complex(hcon); TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y ); /* x are columns, y rows */ if (pos.y) /* full screen cursor absolute positioning */ sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1); else /* relative cursor positioning in line (\r to go to 0) */ sprintf(xbuf,"\r%c[%dC", 0x1B, pos.x); /* FIXME: store internal if we start using own console buffers */ WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL); return TRUE; } /*********************************************************************** * GetNumberOfConsoleInputEvents (KERNEL32.246) */ BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hcon,LPDWORD nrofevents) { CONSOLE_get_input(hcon,FALSE); *nrofevents = 1; /* UMM */ return TRUE; } /*********************************************************************** * GetNumberOfConsoleMouseButtons (KERNEL32.358) */ BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons) { FIXME(console,"(%p): stub\n", nrofbuttons); *nrofbuttons = 2; return TRUE; } /****************************************************************************** * GetConsoleCursorInfo32 [KERNEL32.296] Gets size and visibility of console * * PARAMS * hcon [I] Handle to console screen buffer * cinfo [O] Address of cursor information * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI GetConsoleCursorInfo( HANDLE hcon, LPCONSOLE_CURSOR_INFO cinfo ) { struct get_console_info_reply reply; if (!CONSOLE_GetInfo( hcon, &reply )) return FALSE; if (cinfo) { cinfo->dwSize = reply.cursor_size; cinfo->bVisible = reply.cursor_visible; } return TRUE; } /****************************************************************************** * SetConsoleCursorInfo32 [KERNEL32.626] Sets size and visibility of cursor * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI SetConsoleCursorInfo( HANDLE hcon, /* [in] Handle to console screen buffer */ LPCONSOLE_CURSOR_INFO cinfo) /* [in] Address of cursor information */ { struct set_console_info_request req; char buf[8]; DWORD xlen; if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, K32OBJ_CONSOLE, GENERIC_WRITE )) == -1) return FALSE; CONSOLE_make_complex(hcon); sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l'); WriteFile(hcon,buf,strlen(buf),&xlen,NULL); req.cursor_size = cinfo->dwSize; req.cursor_visible = cinfo->bVisible; req.mask = SET_CONSOLE_INFO_CURSOR; CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 1, &req, sizeof(req) ); return !CLIENT_WaitReply( NULL, NULL, 0 ); } /****************************************************************************** * SetConsoleWindowInfo [KERNEL32.634] Sets size and position of console * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI SetConsoleWindowInfo( HANDLE hcon, /* [in] Handle to console screen buffer */ BOOL bAbsolute, /* [in] Coordinate type flag */ LPSMALL_RECT window) /* [in] Address of new window rectangle */ { FIXME(console, "(%x,%d,%p): stub\n", hcon, bAbsolute, window); return TRUE; } /****************************************************************************** * SetConsoleTextAttribute32 [KERNEL32.631] Sets colors for text * * Sets the foreground and background color attributes of characters * written to the screen buffer. * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttr) { const int colormap[8] = { 0,4,2,6, 1,5,3,7, }; DWORD xlen; char buffer[20]; TRACE(console,"(%d,%d)\n",hConsoleOutput,wAttr); sprintf(buffer,"%c[0;%s3%d;4%dm", 27, (wAttr & FOREGROUND_INTENSITY)?"1;":"", colormap[wAttr&7], colormap[(wAttr&0x70)>>4] ); WriteFile(hConsoleOutput,buffer,strlen(buffer),&xlen,NULL); return TRUE; } /****************************************************************************** * SetConsoleScreenBufferSize [KERNEL32.630] Changes size of console * * PARAMS * hConsoleOutput [I] Handle to console screen buffer * dwSize [I] New size in character rows and cols * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI SetConsoleScreenBufferSize( HANDLE hConsoleOutput, COORD dwSize ) { FIXME(console, "(%d,%dx%d): stub\n",hConsoleOutput,dwSize.x,dwSize.y); return TRUE; } /****************************************************************************** * FillConsoleOutputCharacterA [KERNEL32.242] * * PARAMS * hConsoleOutput [I] Handle to screen buffer * cCharacter [I] Character to write * nLength [I] Number of cells to write to * dwCoord [I] Coords of first cell * lpNumCharsWritten [O] Pointer to number of cells written * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, BYTE cCharacter, DWORD nLength, COORD dwCoord, LPDWORD lpNumCharsWritten) { long count; DWORD xlen; SetConsoleCursorPosition(hConsoleOutput,dwCoord); for(count=0;count