New console code based on Win32 windows.
This commit is contained in:
parent
6b6596a1e3
commit
0b83d4cbc6
|
@ -28,7 +28,8 @@ PROGRAMS = \
|
||||||
|
|
||||||
# Programs that link with libwine
|
# Programs that link with libwine
|
||||||
LIBPROGRAMS = \
|
LIBPROGRAMS = \
|
||||||
debugger/winedbg
|
debugger/winedbg \
|
||||||
|
programs/wineconsole/wineconsole
|
||||||
|
|
||||||
# Libraries (not dlls) to build
|
# Libraries (not dlls) to build
|
||||||
LIBRARIES = \
|
LIBRARIES = \
|
||||||
|
@ -59,6 +60,7 @@ INSTALLSUBDIRS = \
|
||||||
include \
|
include \
|
||||||
library \
|
library \
|
||||||
ole \
|
ole \
|
||||||
|
programs/wineconsole \
|
||||||
server \
|
server \
|
||||||
tools \
|
tools \
|
||||||
tsx11 \
|
tsx11 \
|
||||||
|
|
|
@ -7166,6 +7166,7 @@ programs/regtest/Makefile
|
||||||
programs/uninstaller/Makefile
|
programs/uninstaller/Makefile
|
||||||
programs/view/Makefile
|
programs/view/Makefile
|
||||||
programs/wcmd/Makefile
|
programs/wcmd/Makefile
|
||||||
|
programs/wineconsole/Makefile
|
||||||
programs/winemine/Makefile
|
programs/winemine/Makefile
|
||||||
programs/winetest/Makefile
|
programs/winetest/Makefile
|
||||||
programs/winhelp/Makefile
|
programs/winhelp/Makefile
|
||||||
|
@ -7426,6 +7427,7 @@ programs/regtest/Makefile
|
||||||
programs/uninstaller/Makefile
|
programs/uninstaller/Makefile
|
||||||
programs/view/Makefile
|
programs/view/Makefile
|
||||||
programs/wcmd/Makefile
|
programs/wcmd/Makefile
|
||||||
|
programs/wineconsole/Makefile
|
||||||
programs/winemine/Makefile
|
programs/winemine/Makefile
|
||||||
programs/winetest/Makefile
|
programs/winetest/Makefile
|
||||||
programs/winhelp/Makefile
|
programs/winhelp/Makefile
|
||||||
|
|
|
@ -1336,6 +1336,7 @@ programs/regtest/Makefile
|
||||||
programs/uninstaller/Makefile
|
programs/uninstaller/Makefile
|
||||||
programs/view/Makefile
|
programs/view/Makefile
|
||||||
programs/wcmd/Makefile
|
programs/wcmd/Makefile
|
||||||
|
programs/wineconsole/Makefile
|
||||||
programs/winemine/Makefile
|
programs/winemine/Makefile
|
||||||
programs/winetest/Makefile
|
programs/winetest/Makefile
|
||||||
programs/winhelp/Makefile
|
programs/winhelp/Makefile
|
||||||
|
|
|
@ -444,7 +444,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
|
||||||
if (synchronous) XSynchronize( data->display, True );
|
if (synchronous) XSynchronize( data->display, True );
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
data->display_fd = FILE_DupUnixHandle( ConnectionNumber(data->display),
|
data->display_fd = FILE_DupUnixHandle( ConnectionNumber(data->display),
|
||||||
GENERIC_READ | SYNCHRONIZE );
|
GENERIC_READ | SYNCHRONIZE, FALSE );
|
||||||
data->process_event_count = 0;
|
data->process_event_count = 0;
|
||||||
NtCurrentTeb()->driver_data = data;
|
NtCurrentTeb()->driver_data = data;
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -93,6 +93,17 @@ Options:
|
||||||
options that affect the Windows program should come
|
options that affect the Windows program should come
|
||||||
<emphasis>after</emphasis> it.
|
<emphasis>after</emphasis> it.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If you want to run a console program (aka a CUI executable), use
|
||||||
|
<command>wineconsole</command> instead of <command>wine</command>
|
||||||
|
to start it. It will display the program in a separate Window
|
||||||
|
(this requires X11 to be run). If you don't, you'll still be able
|
||||||
|
to run able your program, in the Unix console were you're started
|
||||||
|
your program, but with very limited capacities (so, your program
|
||||||
|
might work, but your mileage may vary). This shall be improved
|
||||||
|
in the future.
|
||||||
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="command-line-options">
|
<sect1 id="command-line-options">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.TH WINE 1 "Aug 5, 2001" "Version 20010731" "Windows On Unix"
|
.TH WINE 1 "Oct 13, 2001" "Version 20011004" "Windows On Unix"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
wine \- run Windows programs on Unix
|
wine \- run Windows programs on Unix
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -20,6 +20,16 @@ For debugging wine, use
|
||||||
.I program
|
.I program
|
||||||
instead.
|
instead.
|
||||||
.PP
|
.PP
|
||||||
|
For running CUI executables (Windows console programs), use
|
||||||
|
.B wineconsole
|
||||||
|
instead of
|
||||||
|
.B wine
|
||||||
|
. This will display all the output in a separate windows (this requires X11 to
|
||||||
|
run). Not using
|
||||||
|
.B wineconsole
|
||||||
|
for CUI programs will only provide very limited console support, and your
|
||||||
|
program might not function properly.
|
||||||
|
.PP
|
||||||
.B wine
|
.B wine
|
||||||
currently runs a growing list of applications written for all kinds of
|
currently runs a growing list of applications written for all kinds of
|
||||||
Windows versions >= Win2.0, e.g. Win3.1, Win95/98, NT.
|
Windows versions >= Win2.0, e.g. Win3.1, Win95/98, NT.
|
||||||
|
@ -350,6 +360,11 @@ The
|
||||||
.B wine
|
.B wine
|
||||||
program loader.
|
program loader.
|
||||||
.TP
|
.TP
|
||||||
|
.I @prefix@/bin/wineconsole
|
||||||
|
The
|
||||||
|
.B wine
|
||||||
|
program loader for CUI (console) applications.
|
||||||
|
.TP
|
||||||
.I @prefix@/bin/dosmod
|
.I @prefix@/bin/dosmod
|
||||||
The DOS program loader.
|
The DOS program loader.
|
||||||
.TP
|
.TP
|
||||||
|
|
63
files/file.c
63
files/file.c
|
@ -182,7 +182,7 @@ void FILE_SetDosError(void)
|
||||||
* Duplicate a Unix handle into a task handle.
|
* Duplicate a Unix handle into a task handle.
|
||||||
* Returns 0 on failure.
|
* Returns 0 on failure.
|
||||||
*/
|
*/
|
||||||
HANDLE FILE_DupUnixHandle( int fd, DWORD access )
|
HANDLE FILE_DupUnixHandle( int fd, DWORD access, BOOL inherit )
|
||||||
{
|
{
|
||||||
HANDLE ret;
|
HANDLE ret;
|
||||||
|
|
||||||
|
@ -191,6 +191,7 @@ HANDLE FILE_DupUnixHandle( int fd, DWORD access )
|
||||||
SERVER_START_REQ( alloc_file_handle )
|
SERVER_START_REQ( alloc_file_handle )
|
||||||
{
|
{
|
||||||
req->access = access;
|
req->access = access;
|
||||||
|
req->inherit = inherit;
|
||||||
req->fd = fd;
|
req->fd = fd;
|
||||||
SERVER_CALL();
|
SERVER_CALL();
|
||||||
ret = req->handle;
|
ret = req->handle;
|
||||||
|
@ -255,14 +256,15 @@ int FILE_GetUnixHandle( HANDLE handle, DWORD access )
|
||||||
* Open a handle to the current process console.
|
* Open a handle to the current process console.
|
||||||
* Returns 0 on failure.
|
* Returns 0 on failure.
|
||||||
*/
|
*/
|
||||||
static HANDLE FILE_OpenConsole( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES sa )
|
static HANDLE FILE_OpenConsole( BOOL output, DWORD access, DWORD sharing, LPSECURITY_ATTRIBUTES sa )
|
||||||
{
|
{
|
||||||
HANDLE ret;
|
HANDLE ret;
|
||||||
|
|
||||||
SERVER_START_REQ( open_console )
|
SERVER_START_REQ( open_console )
|
||||||
{
|
{
|
||||||
req->output = output;
|
req->from = output;
|
||||||
req->access = access;
|
req->access = access;
|
||||||
|
req->share = sharing;
|
||||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||||
SetLastError(0);
|
SetLastError(0);
|
||||||
SERVER_CALL_ERR();
|
SERVER_CALL_ERR();
|
||||||
|
@ -477,12 +479,12 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
|
||||||
/* Open a console for CONIN$ or CONOUT$ */
|
/* Open a console for CONIN$ or CONOUT$ */
|
||||||
if (!strcasecmp(filename, "CONIN$"))
|
if (!strcasecmp(filename, "CONIN$"))
|
||||||
{
|
{
|
||||||
ret = FILE_OpenConsole( FALSE, access, sa );
|
ret = FILE_OpenConsole( FALSE, access, sharing, sa );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (!strcasecmp(filename, "CONOUT$"))
|
if (!strcasecmp(filename, "CONOUT$"))
|
||||||
{
|
{
|
||||||
ret = FILE_OpenConsole( TRUE, access, sa );
|
ret = FILE_OpenConsole( TRUE, access, sharing, sa );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1452,15 +1454,14 @@ BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
|
||||||
if (!bytesToRead) return TRUE;
|
if (!bytesToRead) return TRUE;
|
||||||
|
|
||||||
unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type );
|
unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type );
|
||||||
if (unix_handle == -1)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
switch(type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case FD_TYPE_OVERLAPPED:
|
case FD_TYPE_OVERLAPPED:
|
||||||
if(!overlapped)
|
if (unix_handle == -1) return FALSE;
|
||||||
|
if (!overlapped)
|
||||||
{
|
{
|
||||||
close(unix_handle);
|
close(unix_handle);
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1493,23 +1494,28 @@ BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
|
||||||
SetLastError(ERROR_IO_PENDING);
|
SetLastError(ERROR_IO_PENDING);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
case FD_TYPE_CONSOLE:
|
||||||
|
return ReadConsoleA(hFile, buffer, bytesToRead, bytesRead, NULL);
|
||||||
default:
|
default:
|
||||||
if(overlapped)
|
/* normal unix files */
|
||||||
{
|
if (unix_handle == -1)
|
||||||
close(unix_handle);
|
return FALSE;
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
if (overlapped)
|
||||||
return FALSE;
|
{
|
||||||
}
|
close(unix_handle);
|
||||||
break;
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* code for synchronous reads */
|
/* code for synchronous reads */
|
||||||
while ((result = read( unix_handle, buffer, bytesToRead )) == -1)
|
while ((result = read( unix_handle, buffer, bytesToRead )) == -1)
|
||||||
{
|
{
|
||||||
if ((errno == EAGAIN) || (errno == EINTR)) continue;
|
if ((errno == EAGAIN) || (errno == EINTR)) continue;
|
||||||
if ((errno == EFAULT) && !IsBadWritePtr( buffer, bytesToRead )) continue;
|
if ((errno == EFAULT) && !IsBadWritePtr( buffer, bytesToRead )) continue;
|
||||||
FILE_SetDosError();
|
FILE_SetDosError();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
close( unix_handle );
|
close( unix_handle );
|
||||||
if (result == -1) return FALSE;
|
if (result == -1) return FALSE;
|
||||||
|
@ -1648,6 +1654,7 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
|
||||||
LPDWORD bytesWritten, LPOVERLAPPED overlapped )
|
LPDWORD bytesWritten, LPOVERLAPPED overlapped )
|
||||||
{
|
{
|
||||||
int unix_handle, result;
|
int unix_handle, result;
|
||||||
|
DWORD type;
|
||||||
|
|
||||||
TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToWrite,
|
TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToWrite,
|
||||||
bytesWritten, overlapped );
|
bytesWritten, overlapped );
|
||||||
|
@ -1659,8 +1666,18 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
|
||||||
if ( overlapped )
|
if ( overlapped )
|
||||||
return WriteFileEx(hFile, buffer, bytesToWrite, overlapped, NULL);
|
return WriteFileEx(hFile, buffer, bytesToWrite, overlapped, NULL);
|
||||||
|
|
||||||
unix_handle = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
|
unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type );
|
||||||
if (unix_handle == -1) return FALSE;
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case FD_TYPE_CONSOLE:
|
||||||
|
TRACE("%d %s %ld %p %p\n", hFile, debugstr_an(buffer, bytesToWrite), bytesToWrite,
|
||||||
|
bytesWritten, overlapped );
|
||||||
|
return WriteConsoleA(hFile, buffer, bytesToWrite, bytesWritten, NULL);
|
||||||
|
default:
|
||||||
|
if (unix_handle == -1)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* synchronous file write */
|
/* synchronous file write */
|
||||||
while ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
|
while ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
|
||||||
|
|
|
@ -71,7 +71,7 @@ inline static int FILE_contains_path (LPCSTR name)
|
||||||
extern int FILE_strcasecmp( const char *str1, const char *str2 );
|
extern int FILE_strcasecmp( const char *str1, const char *str2 );
|
||||||
extern int FILE_strncasecmp( const char *str1, const char *str2, int len );
|
extern int FILE_strncasecmp( const char *str1, const char *str2, int len );
|
||||||
extern void FILE_SetDosError(void);
|
extern void FILE_SetDosError(void);
|
||||||
extern HANDLE FILE_DupUnixHandle( int fd, DWORD access );
|
extern HANDLE FILE_DupUnixHandle( int fd, DWORD access, BOOL inherit );
|
||||||
extern int FILE_GetUnixHandle( HANDLE handle, DWORD access );
|
extern int FILE_GetUnixHandle( HANDLE handle, DWORD access );
|
||||||
extern BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
|
extern BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
|
||||||
extern HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 );
|
extern HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 );
|
||||||
|
|
|
@ -17,6 +17,8 @@ extern "C" {
|
||||||
#define ENABLE_ECHO_INPUT 0x04
|
#define ENABLE_ECHO_INPUT 0x04
|
||||||
#define ENABLE_WINDOW_INPUT 0x08
|
#define ENABLE_WINDOW_INPUT 0x08
|
||||||
#define ENABLE_MOUSE_INPUT 0x10
|
#define ENABLE_MOUSE_INPUT 0x10
|
||||||
|
/* Wine only code (extension) */
|
||||||
|
#define WINE_ENABLE_LINE_INPUT_EMACS 0x80
|
||||||
|
|
||||||
#define ENABLE_PROCESSED_OUTPUT 0x01
|
#define ENABLE_PROCESSED_OUTPUT 0x01
|
||||||
#define ENABLE_WRAP_AT_EOL_OUTPUT 0x02
|
#define ENABLE_WRAP_AT_EOL_OUTPUT 0x02
|
||||||
|
|
|
@ -577,6 +577,7 @@ struct alloc_file_handle_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
unsigned int access;
|
unsigned int access;
|
||||||
|
int inherit;
|
||||||
int fd;
|
int fd;
|
||||||
handle_t handle;
|
handle_t handle;
|
||||||
};
|
};
|
||||||
|
@ -755,8 +756,9 @@ struct alloc_console_request
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
unsigned int access;
|
unsigned int access;
|
||||||
int inherit;
|
int inherit;
|
||||||
|
void* pid;
|
||||||
handle_t handle_in;
|
handle_t handle_in;
|
||||||
handle_t handle_out;
|
handle_t event;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -767,25 +769,69 @@ struct free_console_request
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define CONSOLE_RENDERER_NONE_EVENT 0x00
|
||||||
|
#define CONSOLE_RENDERER_TITLE_EVENT 0x01
|
||||||
|
#define CONSOLE_RENDERER_ACTIVE_SB_EVENT 0x02
|
||||||
|
#define CONSOLE_RENDERER_SB_RESIZE_EVENT 0x03
|
||||||
|
#define CONSOLE_RENDERER_UPDATE_EVENT 0x04
|
||||||
|
#define CONSOLE_RENDERER_CURSOR_POS_EVENT 0x05
|
||||||
|
#define CONSOLE_RENDERER_CURSOR_GEOM_EVENT 0x06
|
||||||
|
#define CONSOLE_RENDERER_DISPLAY_EVENT 0x07
|
||||||
|
#define CONSOLE_RENDERER_EXIT_EVENT 0x08
|
||||||
|
struct console_renderer_event
|
||||||
|
{
|
||||||
|
short event;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct update
|
||||||
|
{
|
||||||
|
short top;
|
||||||
|
short bottom;
|
||||||
|
} update;
|
||||||
|
struct resize
|
||||||
|
{
|
||||||
|
short width;
|
||||||
|
short height;
|
||||||
|
} resize;
|
||||||
|
struct cursor_pos
|
||||||
|
{
|
||||||
|
short x;
|
||||||
|
short y;
|
||||||
|
} cursor_pos;
|
||||||
|
struct cursor_geom
|
||||||
|
{
|
||||||
|
short visible;
|
||||||
|
short size;
|
||||||
|
} cursor_geom;
|
||||||
|
struct display
|
||||||
|
{
|
||||||
|
short left;
|
||||||
|
short top;
|
||||||
|
short width;
|
||||||
|
short height;
|
||||||
|
} display;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
struct open_console_request
|
|
||||||
|
struct get_console_renderer_events_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
int output;
|
|
||||||
unsigned int access;
|
|
||||||
int inherit;
|
|
||||||
handle_t handle;
|
handle_t handle;
|
||||||
|
/* VARARG(data,bytes); */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct set_console_fd_request
|
struct open_console_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
|
int from;
|
||||||
|
|
||||||
|
unsigned int access;
|
||||||
|
int inherit;
|
||||||
|
int share;
|
||||||
handle_t handle;
|
handle_t handle;
|
||||||
int fd_in;
|
|
||||||
int fd_out;
|
|
||||||
int pid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -808,31 +854,114 @@ struct set_console_mode_request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct set_console_info_request
|
struct set_console_input_info_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
handle_t handle;
|
handle_t handle;
|
||||||
int mask;
|
int mask;
|
||||||
int cursor_size;
|
handle_t active_sb;
|
||||||
int cursor_visible;
|
int history_mode;
|
||||||
/* VARARG(title,string); */
|
int history_size;
|
||||||
|
/* VARARG(title,unicode_str); */
|
||||||
};
|
};
|
||||||
#define SET_CONSOLE_INFO_CURSOR 0x01
|
#define SET_CONSOLE_INPUT_INFO_ACTIVE_SB 0x01
|
||||||
#define SET_CONSOLE_INFO_TITLE 0x02
|
#define SET_CONSOLE_INPUT_INFO_TITLE 0x02
|
||||||
|
#define SET_CONSOLE_INPUT_INFO_HISTORY_MODE 0x04
|
||||||
|
#define SET_CONSOLE_INPUT_INFO_HISTORY_SIZE 0x08
|
||||||
|
|
||||||
|
|
||||||
struct get_console_info_request
|
|
||||||
|
struct get_console_input_info_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
handle_t handle;
|
handle_t handle;
|
||||||
int cursor_size;
|
int history_mode;
|
||||||
int cursor_visible;
|
int history_size;
|
||||||
int pid;
|
int history_index;
|
||||||
/* VARARG(title,string); */
|
/* VARARG(title,unicode_str); */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct append_console_input_history_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
/* VARARG(line,unicode_str); */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct get_console_input_history_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
int index;
|
||||||
|
/* VARARG(line,unicode_str); */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct create_console_output_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle_in;
|
||||||
|
int access;
|
||||||
|
int share;
|
||||||
|
int inherit;
|
||||||
|
handle_t handle_out;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct set_console_output_info_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
int mask;
|
||||||
|
short int cursor_size;
|
||||||
|
short int cursor_visible;
|
||||||
|
short int cursor_x;
|
||||||
|
short int cursor_y;
|
||||||
|
short int width;
|
||||||
|
short int height;
|
||||||
|
short int attr;
|
||||||
|
short int win_left;
|
||||||
|
short int win_top;
|
||||||
|
short int win_right;
|
||||||
|
short int win_bottom;
|
||||||
|
short int max_width;
|
||||||
|
short int max_height;
|
||||||
|
};
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM 0x01
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS 0x02
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_SIZE 0x04
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_ATTR 0x08
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW 0x10
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_MAX_SIZE 0x20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct get_console_output_info_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
short int cursor_size;
|
||||||
|
short int cursor_visible;
|
||||||
|
short int cursor_x;
|
||||||
|
short int cursor_y;
|
||||||
|
short int width;
|
||||||
|
short int height;
|
||||||
|
short int attr;
|
||||||
|
short int win_left;
|
||||||
|
short int win_top;
|
||||||
|
short int win_right;
|
||||||
|
short int win_bottom;
|
||||||
|
short int max_width;
|
||||||
|
short int max_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct write_console_input_request
|
struct write_console_input_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
|
@ -842,6 +971,7 @@ struct write_console_input_request
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct read_console_input_request
|
struct read_console_input_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
|
@ -853,6 +983,53 @@ struct read_console_input_request
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct write_console_output_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
short int x;
|
||||||
|
short int y;
|
||||||
|
/* VARARG(data,bytes); */
|
||||||
|
int written;
|
||||||
|
};
|
||||||
|
#define WRITE_CONSOLE_MODE_TEXT 0x00
|
||||||
|
#define WRITE_CONSOLE_MODE_ATTR 0x01
|
||||||
|
#define WRITE_CONSOLE_MODE_TEXTATTR 0x02
|
||||||
|
#define WRITE_CONSOLE_MODE_TEXTSTDATTR 0x03
|
||||||
|
#define WRITE_CONSOLE_MODE_UNIFORM 0x04
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct read_console_output_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
short int x;
|
||||||
|
short int y;
|
||||||
|
short int w;
|
||||||
|
short int h;
|
||||||
|
short int eff_w;
|
||||||
|
short int eff_h;
|
||||||
|
/* VARARG(data,bytes); */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct move_console_output_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
short int x_src;
|
||||||
|
short int y_src;
|
||||||
|
short int x_dst;
|
||||||
|
short int y_dst;
|
||||||
|
short int w;
|
||||||
|
short int h;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct create_change_notification_request
|
struct create_change_notification_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
|
@ -1843,14 +2020,22 @@ enum request
|
||||||
REQ_enable_socket_event,
|
REQ_enable_socket_event,
|
||||||
REQ_alloc_console,
|
REQ_alloc_console,
|
||||||
REQ_free_console,
|
REQ_free_console,
|
||||||
|
REQ_get_console_renderer_events,
|
||||||
REQ_open_console,
|
REQ_open_console,
|
||||||
REQ_set_console_fd,
|
|
||||||
REQ_get_console_mode,
|
REQ_get_console_mode,
|
||||||
REQ_set_console_mode,
|
REQ_set_console_mode,
|
||||||
REQ_set_console_info,
|
REQ_set_console_input_info,
|
||||||
REQ_get_console_info,
|
REQ_get_console_input_info,
|
||||||
|
REQ_append_console_input_history,
|
||||||
|
REQ_get_console_input_history,
|
||||||
|
REQ_create_console_output,
|
||||||
|
REQ_set_console_output_info,
|
||||||
|
REQ_get_console_output_info,
|
||||||
REQ_write_console_input,
|
REQ_write_console_input,
|
||||||
REQ_read_console_input,
|
REQ_read_console_input,
|
||||||
|
REQ_write_console_output,
|
||||||
|
REQ_read_console_output,
|
||||||
|
REQ_move_console_output,
|
||||||
REQ_create_change_notification,
|
REQ_create_change_notification,
|
||||||
REQ_create_mapping,
|
REQ_create_mapping,
|
||||||
REQ_open_mapping,
|
REQ_open_mapping,
|
||||||
|
@ -1990,14 +2175,22 @@ union generic_request
|
||||||
struct enable_socket_event_request enable_socket_event;
|
struct enable_socket_event_request enable_socket_event;
|
||||||
struct alloc_console_request alloc_console;
|
struct alloc_console_request alloc_console;
|
||||||
struct free_console_request free_console;
|
struct free_console_request free_console;
|
||||||
|
struct get_console_renderer_events_request get_console_renderer_events;
|
||||||
struct open_console_request open_console;
|
struct open_console_request open_console;
|
||||||
struct set_console_fd_request set_console_fd;
|
|
||||||
struct get_console_mode_request get_console_mode;
|
struct get_console_mode_request get_console_mode;
|
||||||
struct set_console_mode_request set_console_mode;
|
struct set_console_mode_request set_console_mode;
|
||||||
struct set_console_info_request set_console_info;
|
struct set_console_input_info_request set_console_input_info;
|
||||||
struct get_console_info_request get_console_info;
|
struct get_console_input_info_request get_console_input_info;
|
||||||
|
struct append_console_input_history_request append_console_input_history;
|
||||||
|
struct get_console_input_history_request get_console_input_history;
|
||||||
|
struct create_console_output_request create_console_output;
|
||||||
|
struct set_console_output_info_request set_console_output_info;
|
||||||
|
struct get_console_output_info_request get_console_output_info;
|
||||||
struct write_console_input_request write_console_input;
|
struct write_console_input_request write_console_input;
|
||||||
struct read_console_input_request read_console_input;
|
struct read_console_input_request read_console_input;
|
||||||
|
struct write_console_output_request write_console_output;
|
||||||
|
struct read_console_output_request read_console_output;
|
||||||
|
struct move_console_output_request move_console_output;
|
||||||
struct create_change_notification_request create_change_notification;
|
struct create_change_notification_request create_change_notification;
|
||||||
struct create_mapping_request create_mapping;
|
struct create_mapping_request create_mapping;
|
||||||
struct open_mapping_request open_mapping;
|
struct open_mapping_request open_mapping;
|
||||||
|
@ -2080,6 +2273,6 @@ union generic_request
|
||||||
struct get_window_properties_request get_window_properties;
|
struct get_window_properties_request get_window_properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 64
|
#define SERVER_PROTOCOL_VERSION 65
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -1052,10 +1052,6 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
||||||
|
|
||||||
/* Warn if unsupported features are used */
|
/* Warn if unsupported features are used */
|
||||||
|
|
||||||
if (dwCreationFlags & DETACHED_PROCESS)
|
|
||||||
FIXME("(%s,...): DETACHED_PROCESS ignored\n", name);
|
|
||||||
if (dwCreationFlags & CREATE_NEW_CONSOLE)
|
|
||||||
FIXME("(%s,...): CREATE_NEW_CONSOLE ignored\n", name);
|
|
||||||
if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
|
if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
|
||||||
FIXME("(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
|
FIXME("(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
|
||||||
if (dwCreationFlags & IDLE_PRIORITY_CLASS)
|
if (dwCreationFlags & IDLE_PRIORITY_CLASS)
|
||||||
|
|
|
@ -17,6 +17,7 @@ SUBDIRS = \
|
||||||
uninstaller \
|
uninstaller \
|
||||||
view \
|
view \
|
||||||
wcmd \
|
wcmd \
|
||||||
|
wineconsole \
|
||||||
winemine \
|
winemine \
|
||||||
winetest \
|
winetest \
|
||||||
winhelp \
|
winhelp \
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Makefile
|
||||||
|
wineconsole.spec.c
|
||||||
|
wineconsole_res.res
|
|
@ -0,0 +1,19 @@
|
||||||
|
EXTRADEFS = -DSTRICT -DUNICODE
|
||||||
|
TOPSRCDIR = @top_srcdir@
|
||||||
|
TOPOBJDIR = ../..
|
||||||
|
SRCDIR = @srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
MODULE = wineconsole
|
||||||
|
|
||||||
|
C_SRCS = \
|
||||||
|
dialog.c \
|
||||||
|
user.c \
|
||||||
|
wineconsole.c
|
||||||
|
|
||||||
|
RC_SRCS = \
|
||||||
|
wineconsole_res.rc
|
||||||
|
|
||||||
|
@MAKE_PROG_RULES@
|
||||||
|
|
||||||
|
|
||||||
|
### Dependencies:
|
|
@ -0,0 +1,515 @@
|
||||||
|
/* dialog management for wineconsole
|
||||||
|
* (c) 2001 Eric Pouech
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "winecon_private.h"
|
||||||
|
#include "commctrl.h"
|
||||||
|
#include "prsht.h"
|
||||||
|
|
||||||
|
/* FIXME: so far, part of the code is made in ASCII because the Uncode property sheet functions
|
||||||
|
* are not implemented yet
|
||||||
|
*/
|
||||||
|
struct dialog_info
|
||||||
|
{
|
||||||
|
struct inner_data* data; /* pointer to current winecon info */
|
||||||
|
HWND hDlg; /* handle to window dialog */
|
||||||
|
int nFont; /* number of font size in size LB */
|
||||||
|
struct font_info
|
||||||
|
{
|
||||||
|
TEXTMETRIC tm;
|
||||||
|
LOGFONT lf;
|
||||||
|
} *font; /* array of nFont. index sync'ed with SIZE LB */
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_OptionDlgProc
|
||||||
|
*
|
||||||
|
* Dialog prop for the option property sheet
|
||||||
|
*/
|
||||||
|
static BOOL WINAPI WCUSER_OptionDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct dialog_info* di;
|
||||||
|
unsigned idc;
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
|
||||||
|
di->hDlg = hDlg;
|
||||||
|
SetWindowLongA(hDlg, DWL_USER, (DWORD)di);
|
||||||
|
if (di->data->cursor_size < 33) idc = IDC_OPT_CURSOR_SMALL;
|
||||||
|
else if (di->data->cursor_size < 66) idc = IDC_OPT_CURSOR_MEDIUM;
|
||||||
|
else idc = IDC_OPT_CURSOR_LARGE;
|
||||||
|
SendDlgItemMessage(hDlg, idc, BM_SETCHECK, BST_CHECKED, 0L);
|
||||||
|
SetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, WINECON_GetHistorySize(di->data->hConIn), FALSE);
|
||||||
|
if (WINECON_GetHistoryMode(di->data->hConIn))
|
||||||
|
SendDlgItemMessage(hDlg, IDC_OPT_HIST_DOUBLE, BM_SETCHECK, BST_CHECKED, 0L);
|
||||||
|
return FALSE; /* because we set the focus */
|
||||||
|
case WM_COMMAND:
|
||||||
|
break;
|
||||||
|
case WM_NOTIFY:
|
||||||
|
{
|
||||||
|
NMHDR* nmhdr = (NMHDR*)lParam;
|
||||||
|
|
||||||
|
di = (struct dialog_info*)GetWindowLongA(hDlg, DWL_USER);
|
||||||
|
switch (nmhdr->code)
|
||||||
|
{
|
||||||
|
case PSN_SETACTIVE:
|
||||||
|
/* needed in propsheet to keep properly the selected radio button
|
||||||
|
* otherwise, the focus would be set to the first tab stop in the
|
||||||
|
* propsheet, which would always activate the first radio button
|
||||||
|
*/
|
||||||
|
if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED)
|
||||||
|
idc = IDC_OPT_CURSOR_SMALL;
|
||||||
|
else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED)
|
||||||
|
idc = IDC_OPT_CURSOR_MEDIUM;
|
||||||
|
else
|
||||||
|
idc = IDC_OPT_CURSOR_LARGE;
|
||||||
|
PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, idc), TRUE);
|
||||||
|
break;
|
||||||
|
case PSN_APPLY:
|
||||||
|
{
|
||||||
|
int curs_size;
|
||||||
|
int hist_size;
|
||||||
|
BOOL done;
|
||||||
|
|
||||||
|
if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_SMALL) == BST_CHECKED) curs_size = 33;
|
||||||
|
else if (IsDlgButtonChecked(hDlg, IDC_OPT_CURSOR_MEDIUM) == BST_CHECKED) curs_size = 66;
|
||||||
|
else curs_size = 99;
|
||||||
|
if (curs_size != di->data->cursor_size)
|
||||||
|
{
|
||||||
|
CONSOLE_CURSOR_INFO cinfo;
|
||||||
|
cinfo.dwSize = curs_size;
|
||||||
|
cinfo.bVisible = di->data->cursor_visible;
|
||||||
|
SetConsoleCursorInfo(di->data->hConOut, &cinfo);
|
||||||
|
}
|
||||||
|
hist_size = GetDlgItemInt(hDlg, IDC_OPT_HIST_SIZE, &done, FALSE);
|
||||||
|
if (done) WINECON_SetHistorySize(di->data->hConIn, hist_size);
|
||||||
|
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
|
||||||
|
WINECON_SetHistoryMode(di->data->hConIn,
|
||||||
|
IsDlgButtonChecked(hDlg, IDC_OPT_HIST_DOUBLE) & BST_CHECKED);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_FontPreviewProc
|
||||||
|
*
|
||||||
|
* Window proc for font previewer in font property sheet
|
||||||
|
*/
|
||||||
|
static LRESULT WINAPI WCUSER_FontPreviewProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_PAINT:
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
int font_idx;
|
||||||
|
int size_idx;
|
||||||
|
struct dialog_info* di;
|
||||||
|
|
||||||
|
di = (struct dialog_info*)GetWindowLong(GetParent(hWnd), DWL_USER);
|
||||||
|
BeginPaint(hWnd, &ps);
|
||||||
|
|
||||||
|
font_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
|
||||||
|
size_idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
|
||||||
|
|
||||||
|
if (font_idx >= 0 && size_idx >= 0 && size_idx < di->nFont)
|
||||||
|
{
|
||||||
|
HFONT hFont, hOldFont;
|
||||||
|
WCHAR buf1[256];
|
||||||
|
WCHAR buf2[256];
|
||||||
|
int len1, len2;
|
||||||
|
|
||||||
|
hFont = CreateFontIndirect(&di->font[size_idx].lf);
|
||||||
|
len1 = LoadString(GetModuleHandle(NULL), IDS_FNT_PREVIEW_1,
|
||||||
|
buf1, sizeof(buf1) / sizeof(WCHAR));
|
||||||
|
len2 = LoadString(GetModuleHandle(NULL), IDS_FNT_PREVIEW_2,
|
||||||
|
buf2, sizeof(buf2) / sizeof(WCHAR));
|
||||||
|
if (hFont && len1)
|
||||||
|
{
|
||||||
|
hOldFont = SelectObject(ps.hdc, hFont);
|
||||||
|
SetBkColor(ps.hdc, RGB(0x00, 0x00, 0x00));
|
||||||
|
SetTextColor(ps.hdc, RGB(0xFF, 0xFF, 0xFF));
|
||||||
|
TextOut(ps.hdc, 0, 0, buf1, len1);
|
||||||
|
if (len2)
|
||||||
|
TextOut(ps.hdc, 0, di->font[size_idx].tm.tmHeight, buf2, len2);
|
||||||
|
SelectObject(ps.hdc, hOldFont);
|
||||||
|
DeleteObject(hFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EndPaint(hWnd, &ps);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* font_enum
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int CALLBACK font_enum_size2(const LOGFONT* lf, const TEXTMETRIC* tm,
|
||||||
|
DWORD FontType, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct dialog_info* di = (struct dialog_info*)lParam;
|
||||||
|
|
||||||
|
if (WCUSER_ValidateFontMetric(di->data, tm))
|
||||||
|
{
|
||||||
|
di->nFont++;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CALLBACK font_enum(const LOGFONT* lf, const TEXTMETRIC* tm,
|
||||||
|
DWORD FontType, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct dialog_info* di = (struct dialog_info*)lParam;
|
||||||
|
HDC hdc;
|
||||||
|
|
||||||
|
if (WCUSER_ValidateFont(di->data, lf) && (hdc = GetDC(di->hDlg)))
|
||||||
|
{
|
||||||
|
di->nFont = 0;
|
||||||
|
EnumFontFamilies(hdc, lf->lfFaceName, font_enum_size2, (LPARAM)di);
|
||||||
|
if (di->nFont)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_ADDSTRING,
|
||||||
|
0, (LPARAM)lf->lfFaceName);
|
||||||
|
}
|
||||||
|
ReleaseDC(di->hDlg, hdc);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* font_enum_size
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int CALLBACK font_enum_size(const LOGFONT* lf, const TEXTMETRIC* tm,
|
||||||
|
DWORD FontType, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct dialog_info* di = (struct dialog_info*)lParam;
|
||||||
|
|
||||||
|
if (WCUSER_ValidateFontMetric(di->data, tm))
|
||||||
|
{
|
||||||
|
WCHAR buf[32];
|
||||||
|
WCHAR fmt[] = {'%','l','d',0};
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
/* we want the string to be sorted with a numeric order, not a lexicographic...
|
||||||
|
* do the job by hand... get where to insert the new string
|
||||||
|
*/
|
||||||
|
for (idx = 0; idx < di->nFont && tm->tmHeight > di->font[idx].tm.tmHeight; idx++);
|
||||||
|
wsprintfW(buf, fmt, tm->tmHeight);
|
||||||
|
SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_INSERTSTRING, idx, (LPARAM)buf);
|
||||||
|
|
||||||
|
/* now grow our arrays and insert to values at the same index than in the list box */
|
||||||
|
di->font = HeapReAlloc(GetProcessHeap(), 0, di->font, sizeof(*di->font) * (di->nFont + 1));
|
||||||
|
if (idx != di->nFont)
|
||||||
|
memmove(&di->font[idx + 1], &di->font[idx], (di->nFont - idx) * sizeof(*di->font));
|
||||||
|
di->font[idx].tm = *tm;
|
||||||
|
di->font[idx].lf = *lf;
|
||||||
|
di->nFont++;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* select_font
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static BOOL select_font(struct dialog_info* di)
|
||||||
|
{
|
||||||
|
int idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
|
||||||
|
WCHAR buf[256];
|
||||||
|
WCHAR fmt[128];
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= di->nFont)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
LoadString(GetModuleHandle(NULL), IDS_FNT_DISPLAY, fmt, sizeof(fmt) / sizeof(WCHAR));
|
||||||
|
wsprintfW(buf, fmt, di->font[idx].tm.tmMaxCharWidth, di->font[idx].tm.tmHeight);
|
||||||
|
|
||||||
|
SendDlgItemMessage(di->hDlg, IDC_FNT_FONT_INFO, WM_SETTEXT, 0, (LPARAM)buf);
|
||||||
|
InvalidateRect(GetDlgItem(di->hDlg, IDC_FNT_PREVIEW), NULL, TRUE);
|
||||||
|
UpdateWindow(GetDlgItem(di->hDlg, IDC_FNT_PREVIEW));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* fill_list_size
|
||||||
|
*
|
||||||
|
* fills the size list box according to selected family in font LB
|
||||||
|
*/
|
||||||
|
static BOOL fill_list_size(struct dialog_info* di, BOOL doInit)
|
||||||
|
{
|
||||||
|
HDC hdc;
|
||||||
|
int idx;
|
||||||
|
WCHAR lfFaceName[LF_FACESIZE];
|
||||||
|
|
||||||
|
idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETCURSEL, 0L, 0L);
|
||||||
|
if (idx < 0) return FALSE;
|
||||||
|
|
||||||
|
hdc = GetDC(di->hDlg);
|
||||||
|
if (!hdc) return FALSE;
|
||||||
|
|
||||||
|
SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_GETTEXT, idx, (LPARAM)lfFaceName);
|
||||||
|
SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_RESETCONTENT, 0L, 0L);
|
||||||
|
if (di->font) HeapFree(GetProcessHeap(), 0, di->font);
|
||||||
|
di->nFont = 0;
|
||||||
|
di->font = NULL;
|
||||||
|
|
||||||
|
EnumFontFamilies(hdc, lfFaceName, font_enum_size, (LPARAM)di);
|
||||||
|
ReleaseDC(di->hDlg, hdc);
|
||||||
|
|
||||||
|
if (doInit)
|
||||||
|
{
|
||||||
|
for (idx = 0; idx < di->nFont; idx++)
|
||||||
|
{
|
||||||
|
if (memcmp(&di->data->logFont, &di->font[idx].lf, sizeof(LOGFONT)) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (idx == di->nFont) idx = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
idx = 0;
|
||||||
|
SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_SETCURSEL, idx, 0L);
|
||||||
|
select_font(di);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* fill_list_font
|
||||||
|
*
|
||||||
|
* Fills the font LB
|
||||||
|
*/
|
||||||
|
static BOOL fill_list_font(struct dialog_info* di)
|
||||||
|
{
|
||||||
|
HDC hdc;
|
||||||
|
|
||||||
|
hdc = GetDC(di->hDlg);
|
||||||
|
if (!hdc) return FALSE;
|
||||||
|
|
||||||
|
SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_RESETCONTENT, 0L, 0L);
|
||||||
|
EnumFontFamilies(hdc, NULL, font_enum, (LPARAM)di);
|
||||||
|
ReleaseDC(di->hDlg, hdc);
|
||||||
|
if (SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SELECTSTRING,
|
||||||
|
(WPARAM)-1, (LPARAM)di->data->logFont.lfFaceName) == LB_ERR)
|
||||||
|
SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_FONT, LB_SETCURSEL, 0L, 0L);
|
||||||
|
fill_list_size(di, TRUE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_FontDlgProc
|
||||||
|
*
|
||||||
|
* Dialog proc for the Font property sheet
|
||||||
|
*/
|
||||||
|
static BOOL WINAPI WCUSER_FontDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct dialog_info* di;
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
|
||||||
|
di->hDlg = hDlg;
|
||||||
|
SetWindowLong(hDlg, DWL_USER, (DWORD)di);
|
||||||
|
fill_list_font(di);
|
||||||
|
break;
|
||||||
|
case WM_COMMAND:
|
||||||
|
di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
|
||||||
|
switch (LOWORD(wParam))
|
||||||
|
{
|
||||||
|
case IDC_FNT_LIST_FONT:
|
||||||
|
if (HIWORD(wParam) == LBN_SELCHANGE)
|
||||||
|
{
|
||||||
|
fill_list_size(di, FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDC_FNT_LIST_SIZE:
|
||||||
|
if (HIWORD(wParam) == LBN_SELCHANGE)
|
||||||
|
{
|
||||||
|
select_font(di);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_NOTIFY:
|
||||||
|
{
|
||||||
|
NMHDR* nmhdr = (NMHDR*)lParam;
|
||||||
|
|
||||||
|
di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
|
||||||
|
switch (nmhdr->code)
|
||||||
|
{
|
||||||
|
case PSN_APPLY:
|
||||||
|
{
|
||||||
|
int idx = SendDlgItemMessage(di->hDlg, IDC_FNT_LIST_SIZE, LB_GETCURSEL, 0L, 0L);
|
||||||
|
|
||||||
|
if (idx >= 0 && idx < di->nFont)
|
||||||
|
{
|
||||||
|
WCUSER_SetFont(di->data, &di->font[idx].lf, &di->font[idx].tm);
|
||||||
|
}
|
||||||
|
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_ConfigDlgProc
|
||||||
|
*
|
||||||
|
* Dialog proc for the config property sheet
|
||||||
|
*/
|
||||||
|
static BOOL WINAPI WCUSER_ConfigDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct dialog_info* di;
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
di = (struct dialog_info*)((PROPSHEETPAGEA*)lParam)->lParam;
|
||||||
|
di->hDlg = hDlg;
|
||||||
|
SetWindowLong(hDlg, DWL_USER, (DWORD)di);
|
||||||
|
SetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH, di->data->sb_width, FALSE);
|
||||||
|
SetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT, di->data->sb_height, FALSE);
|
||||||
|
SetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH, di->data->win_width, FALSE);
|
||||||
|
SetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, di->data->win_height, FALSE);
|
||||||
|
break;
|
||||||
|
case WM_COMMAND:
|
||||||
|
di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
|
||||||
|
switch (LOWORD(wParam))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_NOTIFY:
|
||||||
|
{
|
||||||
|
NMHDR* nmhdr = (NMHDR*)lParam;
|
||||||
|
|
||||||
|
di = (struct dialog_info*)GetWindowLong(hDlg, DWL_USER);
|
||||||
|
switch (nmhdr->code)
|
||||||
|
{
|
||||||
|
case PSN_APPLY:
|
||||||
|
{
|
||||||
|
COORD sb;
|
||||||
|
SMALL_RECT pos;
|
||||||
|
BOOL st_w, st_h;
|
||||||
|
|
||||||
|
sb.X = GetDlgItemInt(hDlg, IDC_CNF_SB_WIDTH, &st_w, FALSE);
|
||||||
|
sb.Y = GetDlgItemInt(hDlg, IDC_CNF_SB_HEIGHT, &st_h, FALSE);
|
||||||
|
if (st_w && st_h && (sb.X != di->data->sb_width || sb.Y != di->data->sb_height))
|
||||||
|
{
|
||||||
|
SetConsoleScreenBufferSize(di->data->hConOut, sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.Right = GetDlgItemInt(hDlg, IDC_CNF_WIN_WIDTH, &st_w, FALSE);
|
||||||
|
pos.Bottom = GetDlgItemInt(hDlg, IDC_CNF_WIN_HEIGHT, &st_h, FALSE);
|
||||||
|
if (st_w && st_h &&
|
||||||
|
(pos.Right != di->data->win_width || pos.Bottom != di->data->win_height))
|
||||||
|
{
|
||||||
|
pos.Left = pos.Top = 0;
|
||||||
|
pos.Right--; pos.Bottom--;
|
||||||
|
SetConsoleWindowInfo(di->data->hConOut, FALSE, &pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_GetProperties
|
||||||
|
*
|
||||||
|
* Runs the dialog box to set up the winconsole options
|
||||||
|
*/
|
||||||
|
BOOL WCUSER_GetProperties(struct inner_data* data)
|
||||||
|
{
|
||||||
|
HPROPSHEETPAGE psPage[3];
|
||||||
|
PROPSHEETPAGEA psp;
|
||||||
|
PROPSHEETHEADERA psHead;
|
||||||
|
WNDCLASS wndclass;
|
||||||
|
static WCHAR szFntPreview[] = {'W','i','n','e','C','o','n','F','o','n','t','P','r','e','v','i','e','w',0};
|
||||||
|
struct dialog_info di;
|
||||||
|
|
||||||
|
InitCommonControls();
|
||||||
|
|
||||||
|
di.data = data;
|
||||||
|
di.nFont = 0;
|
||||||
|
di.font = NULL;
|
||||||
|
|
||||||
|
wndclass.style = 0;
|
||||||
|
wndclass.lpfnWndProc = WCUSER_FontPreviewProc;
|
||||||
|
wndclass.cbClsExtra = 0;
|
||||||
|
wndclass.cbWndExtra = 0;
|
||||||
|
wndclass.hInstance = GetModuleHandle(NULL);
|
||||||
|
wndclass.hIcon = 0;
|
||||||
|
wndclass.hCursor = LoadCursor(0, IDC_ARROW);
|
||||||
|
wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
|
||||||
|
wndclass.lpszMenuName = NULL;
|
||||||
|
wndclass.lpszClassName = szFntPreview;
|
||||||
|
RegisterClass(&wndclass);
|
||||||
|
|
||||||
|
memset(&psp, 0, sizeof(psp));
|
||||||
|
psp.dwSize = sizeof(psp);
|
||||||
|
psp.dwFlags = 0;
|
||||||
|
psp.hInstance = wndclass.hInstance;
|
||||||
|
psp.lParam = (LPARAM)&di;
|
||||||
|
|
||||||
|
psp.u.pszTemplate = MAKEINTRESOURCEA(IDD_OPTION);
|
||||||
|
psp.pfnDlgProc = WCUSER_OptionDlgProc;
|
||||||
|
psPage[0] = CreatePropertySheetPageA(&psp);
|
||||||
|
|
||||||
|
psp.u.pszTemplate = MAKEINTRESOURCEA(IDD_FONT);
|
||||||
|
psp.pfnDlgProc = WCUSER_FontDlgProc;
|
||||||
|
psPage[1] = CreatePropertySheetPageA(&psp);
|
||||||
|
|
||||||
|
psp.u.pszTemplate = MAKEINTRESOURCEA(IDD_CONFIG);
|
||||||
|
psp.pfnDlgProc = WCUSER_ConfigDlgProc;
|
||||||
|
psPage[2] = CreatePropertySheetPageA(&psp);
|
||||||
|
|
||||||
|
memset(&psHead, 0, sizeof(psHead));
|
||||||
|
psHead.dwSize = sizeof(psHead);
|
||||||
|
psHead.pszCaption = "Setup";
|
||||||
|
psHead.nPages = 3;
|
||||||
|
psHead.hwndParent = data->hWnd;
|
||||||
|
psHead.u3.phpage = psPage;
|
||||||
|
|
||||||
|
PropertySheetA(&psHead);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,957 @@
|
||||||
|
/*
|
||||||
|
* a GUI application for displaying a console
|
||||||
|
* USER32 back end
|
||||||
|
* Copyright 2001 Eric Pouech
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "winecon_private.h"
|
||||||
|
|
||||||
|
/* mapping console colors to RGB values */
|
||||||
|
static COLORREF color_map[16] =
|
||||||
|
{
|
||||||
|
RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x80), RGB(0x00, 0x80, 0x00), RGB(0x00, 0x80, 0x80),
|
||||||
|
RGB(0x80, 0x00, 0x00), RGB(0x80, 0x00, 0x80), RGB(0x80, 0x80, 0x00), RGB(0x80, 0x80, 0x80),
|
||||||
|
RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xFF),
|
||||||
|
RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xFF),
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_FillMemDC
|
||||||
|
*
|
||||||
|
* Fills the Mem DC with current cells values
|
||||||
|
*/
|
||||||
|
static void WCUSER_FillMemDC(const struct inner_data* data, int upd_tp, int upd_bm)
|
||||||
|
{
|
||||||
|
unsigned i, j, k;
|
||||||
|
CHAR_INFO* cell;
|
||||||
|
HFONT hOldFont;
|
||||||
|
WORD attr;
|
||||||
|
WCHAR* line;
|
||||||
|
|
||||||
|
if (!(line = HeapAlloc(GetProcessHeap(), 0, data->sb_width * sizeof(WCHAR))))
|
||||||
|
{Trace(0, "OOM\n"); return;}
|
||||||
|
|
||||||
|
hOldFont = SelectObject(data->hMemDC, data->hFont);
|
||||||
|
for (j = upd_tp; j <= upd_bm; j++)
|
||||||
|
{
|
||||||
|
cell = &data->cells[j * data->sb_width];
|
||||||
|
for (i = 0; i < data->win_width; i++)
|
||||||
|
{
|
||||||
|
attr = cell[i].Attributes;
|
||||||
|
SetBkColor(data->hMemDC, color_map[attr & 0x0F]);
|
||||||
|
SetTextColor(data->hMemDC, color_map[(attr >> 4) & 0x0F]);
|
||||||
|
for (k = i; k < data->win_width && cell[k].Attributes == attr; k++)
|
||||||
|
{
|
||||||
|
line[k - i] = cell[k].Char.UnicodeChar;
|
||||||
|
}
|
||||||
|
TextOut(data->hMemDC, i * data->cell_width, j * data->cell_height,
|
||||||
|
line, k - i);
|
||||||
|
i = k - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectObject(data->hMemDC, hOldFont);
|
||||||
|
HeapFree(GetProcessHeap(), 0, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_NewBitmap
|
||||||
|
*
|
||||||
|
* Either the font geometry or the sb geometry has changed. we need to recreate the
|
||||||
|
* bitmap geometry
|
||||||
|
*/
|
||||||
|
static void WCUSER_NewBitmap(struct inner_data* data, BOOL fill)
|
||||||
|
{
|
||||||
|
HBITMAP hnew, hold;
|
||||||
|
|
||||||
|
if (!data->sb_width || !data->sb_height)
|
||||||
|
return;
|
||||||
|
hnew = CreateCompatibleBitmap(data->hMemDC,
|
||||||
|
data->sb_width * data->cell_width,
|
||||||
|
data->sb_height * data->cell_height);
|
||||||
|
hold = SelectObject(data->hMemDC, hnew);
|
||||||
|
|
||||||
|
if (data->hBitmap)
|
||||||
|
{
|
||||||
|
if (hold == data->hBitmap)
|
||||||
|
DeleteObject(data->hBitmap);
|
||||||
|
else
|
||||||
|
Trace(0, "leak\n");
|
||||||
|
}
|
||||||
|
data->hBitmap = hnew;
|
||||||
|
if (fill)
|
||||||
|
WCUSER_FillMemDC(data, 0, data->sb_height - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_ResizeScreenBuffer
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void WCUSER_ResizeScreenBuffer(struct inner_data* data)
|
||||||
|
{
|
||||||
|
WCUSER_NewBitmap(data, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_PosCursor
|
||||||
|
*
|
||||||
|
* Set a new position for the cursor
|
||||||
|
*/
|
||||||
|
static void WCUSER_PosCursor(const struct inner_data* data)
|
||||||
|
{
|
||||||
|
if (data->hWnd != GetFocus() || !data->cursor_visible) return;
|
||||||
|
|
||||||
|
SetCaretPos((data->cursor.X - data->win_pos.X) * data->cell_width,
|
||||||
|
(data->cursor.Y - data->win_pos.Y) * data->cell_height);
|
||||||
|
ShowCaret(data->hWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_ShapeCursor
|
||||||
|
*
|
||||||
|
* Sets a new shape for the cursor
|
||||||
|
*/
|
||||||
|
void WCUSER_ShapeCursor(struct inner_data* data, int size, int vis, BOOL force)
|
||||||
|
{
|
||||||
|
if (force || size != data->cursor_size)
|
||||||
|
{
|
||||||
|
if (data->cursor_visible && data->hWnd == GetFocus()) DestroyCaret();
|
||||||
|
if (data->cursor_bitmap) DeleteObject(data->cursor_bitmap);
|
||||||
|
data->cursor_bitmap = (HBITMAP)0;
|
||||||
|
if (size != 100)
|
||||||
|
{
|
||||||
|
int w16b; /* number of byets per row, aligned on word size */
|
||||||
|
BYTE* ptr;
|
||||||
|
int i, j, nbl;
|
||||||
|
|
||||||
|
w16b = ((data->cell_width + 15) & ~15) / 8;
|
||||||
|
ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, w16b * data->cell_height);
|
||||||
|
if (!ptr) {Trace(0, "OOM\n"); return;}
|
||||||
|
nbl = max((data->cell_height * size) / 100, 1);
|
||||||
|
for (j = data->cell_height - nbl; j < data->cell_height; j++)
|
||||||
|
{
|
||||||
|
for (i = 0; i < data->cell_width; i++)
|
||||||
|
{
|
||||||
|
ptr[w16b * j + (i / 8)] |= 0x80 >> (i & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data->cursor_bitmap = CreateBitmap(data->cell_width, data->cell_height, 1, 1, ptr);
|
||||||
|
HeapFree(GetProcessHeap(), 0, ptr);
|
||||||
|
}
|
||||||
|
data->cursor_size = size;
|
||||||
|
data->cursor_visible = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vis = (vis) ? TRUE : FALSE;
|
||||||
|
if (force || vis != data->cursor_visible)
|
||||||
|
{
|
||||||
|
data->cursor_visible = vis;
|
||||||
|
if (data->hWnd == GetFocus())
|
||||||
|
{
|
||||||
|
if (vis)
|
||||||
|
{
|
||||||
|
CreateCaret(data->hWnd, data->cursor_bitmap, data->cell_width, data->cell_height);
|
||||||
|
WCUSER_PosCursor(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DestroyCaret();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* INECON_ComputePositions
|
||||||
|
*
|
||||||
|
* Recomputes all the components (mainly scroll bars) positions
|
||||||
|
*/
|
||||||
|
void WCUSER_ComputePositions(struct inner_data* data)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
int dx, dy;
|
||||||
|
|
||||||
|
/* compute window size from desired client size */
|
||||||
|
r.left = r.top = 0;
|
||||||
|
r.right = data->win_width * data->cell_width;
|
||||||
|
r.bottom = data->win_height * data->cell_height;
|
||||||
|
|
||||||
|
if (IsRectEmpty(&r))
|
||||||
|
{
|
||||||
|
ShowWindow(data->hWnd, SW_HIDE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdjustWindowRect(&r, GetWindowLong(data->hWnd, GWL_STYLE), FALSE);
|
||||||
|
|
||||||
|
dx = dy = 0;
|
||||||
|
if (data->sb_width > data->win_width)
|
||||||
|
{
|
||||||
|
dy = GetSystemMetrics(SM_CYHSCROLL);
|
||||||
|
SetScrollRange(data->hWnd, SB_HORZ, 0, data->sb_width - data->win_width, FALSE);
|
||||||
|
SetScrollPos(data->hWnd, SB_HORZ, 0, FALSE); /* FIXME */
|
||||||
|
ShowScrollBar(data->hWnd, SB_HORZ, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShowScrollBar(data->hWnd, SB_HORZ, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->sb_height > data->win_height)
|
||||||
|
{
|
||||||
|
dx = GetSystemMetrics(SM_CXVSCROLL);
|
||||||
|
SetScrollRange(data->hWnd, SB_VERT, 0, data->sb_height - data->win_height, FALSE);
|
||||||
|
SetScrollPos(data->hWnd, SB_VERT, 0, FALSE); /* FIXME */
|
||||||
|
ShowScrollBar(data->hWnd, SB_VERT, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShowScrollBar(data->hWnd, SB_VERT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(data->hWnd, 0, 0, 0, r.right - r.left + dx, r.bottom - r.top + dy,
|
||||||
|
SWP_NOMOVE|SWP_NOZORDER|SWP_SHOWWINDOW);
|
||||||
|
WCUSER_ShapeCursor(data, data->cursor_size, data->cursor_visible, TRUE);
|
||||||
|
WCUSER_PosCursor(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_SetTitle
|
||||||
|
*
|
||||||
|
* Sets the title to the wine console
|
||||||
|
*/
|
||||||
|
static void WCUSER_SetTitle(const struct inner_data* data)
|
||||||
|
{
|
||||||
|
WCHAR buffer[256];
|
||||||
|
|
||||||
|
if (WINECON_GetConsoleTitle(data->hConIn, buffer, sizeof(buffer)))
|
||||||
|
SetWindowText(data->hWnd, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_SetFont
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WCUSER_SetFont(struct inner_data* data, const LOGFONT* logfont, const TEXTMETRIC* tm)
|
||||||
|
{
|
||||||
|
if (!memcmp(logfont, &data->logFont, sizeof(LOGFONT))) return TRUE;
|
||||||
|
if (data->hFont) DeleteObject(data->hFont);
|
||||||
|
data->hFont = CreateFontIndirect(logfont);
|
||||||
|
if (!data->hFont) {Trace(0, "wrong font\n");return FALSE;}
|
||||||
|
data->cell_width = tm->tmMaxCharWidth; /* font is fixed Avg == Max */
|
||||||
|
data->cell_height = tm->tmHeight;
|
||||||
|
data->logFont = *logfont;
|
||||||
|
WCUSER_ComputePositions(data);
|
||||||
|
WCUSER_NewBitmap(data, TRUE);
|
||||||
|
InvalidateRect(data->hWnd, NULL, FALSE);
|
||||||
|
UpdateWindow(data->hWnd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_GetCell
|
||||||
|
*
|
||||||
|
* Get a cell from the a relative coordinate in window (takes into
|
||||||
|
* account the scrolling)
|
||||||
|
*/
|
||||||
|
static COORD WCUSER_GetCell(const struct inner_data* data, LPARAM lParam)
|
||||||
|
{
|
||||||
|
COORD c;
|
||||||
|
|
||||||
|
c.X = data->win_pos.X + (short)LOWORD(lParam) / data->cell_width;
|
||||||
|
c.Y = data->win_pos.Y + (short)HIWORD(lParam) / data->cell_height;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_GetSelectionRect
|
||||||
|
*
|
||||||
|
* Get the selection rectangle
|
||||||
|
*/
|
||||||
|
static void WCUSER_GetSelectionRect(const struct inner_data* data, LPRECT r)
|
||||||
|
{
|
||||||
|
r->left = (min(data->selectPt1.X, data->selectPt2.X) ) * data->cell_width;
|
||||||
|
r->top = (min(data->selectPt1.Y, data->selectPt2.Y) ) * data->cell_height;
|
||||||
|
r->right = (max(data->selectPt1.X, data->selectPt2.X) + 1) * data->cell_width;
|
||||||
|
r->bottom = (max(data->selectPt1.Y, data->selectPt2.Y) + 1) * data->cell_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_SetSelection
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void WCUSER_SetSelection(const struct inner_data* data, HDC hRefDC)
|
||||||
|
{
|
||||||
|
HDC hDC;
|
||||||
|
RECT r;
|
||||||
|
|
||||||
|
WCUSER_GetSelectionRect(data, &r);
|
||||||
|
hDC = hRefDC ? hRefDC : GetDC(data->hWnd);
|
||||||
|
if (hDC)
|
||||||
|
{
|
||||||
|
if (data->hWnd == GetFocus() && data->cursor_visible)
|
||||||
|
HideCaret(data->hWnd);
|
||||||
|
InvertRect(hDC, &r);
|
||||||
|
if (hDC != hRefDC)
|
||||||
|
ReleaseDC(data->hWnd, hDC);
|
||||||
|
if (data->hWnd == GetFocus() && data->cursor_visible)
|
||||||
|
ShowCaret(data->hWnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_MoveSelection
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void WCUSER_MoveSelection(struct inner_data* data, COORD dst, BOOL final)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
HDC hDC;
|
||||||
|
|
||||||
|
WCUSER_GetSelectionRect(data, &r);
|
||||||
|
hDC = GetDC(data->hWnd);
|
||||||
|
if (hDC)
|
||||||
|
{
|
||||||
|
if (data->hWnd == GetFocus() && data->cursor_visible)
|
||||||
|
HideCaret(data->hWnd);
|
||||||
|
InvertRect(hDC, &r);
|
||||||
|
}
|
||||||
|
data->selectPt2 = dst;
|
||||||
|
if (hDC)
|
||||||
|
{
|
||||||
|
WCUSER_GetSelectionRect(data, &r);
|
||||||
|
InvertRect(hDC, &r);
|
||||||
|
ReleaseDC(data->hWnd, hDC);
|
||||||
|
if (data->hWnd == GetFocus() && data->cursor_visible)
|
||||||
|
ShowCaret(data->hWnd);
|
||||||
|
}
|
||||||
|
if (final)
|
||||||
|
{
|
||||||
|
ReleaseCapture();
|
||||||
|
data->hasSelection = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_CopySelectionToClipboard
|
||||||
|
*
|
||||||
|
* Copies the current selection into the clipboard
|
||||||
|
*/
|
||||||
|
static void WCUSER_CopySelectionToClipboard(const struct inner_data* data)
|
||||||
|
{
|
||||||
|
HANDLE hMem;
|
||||||
|
LPWSTR p;
|
||||||
|
unsigned w, h;
|
||||||
|
|
||||||
|
w = abs(data->selectPt1.X - data->selectPt2.X) + 2;
|
||||||
|
h = abs(data->selectPt1.Y - data->selectPt2.Y) + 1;
|
||||||
|
|
||||||
|
if (!OpenClipboard(data->hWnd)) return;
|
||||||
|
EmptyClipboard();
|
||||||
|
|
||||||
|
hMem = GlobalAlloc(GMEM_MOVEABLE, (w * h - 1) * sizeof(WCHAR));
|
||||||
|
if (hMem && (p = GlobalLock(hMem)))
|
||||||
|
{
|
||||||
|
COORD c;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
c.X = data->win_pos.X + min(data->selectPt1.X, data->selectPt2.X);
|
||||||
|
c.Y = data->win_pos.Y + min(data->selectPt1.Y, data->selectPt2.Y);
|
||||||
|
|
||||||
|
for (y = 0; y < h; y++, c.Y++)
|
||||||
|
{
|
||||||
|
ReadConsoleOutputCharacter(data->hConOut, &p[y * w], w - 1, c, NULL);
|
||||||
|
if (y < h - 1) p[y * w + w - 1] = '\n';
|
||||||
|
}
|
||||||
|
GlobalUnlock(hMem);
|
||||||
|
SetClipboardData(CF_UNICODETEXT, hMem);
|
||||||
|
}
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_PasteFromClipboard
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void WCUSER_PasteFromClipboard(struct inner_data* data)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
WCHAR* ptr;
|
||||||
|
|
||||||
|
if (!OpenClipboard(data->hWnd)) return;
|
||||||
|
h = GetClipboardData(CF_UNICODETEXT);
|
||||||
|
if (h && (ptr = GlobalLock(h)))
|
||||||
|
{
|
||||||
|
int i, len = GlobalSize(h) / sizeof(WCHAR);
|
||||||
|
INPUT_RECORD ir[2];
|
||||||
|
DWORD n;
|
||||||
|
SHORT sh;
|
||||||
|
|
||||||
|
ir[0].EventType = KEY_EVENT;
|
||||||
|
ir[0].Event.KeyEvent.wRepeatCount = 0;
|
||||||
|
ir[0].Event.KeyEvent.dwControlKeyState = 0;
|
||||||
|
ir[0].Event.KeyEvent.bKeyDown = TRUE;
|
||||||
|
|
||||||
|
/* generate the corresponding input records */
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
/* FIXME: the modifying keys are not generated (shift, ctrl...) */
|
||||||
|
sh = VkKeyScan(ptr[i]);
|
||||||
|
ir[0].Event.KeyEvent.wVirtualKeyCode = LOBYTE(sh);
|
||||||
|
ir[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(LOBYTE(sh), 0);
|
||||||
|
ir[0].Event.KeyEvent.uChar.UnicodeChar = ptr[i];
|
||||||
|
|
||||||
|
ir[1] = ir[0];
|
||||||
|
ir[1].Event.KeyEvent.bKeyDown = FALSE;
|
||||||
|
|
||||||
|
WriteConsoleInput(data->hConIn, ir, 2, &n);
|
||||||
|
}
|
||||||
|
GlobalUnlock(h);
|
||||||
|
}
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCUSER_Refresh(const struct inner_data* data, int tp, int bm)
|
||||||
|
{
|
||||||
|
if (data->win_pos.Y <= bm && data->win_pos.Y + data->win_height >= tp)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
|
||||||
|
r.left = 0;
|
||||||
|
r.right = data->win_width * data->cell_width;
|
||||||
|
r.top = (tp - data->win_pos.Y) * data->cell_height;
|
||||||
|
r.bottom = (bm - data->win_pos.Y + 1) * data->cell_height;
|
||||||
|
InvalidateRect(data->hWnd, &r, FALSE);
|
||||||
|
WCUSER_FillMemDC(data, tp, bm);
|
||||||
|
UpdateWindow(data->hWnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_Paint
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void WCUSER_Paint(const struct inner_data* data)
|
||||||
|
{
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
|
||||||
|
BeginPaint(data->hWnd, &ps);
|
||||||
|
BitBlt(ps.hdc, 0, 0, data->win_width * data->cell_width, data->win_height * data->cell_height,
|
||||||
|
data->hMemDC, data->win_pos.X * data->cell_width, data->win_pos.Y * data->cell_height,
|
||||||
|
SRCCOPY);
|
||||||
|
if (data->hasSelection)
|
||||||
|
WCUSER_SetSelection(data, ps.hdc);
|
||||||
|
EndPaint(data->hWnd, &ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_Scroll
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void WCUSER_Scroll(struct inner_data* data, int pos, BOOL horz)
|
||||||
|
{
|
||||||
|
if (horz)
|
||||||
|
{
|
||||||
|
SetScrollPos(data->hWnd, SB_HORZ, pos, TRUE);
|
||||||
|
data->win_pos.X = pos;
|
||||||
|
InvalidateRect(data->hWnd, NULL, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetScrollPos(data->hWnd, SB_VERT, pos, TRUE);
|
||||||
|
data->win_pos.Y = pos;
|
||||||
|
}
|
||||||
|
InvalidateRect(data->hWnd, NULL, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct font_chooser {
|
||||||
|
struct inner_data* data;
|
||||||
|
int done;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_ValidateFontMetric
|
||||||
|
*
|
||||||
|
* Returns true if the font described in tm is usable as a font for the renderer
|
||||||
|
*/
|
||||||
|
BOOL WCUSER_ValidateFontMetric(const struct inner_data* data, const TEXTMETRIC* tm)
|
||||||
|
{
|
||||||
|
return tm->tmMaxCharWidth * data->win_width < GetSystemMetrics(SM_CXSCREEN) &&
|
||||||
|
tm->tmHeight * data->win_height < GetSystemMetrics(SM_CYSCREEN) &&
|
||||||
|
!tm->tmItalic && !tm->tmUnderlined && !tm->tmStruckOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_ValidateFont
|
||||||
|
*
|
||||||
|
* Returns true if the font family described in lf is usable as a font for the renderer
|
||||||
|
*/
|
||||||
|
BOOL WCUSER_ValidateFont(const struct inner_data* data, const LOGFONT* lf)
|
||||||
|
{
|
||||||
|
return (lf->lfPitchAndFamily & 3) == FIXED_PITCH && (lf->lfPitchAndFamily & 0xF0) == FF_MODERN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* get_first_font_enum_2
|
||||||
|
* get_first_font_enum
|
||||||
|
*
|
||||||
|
* Helper functions to get a decent font for the renderer
|
||||||
|
*/
|
||||||
|
static int CALLBACK get_first_font_enum_2(const LOGFONT* lf, const TEXTMETRIC* tm,
|
||||||
|
DWORD FontType, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct font_chooser* fc = (struct font_chooser*)lParam;
|
||||||
|
|
||||||
|
if (WCUSER_ValidateFontMetric(fc->data, tm))
|
||||||
|
{
|
||||||
|
WCUSER_SetFont(fc->data, lf, tm);
|
||||||
|
fc->done = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CALLBACK get_first_font_enum(const LOGFONT* lf, const TEXTMETRIC* tm,
|
||||||
|
DWORD FontType, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct font_chooser* fc = (struct font_chooser*)lParam;
|
||||||
|
|
||||||
|
if (WCUSER_ValidateFont(fc->data, lf))
|
||||||
|
{
|
||||||
|
EnumFontFamilies(fc->data->hMemDC, lf->lfFaceName, get_first_font_enum_2, lParam);
|
||||||
|
return !fc->done; /* we just need the first matching one... */
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_Create
|
||||||
|
*
|
||||||
|
* Creates the window for the rendering
|
||||||
|
*/
|
||||||
|
static LRESULT WCUSER_Create(HWND hWnd, LPCREATESTRUCT lpcs)
|
||||||
|
{
|
||||||
|
struct inner_data* data;
|
||||||
|
HMENU hMenu;
|
||||||
|
HMENU hSubMenu;
|
||||||
|
WCHAR buff[256];
|
||||||
|
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||||
|
|
||||||
|
data = lpcs->lpCreateParams;
|
||||||
|
SetWindowLong(hWnd, 0L, (DWORD)data);
|
||||||
|
data->hWnd = hWnd;
|
||||||
|
|
||||||
|
data->cursor_size = 101; /* invalid value, will trigger a complete cleanup */
|
||||||
|
/* FIXME: error handling & memory cleanup */
|
||||||
|
hSubMenu = CreateMenu();
|
||||||
|
if (!hSubMenu) return 0;
|
||||||
|
|
||||||
|
hMenu = GetSystemMenu(hWnd, FALSE);
|
||||||
|
if (!hMenu) return 0;
|
||||||
|
|
||||||
|
LoadString(hInstance, IDS_MARK, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hSubMenu, -1, MF_BYPOSITION|MF_STRING, IDS_MARK, buff);
|
||||||
|
LoadString(hInstance, IDS_COPY, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hSubMenu, -1, MF_BYPOSITION|MF_STRING, IDS_COPY, buff);
|
||||||
|
LoadString(hInstance, IDS_PASTE, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hSubMenu, -1, MF_BYPOSITION|MF_STRING, IDS_PASTE, buff);
|
||||||
|
LoadString(hInstance, IDS_SELECTALL, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hSubMenu, -1, MF_BYPOSITION|MF_STRING, IDS_SELECTALL, buff);
|
||||||
|
LoadString(hInstance, IDS_SCROLL, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hSubMenu, -1, MF_BYPOSITION|MF_STRING, IDS_SCROLL, buff);
|
||||||
|
LoadString(hInstance, IDS_SEARCH, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hSubMenu, -1, MF_BYPOSITION|MF_STRING, IDS_SEARCH, buff);
|
||||||
|
|
||||||
|
InsertMenu(hMenu, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
|
||||||
|
LoadString(hInstance, IDS_EDIT, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hMenu, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR)hSubMenu, buff);
|
||||||
|
LoadString(hInstance, IDS_DEFAULT, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hMenu, -1, MF_BYPOSITION|MF_STRING, IDS_DEFAULT, buff);
|
||||||
|
LoadString(hInstance, IDS_PROPERTY, buff, sizeof(buff) / sizeof(WCHAR));
|
||||||
|
InsertMenu(hMenu, -1, MF_BYPOSITION|MF_STRING, IDS_PROPERTY, buff);
|
||||||
|
|
||||||
|
data->hMemDC = CreateCompatibleDC(0);
|
||||||
|
if (!data->hMemDC) {Trace(0, "no mem dc\n");return 0;}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_SetMenuDetails
|
||||||
|
*
|
||||||
|
* Grays / ungrays the menu items according to their state
|
||||||
|
*/
|
||||||
|
static void WCUSER_SetMenuDetails(const struct inner_data* data)
|
||||||
|
{
|
||||||
|
HMENU hMenu = GetSystemMenu(data->hWnd, FALSE);
|
||||||
|
|
||||||
|
if (!hMenu) {Trace(0, "Issue in getting menu bits\n");return;}
|
||||||
|
|
||||||
|
/* FIXME: set the various menu items to their state (if known) */
|
||||||
|
EnableMenuItem(hMenu, IDS_DEFAULT, MF_BYCOMMAND|MF_GRAYED);
|
||||||
|
|
||||||
|
EnableMenuItem(hMenu, IDS_MARK, MF_BYCOMMAND|MF_GRAYED);
|
||||||
|
EnableMenuItem(hMenu, IDS_COPY, MF_BYCOMMAND|(data->hasSelection ? MF_ENABLED : MF_GRAYED));
|
||||||
|
EnableMenuItem(hMenu, IDS_PASTE,
|
||||||
|
MF_BYCOMMAND|(IsClipboardFormatAvailable(CF_UNICODETEXT)
|
||||||
|
? MF_ENABLED : MF_GRAYED));
|
||||||
|
/* Select all: always active */
|
||||||
|
EnableMenuItem(hMenu, IDS_SCROLL, MF_BYCOMMAND|MF_GRAYED);
|
||||||
|
EnableMenuItem(hMenu, IDS_SEARCH, MF_BYCOMMAND|MF_GRAYED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_GenerateInputRecord
|
||||||
|
*
|
||||||
|
* generates input_record from windows WM_KEYUP/WM_KEYDOWN messages
|
||||||
|
*/
|
||||||
|
static void WCUSER_GenerateInputRecord(struct inner_data* data, BOOL down,
|
||||||
|
WPARAM wParam, LPARAM lParam, BOOL sys)
|
||||||
|
{
|
||||||
|
INPUT_RECORD ir;
|
||||||
|
DWORD n;
|
||||||
|
WCHAR buf[2];
|
||||||
|
BYTE keyState[256];
|
||||||
|
static WCHAR last; /* keep last char seen as feed for key up message */
|
||||||
|
|
||||||
|
ir.EventType = KEY_EVENT;
|
||||||
|
ir.Event.KeyEvent.bKeyDown = down;
|
||||||
|
ir.Event.KeyEvent.wRepeatCount = LOWORD(lParam);
|
||||||
|
ir.Event.KeyEvent.wVirtualKeyCode = wParam;
|
||||||
|
|
||||||
|
ir.Event.KeyEvent.wVirtualScanCode = HIWORD(lParam) & 0xFF;
|
||||||
|
GetKeyboardState(keyState);
|
||||||
|
|
||||||
|
ir.Event.KeyEvent.uChar.UnicodeChar = 0;
|
||||||
|
ir.Event.KeyEvent.dwControlKeyState = 0;
|
||||||
|
if (lParam & (1L << 24)) ir.Event.KeyEvent.dwControlKeyState |= ENHANCED_KEY;
|
||||||
|
if (keyState[VK_SHIFT] & 0x80) ir.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
|
||||||
|
if (keyState[VK_CONTROL] & 0x80) ir.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; /* FIXME: gotta choose one */
|
||||||
|
if (keyState[VK_LCONTROL] & 0x80) ir.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED;
|
||||||
|
if (keyState[VK_RCONTROL] & 0x80) ir.Event.KeyEvent.dwControlKeyState |= RIGHT_CTRL_PRESSED;
|
||||||
|
if (sys) ir.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED; /* FIXME: gotta choose one */
|
||||||
|
if (keyState[VK_LMENU] & 0x80) ir.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED;
|
||||||
|
if (keyState[VK_RMENU] & 0x80) ir.Event.KeyEvent.dwControlKeyState |= RIGHT_ALT_PRESSED;
|
||||||
|
if (keyState[VK_CAPITAL] & 0x01) ir.Event.KeyEvent.dwControlKeyState |= CAPSLOCK_ON;
|
||||||
|
if (keyState[VK_NUMLOCK] & 0x01) ir.Event.KeyEvent.dwControlKeyState |= NUMLOCK_ON;
|
||||||
|
if (keyState[VK_SCROLL] & 0x01) ir.Event.KeyEvent.dwControlKeyState |= SCROLLLOCK_ON;
|
||||||
|
|
||||||
|
if (data->hasSelection && ir.Event.KeyEvent.dwControlKeyState == 0 &&
|
||||||
|
ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN)
|
||||||
|
{
|
||||||
|
data->hasSelection = FALSE;
|
||||||
|
WCUSER_SetSelection(data, 0);
|
||||||
|
WCUSER_CopySelectionToClipboard(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ir.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY))
|
||||||
|
{
|
||||||
|
if (down)
|
||||||
|
{
|
||||||
|
switch (ToUnicode(wParam, HIWORD(lParam), keyState, buf, 2, 0))
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
/* FIXME... should generate two events... */
|
||||||
|
/* fall thru */
|
||||||
|
case 1:
|
||||||
|
last = buf[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
last = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir.Event.KeyEvent.uChar.UnicodeChar = last; /* FIXME HACKY... and buggy 'coz it should be a stack, not a single value */
|
||||||
|
if (!down) last = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteConsoleInput(data->hConIn, &ir, 1, &n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_Proc
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static LRESULT CALLBACK WCUSER_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct inner_data* data = (struct inner_data*)GetWindowLong(hWnd, 0);
|
||||||
|
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
case WM_CREATE:
|
||||||
|
return WCUSER_Create(hWnd, (LPCREATESTRUCT)lParam);
|
||||||
|
case WM_DESTROY:
|
||||||
|
data->hWnd = 0;
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
case WM_PAINT:
|
||||||
|
WCUSER_Paint(data);
|
||||||
|
break;
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
WCUSER_GenerateInputRecord(data, uMsg == WM_KEYDOWN, wParam, lParam, FALSE);
|
||||||
|
break;
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
WCUSER_GenerateInputRecord(data, uMsg == WM_SYSKEYDOWN, wParam, lParam, TRUE);
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
/* EPP if (wParam != MK_LBUTTON) */
|
||||||
|
if (data->hasSelection)
|
||||||
|
{
|
||||||
|
data->hasSelection = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data->selectPt1 = data->selectPt2 = WCUSER_GetCell(data, lParam);
|
||||||
|
SetCapture(data->hWnd);
|
||||||
|
}
|
||||||
|
WCUSER_SetSelection(data, 0);
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
/* EPP if (wParam != MK_LBUTTON) */
|
||||||
|
if (GetCapture() == data->hWnd)
|
||||||
|
{
|
||||||
|
WCUSER_MoveSelection(data, WCUSER_GetCell(data, lParam), FALSE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
/* EPP if (wParam != MK_LBUTTON) */
|
||||||
|
if (GetCapture() == data->hWnd)
|
||||||
|
{
|
||||||
|
WCUSER_MoveSelection(data, WCUSER_GetCell(data, lParam), TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
if (data->cursor_visible)
|
||||||
|
{
|
||||||
|
CreateCaret(data->hWnd, data->cursor_bitmap, data->cell_width, data->cell_height);
|
||||||
|
WCUSER_PosCursor(data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_KILLFOCUS:
|
||||||
|
if (data->cursor_visible)
|
||||||
|
DestroyCaret();
|
||||||
|
break;
|
||||||
|
case WM_HSCROLL:
|
||||||
|
{
|
||||||
|
int pos = data->win_pos.X;
|
||||||
|
|
||||||
|
switch (LOWORD(wParam))
|
||||||
|
{
|
||||||
|
case SB_PAGEUP: pos -= 8; break;
|
||||||
|
case SB_PAGEDOWN: pos += 8; break;
|
||||||
|
case SB_LINEUP: pos--; break;
|
||||||
|
case SB_LINEDOWN: pos++; break;
|
||||||
|
case SB_THUMBTRACK: pos = HIWORD(wParam); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (pos < 0) pos = 0;
|
||||||
|
if (pos > data->sb_width - data->win_width) pos = data->sb_width - data->win_width;
|
||||||
|
if (pos != data->win_pos.X)
|
||||||
|
{
|
||||||
|
ScrollWindow(hWnd, (data->win_pos.X - pos) * data->cell_width, 0, NULL, NULL);
|
||||||
|
data->win_pos.X = pos;
|
||||||
|
SetScrollPos(hWnd, SB_HORZ, pos, TRUE);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
WCUSER_PosCursor(data);
|
||||||
|
WINECON_NotifyWindowChange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_VSCROLL:
|
||||||
|
{
|
||||||
|
int pos = data->win_pos.Y;
|
||||||
|
|
||||||
|
switch (LOWORD(wParam))
|
||||||
|
{
|
||||||
|
case SB_PAGEUP: pos -= 8; break;
|
||||||
|
case SB_PAGEDOWN: pos += 8; break;
|
||||||
|
case SB_LINEUP: pos--; break;
|
||||||
|
case SB_LINEDOWN: pos++; break;
|
||||||
|
case SB_THUMBTRACK: pos = HIWORD(wParam); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (pos < 0) pos = 0;
|
||||||
|
if (pos > data->sb_height - data->win_height) pos = data->sb_height - data->win_height;
|
||||||
|
if (pos != data->win_pos.Y)
|
||||||
|
{
|
||||||
|
ScrollWindow(hWnd, 0, (data->win_pos.Y - pos) * data->cell_height, NULL, NULL);
|
||||||
|
data->win_pos.Y = pos;
|
||||||
|
SetScrollPos(hWnd, SB_VERT, pos, TRUE);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
WCUSER_PosCursor(data);
|
||||||
|
WINECON_NotifyWindowChange(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_SYSCOMMAND:
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case IDS_DEFAULT:
|
||||||
|
Trace(0, "unhandled yet command: %x\n", wParam);
|
||||||
|
break;
|
||||||
|
case IDS_PROPERTY:
|
||||||
|
WCUSER_GetProperties(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
WCUSER_GetProperties(data);
|
||||||
|
break;
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case IDS_MARK:
|
||||||
|
goto niy;
|
||||||
|
case IDS_COPY:
|
||||||
|
data->hasSelection = FALSE;
|
||||||
|
WCUSER_SetSelection(data, 0);
|
||||||
|
WCUSER_CopySelectionToClipboard(data);
|
||||||
|
break;
|
||||||
|
case IDS_PASTE:
|
||||||
|
WCUSER_PasteFromClipboard(data);
|
||||||
|
break;
|
||||||
|
case IDS_SELECTALL:
|
||||||
|
data->selectPt1.X = data->selectPt1.Y = 0;
|
||||||
|
data->selectPt2.X = (data->sb_width - 1) * data->cell_width;
|
||||||
|
data->selectPt2.Y = (data->sb_height - 1) * data->cell_height;
|
||||||
|
WCUSER_SetSelection(data, 0);
|
||||||
|
data->hasSelection = TRUE;
|
||||||
|
break;
|
||||||
|
case IDS_SCROLL:
|
||||||
|
case IDS_SEARCH:
|
||||||
|
niy:
|
||||||
|
Trace(0, "unhandled yet command: %x\n", wParam);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_INITMENUPOPUP:
|
||||||
|
if (!HIWORD(lParam)) return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
WCUSER_SetMenuDetails(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_DeleteBackend
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void WCUSER_DeleteBackend(struct inner_data* data)
|
||||||
|
{
|
||||||
|
if (data->hWnd) DestroyWindow(data->hWnd);
|
||||||
|
if (data->hFont) DeleteObject(data->hFont);
|
||||||
|
if (data->cursor_bitmap) DeleteObject(data->cursor_bitmap);
|
||||||
|
if (data->hMemDC) DeleteDC(data->hMemDC);
|
||||||
|
if (data->hBitmap) DeleteObject(data->hBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_MainLoop
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int WCUSER_MainLoop(struct inner_data* data)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
switch (MsgWaitForMultipleObjects(1, &data->hSynchro, FALSE, INFINITE, QS_ALLINPUT))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
if (!WINECON_GrabChanges(data))
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
case WAIT_OBJECT_0+1:
|
||||||
|
switch (GetMessage(&msg, 0, 0, 0))
|
||||||
|
{
|
||||||
|
case -1: /* the event handle became invalid, so exit */
|
||||||
|
return -1;
|
||||||
|
case 0: /* WM_QUIT has been posted */
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Trace(0, "got pb\n");
|
||||||
|
/* err */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WCUSER_InitBackend
|
||||||
|
*
|
||||||
|
* Initialisation part II: creation of window.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WCUSER_InitBackend(struct inner_data* data)
|
||||||
|
{
|
||||||
|
static WCHAR wClassName[] = {'W','i','n','e','C','o','n','s','o','l','e','C','l','a','s','s',0};
|
||||||
|
|
||||||
|
WNDCLASS wndclass;
|
||||||
|
struct font_chooser fc;
|
||||||
|
|
||||||
|
data->fnMainLoop = WCUSER_MainLoop;
|
||||||
|
data->fnPosCursor = WCUSER_PosCursor;
|
||||||
|
data->fnShapeCursor = WCUSER_ShapeCursor;
|
||||||
|
data->fnComputePositions = WCUSER_ComputePositions;
|
||||||
|
data->fnRefresh = WCUSER_Refresh;
|
||||||
|
data->fnResizeScreenBuffer = WCUSER_ResizeScreenBuffer;
|
||||||
|
data->fnSetTitle = WCUSER_SetTitle;
|
||||||
|
data->fnScroll = WCUSER_Scroll;
|
||||||
|
data->fnDeleteBackend = WCUSER_DeleteBackend;
|
||||||
|
|
||||||
|
wndclass.style = 0;
|
||||||
|
wndclass.lpfnWndProc = WCUSER_Proc;
|
||||||
|
wndclass.cbClsExtra = 0;
|
||||||
|
wndclass.cbWndExtra = sizeof(DWORD);
|
||||||
|
wndclass.hInstance = GetModuleHandle(NULL);
|
||||||
|
wndclass.hIcon = LoadIcon(0, IDI_WINLOGO);
|
||||||
|
wndclass.hCursor = LoadCursor(0, IDC_ARROW);
|
||||||
|
wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
|
||||||
|
wndclass.lpszMenuName = NULL;
|
||||||
|
wndclass.lpszClassName = wClassName;
|
||||||
|
|
||||||
|
RegisterClass(&wndclass);
|
||||||
|
|
||||||
|
CreateWindow(wndclass.lpszClassName, NULL,
|
||||||
|
WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_HSCROLL|WS_VSCROLL,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, 0, 0, wndclass.hInstance, data);
|
||||||
|
if (!data->hWnd) return FALSE;
|
||||||
|
|
||||||
|
/* force update of current data */
|
||||||
|
WINECON_GrabChanges(data);
|
||||||
|
|
||||||
|
/* try to find an acceptable font */
|
||||||
|
fc.data = data;
|
||||||
|
fc.done = 0;
|
||||||
|
EnumFontFamilies(data->hMemDC, NULL, get_first_font_enum, (LPARAM)&fc);
|
||||||
|
|
||||||
|
return fc.done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include <winbase.h>
|
||||||
|
#include <wingdi.h>
|
||||||
|
#include <winuser.h>
|
||||||
|
#include <wincon.h>
|
||||||
|
|
||||||
|
#include "wineconsole_res.h"
|
||||||
|
|
||||||
|
struct inner_data {
|
||||||
|
unsigned sb_width; /* active screen buffer width */
|
||||||
|
unsigned sb_height; /* active screen buffer height */
|
||||||
|
CHAR_INFO* cells; /* local copy of cells (sb_width * sb_height) */
|
||||||
|
COORD win_pos; /* position (in cells) of visible part of screen buffer in window */
|
||||||
|
unsigned win_width; /* size (in cells) of visible part of window (width & height) */
|
||||||
|
unsigned win_height;
|
||||||
|
|
||||||
|
COORD cursor; /* position in cells of cursor */
|
||||||
|
int cursor_visible;
|
||||||
|
int cursor_size; /* in % of cell height */
|
||||||
|
|
||||||
|
HANDLE hConIn; /* console input handle */
|
||||||
|
HANDLE hConOut; /* screen buffer handle: has to be changed when active sb changes */
|
||||||
|
HANDLE hSynchro; /* waitable handle signalled by server when something in server has been modified */
|
||||||
|
|
||||||
|
int (*fnMainLoop)(struct inner_data* data);
|
||||||
|
void (*fnPosCursor)(const struct inner_data* data);
|
||||||
|
void (*fnShapeCursor)(struct inner_data* data, int size, int vis, BOOL force);
|
||||||
|
void (*fnComputePositions)(struct inner_data* data);
|
||||||
|
void (*fnRefresh)(const struct inner_data* data, int tp, int bm);
|
||||||
|
void (*fnResizeScreenBuffer)(struct inner_data* data);
|
||||||
|
void (*fnSetTitle)(const struct inner_data* data);
|
||||||
|
void (*fnScroll)(struct inner_data* data, int pos, BOOL horz);
|
||||||
|
void (*fnDeleteBackend)(struct inner_data* data);
|
||||||
|
|
||||||
|
/* the following fields are only user by the USER backend (should be hidden in user) */
|
||||||
|
HWND hWnd; /* handle to windows for rendering */
|
||||||
|
HFONT hFont; /* font used for rendering, usually fixed */
|
||||||
|
LOGFONT logFont; /* logFont dscription for used hFont */
|
||||||
|
unsigned cell_width; /* width in pixels of a character */
|
||||||
|
unsigned cell_height; /* height in pixels of a character */
|
||||||
|
HDC hMemDC; /* memory DC holding the bitmap below */
|
||||||
|
HBITMAP hBitmap; /* bitmap of display window content */
|
||||||
|
|
||||||
|
HBITMAP cursor_bitmap; /* bitmap used for the caret */
|
||||||
|
BOOL hasSelection; /* a rectangular mouse selection has taken place */
|
||||||
|
COORD selectPt1; /* start (and end) point of a mouse selection */
|
||||||
|
COORD selectPt2;
|
||||||
|
};
|
||||||
|
|
||||||
|
# ifdef __GNUC__
|
||||||
|
extern void XTracer(int level, const char* format, ...) __attribute__((format (printf,2,3)));
|
||||||
|
# else
|
||||||
|
extern void XTracer(int level, const char* format, ...);
|
||||||
|
# endif
|
||||||
|
#if 0
|
||||||
|
/* Trace mode */
|
||||||
|
# define Trace XTracer
|
||||||
|
#else
|
||||||
|
/* non trace mode */
|
||||||
|
# define Trace (1) ? (void)0 : XTracer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void WINECON_NotifyWindowChange(struct inner_data* data);
|
||||||
|
extern int WINECON_GetHistorySize(HANDLE hConIn);
|
||||||
|
extern BOOL WINECON_SetHistorySize(HANDLE hConIn, int size);
|
||||||
|
extern int WINECON_GetHistoryMode(HANDLE hConIn);
|
||||||
|
extern BOOL WINECON_SetHistoryMode(HANDLE hConIn, int mode);
|
||||||
|
extern BOOL WINECON_GetConsoleTitle(HANDLE hConIn, WCHAR* buffer, size_t len);
|
||||||
|
extern void WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm);
|
||||||
|
extern int WINECON_GrabChanges(struct inner_data* data);
|
||||||
|
|
||||||
|
extern BOOL WCUSER_GetProperties(struct inner_data*);
|
||||||
|
extern BOOL WCUSER_SetFont(struct inner_data* data, const LOGFONT* font, const TEXTMETRIC* tm);
|
||||||
|
extern BOOL WCUSER_ValidateFont(const struct inner_data* data, const LOGFONT* lf);
|
||||||
|
extern BOOL WCUSER_ValidateFontMetric(const struct inner_data* data, const TEXTMETRIC* tm);
|
||||||
|
extern BOOL WCUSER_InitBackend(struct inner_data* data);
|
|
@ -0,0 +1,479 @@
|
||||||
|
/*
|
||||||
|
* an application for displaying Win32 console
|
||||||
|
*
|
||||||
|
* Copyright 2001 Eric Pouech
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wine/server.h>
|
||||||
|
#include "winecon_private.h"
|
||||||
|
|
||||||
|
static int trace_level = 1;
|
||||||
|
void XTracer(int level, const char* format, ...)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
va_list valist;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (level > trace_level) return;
|
||||||
|
|
||||||
|
va_start(valist, format);
|
||||||
|
len = wvsnprintfA(buf, sizeof(buf), format, valist);
|
||||||
|
va_end(valist);
|
||||||
|
|
||||||
|
if (len <= -1)
|
||||||
|
{
|
||||||
|
len = sizeof(buf) - 1;
|
||||||
|
buf[len] = 0;
|
||||||
|
buf[len - 1] = buf[len - 2] = buf[len - 3] = '.';
|
||||||
|
}
|
||||||
|
fprintf(stderr, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_FetchCells
|
||||||
|
*
|
||||||
|
* updates the local copy of cells (band to update)
|
||||||
|
*/
|
||||||
|
void WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm)
|
||||||
|
{
|
||||||
|
int step;
|
||||||
|
int j, nr;
|
||||||
|
|
||||||
|
step = REQUEST_MAX_VAR_SIZE / (data->sb_width * 4);
|
||||||
|
|
||||||
|
for (j = upd_tp; j <= upd_bm; j += step)
|
||||||
|
{
|
||||||
|
nr = min(step, upd_bm - j + 1);
|
||||||
|
SERVER_START_VAR_REQ( read_console_output, 4 * nr * data->sb_width )
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)data->hConOut;
|
||||||
|
req->x = 0;
|
||||||
|
req->y = j;
|
||||||
|
req->w = data->sb_width;
|
||||||
|
req->h = nr;
|
||||||
|
if (!SERVER_CALL_ERR())
|
||||||
|
{
|
||||||
|
if (data->sb_width != req->eff_w || nr != req->eff_h)
|
||||||
|
Trace(0, "pb here... wrong eff_w %d/%d or eff_h %d/%d\n",
|
||||||
|
req->eff_w, data->sb_width, req->eff_h, nr);
|
||||||
|
memcpy(&data->cells[j * data->sb_width], server_data_ptr(req),
|
||||||
|
4 * nr * data->sb_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SERVER_END_VAR_REQ;
|
||||||
|
}
|
||||||
|
data->fnRefresh(data, upd_tp, upd_bm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_NotifyWindowChange
|
||||||
|
*
|
||||||
|
* Inform server that visible window on sb has changed
|
||||||
|
*/
|
||||||
|
void WINECON_NotifyWindowChange(struct inner_data* data)
|
||||||
|
{
|
||||||
|
SERVER_START_REQ( set_console_output_info )
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)data->hConOut;
|
||||||
|
req->win_left = data->win_pos.X;
|
||||||
|
req->win_top = data->win_pos.Y;
|
||||||
|
req->win_right = data->win_pos.X + data->win_width - 1;
|
||||||
|
req->win_bottom = data->win_pos.Y + data->win_height - 1;
|
||||||
|
req->mask = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
|
||||||
|
if (!SERVER_CALL_ERR())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_GetHistorySize
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int WINECON_GetHistorySize(HANDLE hConIn)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
SERVER_START_REQ(get_console_input_info)
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)hConIn;
|
||||||
|
if (!SERVER_CALL_ERR()) ret = req->history_size;
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_SetHistorySize
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINECON_SetHistorySize(HANDLE hConIn, int size)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
SERVER_START_REQ(set_console_input_info)
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)hConIn;
|
||||||
|
req->mask = SET_CONSOLE_INPUT_INFO_HISTORY_SIZE;
|
||||||
|
req->history_size = size;
|
||||||
|
ret = !SERVER_CALL_ERR();
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_GetHistoryMode
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int WINECON_GetHistoryMode(HANDLE hConIn)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
SERVER_START_REQ(get_console_input_info)
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)hConIn;
|
||||||
|
if (!SERVER_CALL_ERR()) ret = req->history_mode;
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_SetHistoryMode
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINECON_SetHistoryMode(HANDLE hConIn, int mode)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
SERVER_START_REQ(set_console_input_info)
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)hConIn;
|
||||||
|
req->mask = SET_CONSOLE_INPUT_INFO_HISTORY_MODE;
|
||||||
|
req->history_mode = mode;
|
||||||
|
ret = !SERVER_CALL_ERR();
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_GetConsoleTitle
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINECON_GetConsoleTitle(HANDLE hConIn, WCHAR* buffer, size_t len)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
DWORD size = 0;
|
||||||
|
|
||||||
|
SERVER_START_VAR_REQ(get_console_input_info, sizeof(buffer))
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)hConIn;
|
||||||
|
if ((ret = !SERVER_CALL_ERR()))
|
||||||
|
{
|
||||||
|
size = min(len - sizeof(WCHAR), server_data_size(req));
|
||||||
|
memcpy(buffer, server_data_ptr(req), size);
|
||||||
|
buffer[size / sizeof(WCHAR)] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SERVER_END_VAR_REQ;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_GrabChanges
|
||||||
|
*
|
||||||
|
* A change occurs, try to figure out which
|
||||||
|
*/
|
||||||
|
int WINECON_GrabChanges(struct inner_data* data)
|
||||||
|
{
|
||||||
|
struct console_renderer_event evts[16];
|
||||||
|
int i, num;
|
||||||
|
HANDLE h;
|
||||||
|
|
||||||
|
SERVER_START_VAR_REQ( get_console_renderer_events, sizeof(evts) )
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)data->hSynchro;
|
||||||
|
if (!SERVER_CALL_ERR())
|
||||||
|
{
|
||||||
|
num = server_data_size(req);
|
||||||
|
memcpy(evts, server_data_ptr(req), num);
|
||||||
|
num /= sizeof(evts[0]);
|
||||||
|
}
|
||||||
|
else num = 0;
|
||||||
|
}
|
||||||
|
SERVER_END_VAR_REQ;
|
||||||
|
if (!num) {Trace(0, "hmm renderer signaled but no events available\n"); return 1;}
|
||||||
|
|
||||||
|
/* FIXME: should do some event compression here (cursor pos, update) */
|
||||||
|
Trace(1, "Change notification:");
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
switch (evts[i].event)
|
||||||
|
{
|
||||||
|
case CONSOLE_RENDERER_TITLE_EVENT:
|
||||||
|
data->fnSetTitle(data);
|
||||||
|
break;
|
||||||
|
case CONSOLE_RENDERER_ACTIVE_SB_EVENT:
|
||||||
|
SERVER_START_REQ( open_console )
|
||||||
|
{
|
||||||
|
req->from = (int)data->hConIn;
|
||||||
|
req->access = GENERIC_READ | GENERIC_WRITE;
|
||||||
|
req->share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||||
|
req->inherit = FALSE;
|
||||||
|
h = SERVER_CALL_ERR() ? 0 : (HANDLE)req->handle;
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
Trace(1, " active(%d)", (int)h);
|
||||||
|
if (h)
|
||||||
|
{
|
||||||
|
CloseHandle(data->hConOut);
|
||||||
|
data->hConOut = h;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSOLE_RENDERER_SB_RESIZE_EVENT:
|
||||||
|
if (data->sb_width != evts[i].u.resize.width ||
|
||||||
|
data->sb_height != evts[i].u.resize.height)
|
||||||
|
{
|
||||||
|
Trace(1, " resize(%d,%d)", evts[i].u.resize.width, evts[i].u.resize.height);
|
||||||
|
data->sb_width = evts[i].u.resize.width;
|
||||||
|
data->sb_height = evts[i].u.resize.height;
|
||||||
|
|
||||||
|
data->cells = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, data->cells,
|
||||||
|
data->sb_width * data->sb_height * sizeof(CHAR_INFO));
|
||||||
|
if (!data->cells) {Trace(0, "OOM\n"); exit(0);}
|
||||||
|
data->fnResizeScreenBuffer(data);
|
||||||
|
data->fnComputePositions(data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSOLE_RENDERER_UPDATE_EVENT:
|
||||||
|
Trace(1, " update(%d,%d)", evts[i].u.update.top, evts[i].u.update.bottom);
|
||||||
|
WINECON_FetchCells(data, evts[i].u.update.top, evts[i].u.update.bottom);
|
||||||
|
break;
|
||||||
|
case CONSOLE_RENDERER_CURSOR_POS_EVENT:
|
||||||
|
if (evts[i].u.cursor_pos.x != data->cursor.X || evts[i].u.cursor_pos.y != data->cursor.Y)
|
||||||
|
{
|
||||||
|
data->cursor.X = evts[i].u.cursor_pos.x;
|
||||||
|
data->cursor.Y = evts[i].u.cursor_pos.y;
|
||||||
|
data->fnPosCursor(data);
|
||||||
|
Trace(1, " curs-pos(%d,%d)",evts[i].u.cursor_pos.x, evts[i].u.cursor_pos.y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSOLE_RENDERER_CURSOR_GEOM_EVENT:
|
||||||
|
if (evts[i].u.cursor_geom.size != data->cursor_size ||
|
||||||
|
evts[i].u.cursor_geom.visible != data->cursor_visible)
|
||||||
|
{
|
||||||
|
data->fnShapeCursor(data, evts[i].u.cursor_geom.size,
|
||||||
|
evts[i].u.cursor_geom.visible, FALSE);
|
||||||
|
Trace(1, " curs-geom(%d,%d)",
|
||||||
|
evts[i].u.cursor_geom.size, evts[i].u.cursor_geom.visible);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSOLE_RENDERER_DISPLAY_EVENT:
|
||||||
|
if (evts[i].u.display.left != data->win_pos.X)
|
||||||
|
{
|
||||||
|
data->fnScroll(data, evts[i].u.display.left, TRUE);
|
||||||
|
data->fnPosCursor(data);
|
||||||
|
Trace(1, " h-scroll(%d)", evts[i].u.display.left);
|
||||||
|
}
|
||||||
|
if (evts[i].u.display.top != data->win_pos.Y)
|
||||||
|
{
|
||||||
|
data->fnScroll(data, evts[i].u.display.top, FALSE);
|
||||||
|
data->fnPosCursor(data);
|
||||||
|
Trace(1, " v-scroll(%d)", evts[i].u.display.top);
|
||||||
|
}
|
||||||
|
if (evts[i].u.display.width != data->win_width ||
|
||||||
|
evts[i].u.display.height != data->win_height)
|
||||||
|
{
|
||||||
|
Trace(1, " win-size(%d,%d)", evts[i].u.display.width, evts[i].u.display.height);
|
||||||
|
data->win_width = evts[i].u.display.width;
|
||||||
|
data->win_height = evts[i].u.display.height;
|
||||||
|
data->fnComputePositions(data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONSOLE_RENDERER_EXIT_EVENT:
|
||||||
|
Trace(1, ". Exit!!\n");
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
Trace(0, "Unknown event type (%d)\n", evts[i].event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace(1, ". Done\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_Delete
|
||||||
|
*
|
||||||
|
* Destroy wineconsole internal data
|
||||||
|
*/
|
||||||
|
static void WINECON_Delete(struct inner_data* data)
|
||||||
|
{
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
if (data->hConIn) CloseHandle(data->hConIn);
|
||||||
|
if (data->hConOut) CloseHandle(data->hConOut);
|
||||||
|
if (data->hSynchro) CloseHandle(data->hSynchro);
|
||||||
|
if (data->cells) HeapFree(GetProcessHeap(), 0, data->cells);
|
||||||
|
data->fnDeleteBackend(data);
|
||||||
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_Init
|
||||||
|
*
|
||||||
|
* Initialisation part I. Creation of server object (console input and
|
||||||
|
* active screen buffer)
|
||||||
|
*/
|
||||||
|
static struct inner_data* WINECON_Init(HINSTANCE hInst, void* pid)
|
||||||
|
{
|
||||||
|
struct inner_data* data = NULL;
|
||||||
|
DWORD ret;
|
||||||
|
WCHAR szTitle[] = {'W','i','n','e',' ','c','o','n','s','o','l','e',0};
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
|
||||||
|
if (!data) return 0;
|
||||||
|
|
||||||
|
/* the handles here are created without the whistles and bells required by console
|
||||||
|
* (mainly because wineconsole doesn't need it)
|
||||||
|
* - there are not inheritable
|
||||||
|
* - hConIn is not synchronizable
|
||||||
|
*/
|
||||||
|
SERVER_START_REQ(alloc_console)
|
||||||
|
{
|
||||||
|
req->access = GENERIC_READ | GENERIC_WRITE;
|
||||||
|
req->inherit = FALSE;
|
||||||
|
req->pid = pid;
|
||||||
|
ret = !SERVER_CALL_ERR();
|
||||||
|
data->hConIn = (HANDLE)req->handle_in;
|
||||||
|
data->hSynchro = (HANDLE)req->event;
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
if (!ret) goto error;
|
||||||
|
|
||||||
|
len = lstrlenW(szTitle) * sizeof(WCHAR);
|
||||||
|
len = min(len, REQUEST_MAX_VAR_SIZE);
|
||||||
|
|
||||||
|
SERVER_START_VAR_REQ(set_console_input_info, len)
|
||||||
|
{
|
||||||
|
req->handle = (handle_t)data->hConIn;
|
||||||
|
req->mask = SET_CONSOLE_INPUT_INFO_TITLE;
|
||||||
|
memcpy(server_data_ptr(req), szTitle, len);
|
||||||
|
ret = !SERVER_CALL_ERR();
|
||||||
|
}
|
||||||
|
SERVER_END_VAR_REQ;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
SERVER_START_REQ(create_console_output)
|
||||||
|
{
|
||||||
|
req->handle_in = (handle_t)data->hConIn;
|
||||||
|
req->access = GENERIC_WRITE|GENERIC_READ;
|
||||||
|
req->share = FILE_SHARE_READ|FILE_SHARE_WRITE;
|
||||||
|
req->inherit = FALSE;
|
||||||
|
data->hConOut = (HANDLE)(SERVER_CALL_ERR() ? 0 : req->handle_out);
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
if (data->hConOut) return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
WINECON_Delete(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_Spawn
|
||||||
|
*
|
||||||
|
* Spawn the child processus when invoked with wineconsole foo bar
|
||||||
|
*/
|
||||||
|
static BOOL WINECON_Spawn(struct inner_data* data, LPCSTR lpCmdLine)
|
||||||
|
{
|
||||||
|
PROCESS_INFORMATION info;
|
||||||
|
STARTUPINFO startup;
|
||||||
|
LPWSTR ptr = GetCommandLine(); /* we're unicode... */
|
||||||
|
BOOL done;
|
||||||
|
|
||||||
|
/* we're in the case wineconsole <exe> <options>... spawn the new process */
|
||||||
|
memset(&startup, 0, sizeof(startup));
|
||||||
|
startup.cb = sizeof(startup);
|
||||||
|
startup.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
|
||||||
|
startup.wShowWindow = SW_SHOWNORMAL;
|
||||||
|
|
||||||
|
/* the attributes of wineconsole's handles are not adequate for inheritance, so
|
||||||
|
* get them with the correct attributes before process creation
|
||||||
|
*/
|
||||||
|
if (!DuplicateHandle(GetCurrentProcess(), data->hConIn, GetCurrentProcess(),
|
||||||
|
&startup.hStdInput, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, TRUE, 0) ||
|
||||||
|
!DuplicateHandle(GetCurrentProcess(), data->hConOut, GetCurrentProcess(),
|
||||||
|
&startup.hStdOutput, GENERIC_READ|GENERIC_WRITE, TRUE, 0) ||
|
||||||
|
!DuplicateHandle(GetCurrentProcess(), data->hConOut, GetCurrentProcess(),
|
||||||
|
&startup.hStdError, GENERIC_READ|GENERIC_WRITE, TRUE, 0))
|
||||||
|
{
|
||||||
|
Trace(0, "can't dup handles\n");
|
||||||
|
/* no need to delete handles, we're exiting the programm anyway */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we could have several ' ' in process command line... so try first space...
|
||||||
|
* FIXME:
|
||||||
|
* the correct way would be to check the existence of the left part of ptr
|
||||||
|
* (to be a file)
|
||||||
|
*/
|
||||||
|
while (*ptr && *ptr++ != ' ');
|
||||||
|
|
||||||
|
done = *ptr && CreateProcess(NULL, ptr, NULL, NULL, TRUE, 0L, NULL, NULL, &startup, &info);
|
||||||
|
|
||||||
|
/* we no longer need the handles passed to the child for the console */
|
||||||
|
CloseHandle(startup.hStdInput);
|
||||||
|
CloseHandle(startup.hStdOutput);
|
||||||
|
CloseHandle(startup.hStdError);
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* WINECON_WinMain
|
||||||
|
*
|
||||||
|
* wineconsole can either be started as:
|
||||||
|
* wineconsole <int> used when a new console is created (AllocConsole)
|
||||||
|
* wineconsole <pgm> <arguments> used to start the program <pgm> from the command line in
|
||||||
|
* a freshly created console
|
||||||
|
*/
|
||||||
|
int PASCAL WINECON_WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPCSTR lpCmdLine, UINT nCmdShow)
|
||||||
|
{
|
||||||
|
struct inner_data* data;
|
||||||
|
int ret = 1;
|
||||||
|
unsigned evt;
|
||||||
|
|
||||||
|
/* case of wineconsole <evt>, signal process that created us that we're up and running */
|
||||||
|
if (sscanf(lpCmdLine, "%d", &evt) == 1)
|
||||||
|
{
|
||||||
|
if (!(data = WINECON_Init(hInst, 0))) return 0;
|
||||||
|
ret = SetEvent((HANDLE)evt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(data = WINECON_Init(hInst, (void*)GetCurrentProcessId()))) return 0;
|
||||||
|
ret = WINECON_Spawn(data, lpCmdLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret && WCUSER_InitBackend(data))
|
||||||
|
{
|
||||||
|
ret = data->fnMainLoop(data);
|
||||||
|
}
|
||||||
|
WINECON_Delete(data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
name wineconsole
|
||||||
|
mode guiexe
|
||||||
|
type win32
|
||||||
|
init WINECON_WinMain
|
||||||
|
rsrc wineconsole_res.res
|
||||||
|
|
||||||
|
import -delay comctl32
|
||||||
|
import gdi32.dll
|
||||||
|
import user32.dll
|
||||||
|
#import advapi32.dll
|
||||||
|
import kernel32.dll
|
||||||
|
import ntdll.dll
|
|
@ -0,0 +1,70 @@
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
|
||||||
|
|
||||||
|
STRINGTABLE LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
BEGIN
|
||||||
|
IDS_EDIT, "&Edit"
|
||||||
|
IDS_DEFAULT, "&Default"
|
||||||
|
IDS_PROPERTY, "&Property"
|
||||||
|
IDS_MARK, "&Mark"
|
||||||
|
IDS_COPY, "&Copy"
|
||||||
|
IDS_PASTE, "&Paste"
|
||||||
|
IDS_SELECTALL, "&Select all"
|
||||||
|
IDS_SCROLL, "Sc&roll"
|
||||||
|
IDS_SEARCH, "S&earch"
|
||||||
|
IDS_FNT_DISPLAY, "Each character is %ld pixels wide on %ld pixels high"
|
||||||
|
IDS_FNT_PREVIEW_1, "This is a test"
|
||||||
|
IDS_FNT_PREVIEW_2, ""
|
||||||
|
END
|
||||||
|
|
||||||
|
IDD_OPTION DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 140, 105 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION " Options "
|
||||||
|
FONT 8, "Helv"
|
||||||
|
{
|
||||||
|
GROUPBOX "Cursor size", -1, 10, 11, 120, 44, BS_GROUPBOX
|
||||||
|
AUTORADIOBUTTON "&Small", IDC_OPT_CURSOR_SMALL, 14, 23, 84, 10, WS_TABSTOP
|
||||||
|
AUTORADIOBUTTON "&Medium", IDC_OPT_CURSOR_MEDIUM, 14, 33, 84, 10, WS_TABSTOP
|
||||||
|
AUTORADIOBUTTON "&Large", IDC_OPT_CURSOR_LARGE, 14, 43, 84, 10, WS_TABSTOP
|
||||||
|
|
||||||
|
GROUPBOX "Command history", -1, 10, 57, 180, 35, BS_GROUPBOX
|
||||||
|
LTEXT "&Numbers of recalled commands :", -1, 14, 67, 78, 18
|
||||||
|
EDITTEXT IDC_OPT_HIST_SIZE, 92, 69, 31, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_OPT_HIST_SIZE_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
AUTOCHECKBOX "&Remove doubles", IDC_OPT_HIST_DOUBLE, 130, 67, 50, 18, WS_TABSTOP|BS_MULTILINE
|
||||||
|
}
|
||||||
|
|
||||||
|
IDD_FONT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 140, 105 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION " Font "
|
||||||
|
FONT 8, "Helv"
|
||||||
|
{
|
||||||
|
LTEXT "&Font", -1, 5, 5, 24, 8
|
||||||
|
LISTBOX IDC_FNT_LIST_FONT, 5,18,109,42, LBS_SORT|WS_VSCROLL
|
||||||
|
LTEXT "&Size", -1, 128, 5, 60, 8
|
||||||
|
LISTBOX IDC_FNT_LIST_SIZE, 128, 18, 50, 60, WS_VSCROLL
|
||||||
|
CONTROL "", IDC_FNT_PREVIEW, "WineConFontPreview", 0L, 5,60,109,40
|
||||||
|
LTEXT "", IDC_FNT_FONT_INFO, 128, 76, 80, 18
|
||||||
|
}
|
||||||
|
|
||||||
|
IDD_CONFIG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 140, 105 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION " Configuration "
|
||||||
|
FONT 8, "Helv"
|
||||||
|
{
|
||||||
|
GROUPBOX "Buffer zone", -1, 10, 11, 110, 42, BS_GROUPBOX
|
||||||
|
LTEXT "&Width :", -1, 14, 25, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_SB_WIDTH, 78, 23, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_SB_WIDTH_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
LTEXT "&Height :", -1, 14, 39, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_SB_HEIGHT, 78, 37, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_SB_HEIGHT_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
|
||||||
|
GROUPBOX "Window size", -1, 10, 55, 110, 42
|
||||||
|
LTEXT "W&idth :", -1, 14, 69, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_WIN_WIDTH, 78, 67, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_WIN_WIDTH_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
LTEXT "H&eight :", -1, 14, 83, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_WIN_HEIGHT, 78, 81, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_WIN_HEIGHT_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
|
||||||
|
|
||||||
|
STRINGTABLE LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||||
|
BEGIN
|
||||||
|
IDS_EDIT, "&Editer"
|
||||||
|
IDS_DEFAULT, "Par &défaut"
|
||||||
|
IDS_PROPERTY, "&Propriétés"
|
||||||
|
IDS_MARK, "&Marquer"
|
||||||
|
IDS_COPY, "&Copier"
|
||||||
|
IDS_PASTE, "C&oller"
|
||||||
|
IDS_SELECTALL, "&Sélectionner tout"
|
||||||
|
IDS_SCROLL, "&Défiler"
|
||||||
|
IDS_SEARCH, "C&hercher"
|
||||||
|
IDS_FNT_DISPLAY, "Chaque caractère a %ld points en largeur et %ld points en hauteur"
|
||||||
|
IDS_FNT_PREVIEW_1, "Ceci est un test"
|
||||||
|
IDS_FNT_PREVIEW_2, "éèàôë"
|
||||||
|
END
|
||||||
|
|
||||||
|
IDD_OPTION DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 140, 105 LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||||
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION " Options "
|
||||||
|
FONT 8, "Helv"
|
||||||
|
{
|
||||||
|
GROUPBOX "Taille du curseur", -1, 10, 11, 120, 44, BS_GROUPBOX
|
||||||
|
AUTORADIOBUTTON "&Petit", IDC_OPT_CURSOR_SMALL, 14, 23, 84, 10, WS_TABSTOP
|
||||||
|
AUTORADIOBUTTON "&Moyen", IDC_OPT_CURSOR_MEDIUM, 14, 33, 84, 10, WS_TABSTOP
|
||||||
|
AUTORADIOBUTTON "&Grand", IDC_OPT_CURSOR_LARGE, 14, 43, 84, 10, WS_TABSTOP
|
||||||
|
|
||||||
|
GROUPBOX "Historique des commandes", -1, 10, 57, 180, 35, BS_GROUPBOX
|
||||||
|
LTEXT "&Taille de la mémoire tampon :", -1, 14, 67, 78, 18
|
||||||
|
EDITTEXT IDC_OPT_HIST_SIZE, 92, 69, 31, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_OPT_HIST_SIZE_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
AUTOCHECKBOX "&Supprimer les doublons", IDC_OPT_HIST_DOUBLE, 130, 67, 50, 18, WS_TABSTOP|BS_MULTILINE
|
||||||
|
}
|
||||||
|
|
||||||
|
IDD_FONT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 140, 105 LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||||
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION " Police "
|
||||||
|
FONT 8, "Helv"
|
||||||
|
{
|
||||||
|
LTEXT "&Police", -1, 5, 5, 24, 8
|
||||||
|
LISTBOX IDC_FNT_LIST_FONT, 5, 18, 109, 42, LBS_SORT|WS_VSCROLL
|
||||||
|
LTEXT "&Taille", -1, 128, 5, 60, 8
|
||||||
|
LISTBOX IDC_FNT_LIST_SIZE, 128, 18, 50, 60, WS_VSCROLL
|
||||||
|
CONTROL "", IDC_FNT_PREVIEW, "WineConFontPreview", 0L, 5, 60, 109, 40
|
||||||
|
LTEXT "", IDC_FNT_FONT_INFO, 128, 76, 80, 18
|
||||||
|
}
|
||||||
|
|
||||||
|
IDD_CONFIG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 140, 105 LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||||
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION " Configuration "
|
||||||
|
FONT 8, "Helv"
|
||||||
|
{
|
||||||
|
GROUPBOX "Taille mémoire tampon écran", -1, 10, 11, 110, 42, BS_GROUPBOX
|
||||||
|
LTEXT "&Largeur :", -1, 14, 25, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_SB_WIDTH, 78, 23, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_SB_WIDTH_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
LTEXT "Ha&uteur :", -1, 14, 39, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_SB_HEIGHT, 78, 37, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_SB_HEIGHT_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
|
||||||
|
GROUPBOX "Taille de la fenêtre", -1, 10, 55, 110, 42
|
||||||
|
LTEXT "La&rgeur :", -1, 14, 69, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_WIN_WIDTH, 78, 67, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_WIN_WIDTH_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
LTEXT "Hau&teur :", -1, 14, 83, 54, 9
|
||||||
|
EDITTEXT IDC_CNF_WIN_HEIGHT, 78, 81, 36, 12, WS_TABSTOP|WS_BORDER|ES_NUMBER
|
||||||
|
CONTROL "", IDC_CNF_WIN_HEIGHT_UD, "msctls_updown32", UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_AUTOBUDDY|UDS_ARROWKEYS|UDS_NOTHOUSANDS, 0, 0, 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* wineconsole resource definitions */
|
||||||
|
|
||||||
|
/* strings */
|
||||||
|
#define IDS_EDIT 0x100
|
||||||
|
#define IDS_DEFAULT 0x101
|
||||||
|
#define IDS_PROPERTY 0x102
|
||||||
|
|
||||||
|
#define IDS_MARK 0x110
|
||||||
|
#define IDS_COPY 0x111
|
||||||
|
#define IDS_PASTE 0x112
|
||||||
|
#define IDS_SELECTALL 0x113
|
||||||
|
#define IDS_SCROLL 0x114
|
||||||
|
#define IDS_SEARCH 0x115
|
||||||
|
|
||||||
|
#define IDS_FNT_DISPLAY 0x200
|
||||||
|
#define IDS_FNT_PREVIEW_1 0x201
|
||||||
|
#define IDS_FNT_PREVIEW_2 0x202
|
||||||
|
|
||||||
|
#define IDD_OPTION 0x0100
|
||||||
|
#define IDD_FONT 0x0200
|
||||||
|
#define IDD_CONFIG 0x0300
|
||||||
|
|
||||||
|
/* dialog boxes */
|
||||||
|
#define IDC_OPT_CURSOR_SMALL 0x0101
|
||||||
|
#define IDC_OPT_CURSOR_MEDIUM 0x0102
|
||||||
|
#define IDC_OPT_CURSOR_LARGE 0x0103
|
||||||
|
#define IDC_OPT_HIST_SIZE 0x0104
|
||||||
|
#define IDC_OPT_HIST_SIZE_UD 0x0105
|
||||||
|
#define IDC_OPT_HIST_DOUBLE 0x0106
|
||||||
|
|
||||||
|
#define IDC_FNT_LIST_FONT 0x0201
|
||||||
|
#define IDC_FNT_LIST_SIZE 0x0202
|
||||||
|
#define IDC_FNT_FONT_INFO 0x0203
|
||||||
|
#define IDC_FNT_PREVIEW 0x0204
|
||||||
|
|
||||||
|
#define IDC_CNF_SB_WIDTH 0x0301
|
||||||
|
#define IDC_CNF_SB_WIDTH_UD 0x0302
|
||||||
|
#define IDC_CNF_SB_HEIGHT 0x0303
|
||||||
|
#define IDC_CNF_SB_HEIGHT_UD 0x0304
|
||||||
|
#define IDC_CNF_WIN_WIDTH 0x0305
|
||||||
|
#define IDC_CNF_WIN_WIDTH_UD 0x0306
|
||||||
|
#define IDC_CNF_WIN_HEIGHT 0x0307
|
||||||
|
#define IDC_CNF_WIN_HEIGHT_UD 0x0308
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "commctrl.h"
|
||||||
|
#include "wineconsole_res.h"
|
||||||
|
|
||||||
|
#include "wineconsole_En.rc"
|
||||||
|
#include "wineconsole_Fr.rc"
|
|
@ -20,6 +20,7 @@
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
|
#include "wincon.h"
|
||||||
#include "wine/server.h"
|
#include "wine/server.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
|
@ -216,29 +217,6 @@ void PROCESS_CallUserSignalProc( UINT uCode, HMODULE16 hModule )
|
||||||
Callout.UserSignalProc( uCode, GetCurrentProcessId(), dwFlags, hModule );
|
Callout.UserSignalProc( uCode, GetCurrentProcessId(), dwFlags, hModule );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* set_console_handles
|
|
||||||
*
|
|
||||||
* Set the console handles to use stdin/stdout.
|
|
||||||
*/
|
|
||||||
static void set_console_handles( HANDLE console )
|
|
||||||
{
|
|
||||||
wine_server_send_fd( 0 );
|
|
||||||
wine_server_send_fd( 1 );
|
|
||||||
|
|
||||||
SERVER_START_REQ( set_console_fd )
|
|
||||||
{
|
|
||||||
req->handle = console;
|
|
||||||
req->fd_in = 0;
|
|
||||||
req->fd_out = 1;
|
|
||||||
req->pid = 0;
|
|
||||||
SERVER_CALL();
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* process_init
|
* process_init
|
||||||
*
|
*
|
||||||
|
@ -287,15 +265,28 @@ static BOOL process_init( char *argv[] )
|
||||||
SERVER_END_VAR_REQ;
|
SERVER_END_VAR_REQ;
|
||||||
if (!ret) return FALSE;
|
if (!ret) return FALSE;
|
||||||
|
|
||||||
SetStdHandle( STD_INPUT_HANDLE, current_startupinfo.hStdInput );
|
|
||||||
SetStdHandle( STD_OUTPUT_HANDLE, current_startupinfo.hStdOutput );
|
|
||||||
SetStdHandle( STD_ERROR_HANDLE, current_startupinfo.hStdError );
|
|
||||||
if (create_flags & CREATE_NEW_CONSOLE)
|
|
||||||
set_console_handles( current_startupinfo.hStdOutput );
|
|
||||||
|
|
||||||
/* Create the process heap */
|
/* Create the process heap */
|
||||||
current_process.heap = HeapCreate( HEAP_GROWABLE, 0, 0 );
|
current_process.heap = HeapCreate( HEAP_GROWABLE, 0, 0 );
|
||||||
|
|
||||||
|
if (create_flags == 0 &&
|
||||||
|
current_startupinfo.hStdInput == 0 &&
|
||||||
|
current_startupinfo.hStdOutput == 0 &&
|
||||||
|
current_startupinfo.hStdError == 0)
|
||||||
|
{
|
||||||
|
/* no parent, and no new console requested, create a simple console with bare handles to
|
||||||
|
* unix stdio input & output streams (aka simple console)
|
||||||
|
*/
|
||||||
|
SetStdHandle( STD_INPUT_HANDLE, FILE_DupUnixHandle( 0, GENERIC_READ, TRUE ));
|
||||||
|
SetStdHandle( STD_OUTPUT_HANDLE, FILE_DupUnixHandle( 1, GENERIC_WRITE, TRUE ));
|
||||||
|
SetStdHandle( STD_ERROR_HANDLE, FILE_DupUnixHandle( 1, GENERIC_WRITE, TRUE ));
|
||||||
|
}
|
||||||
|
else if (!(create_flags & (DETACHED_PROCESS|CREATE_NEW_CONSOLE)))
|
||||||
|
{
|
||||||
|
SetStdHandle( STD_INPUT_HANDLE, current_startupinfo.hStdInput );
|
||||||
|
SetStdHandle( STD_OUTPUT_HANDLE, current_startupinfo.hStdOutput );
|
||||||
|
SetStdHandle( STD_ERROR_HANDLE, current_startupinfo.hStdError );
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we can use the pthreads routines */
|
/* Now we can use the pthreads routines */
|
||||||
PTHREAD_init_done();
|
PTHREAD_init_done();
|
||||||
|
|
||||||
|
@ -305,7 +296,11 @@ static BOOL process_init( char *argv[] )
|
||||||
/* Parse command line arguments */
|
/* Parse command line arguments */
|
||||||
OPTIONS_ParseOptions( argv );
|
OPTIONS_ParseOptions( argv );
|
||||||
|
|
||||||
return MAIN_MainInit();
|
ret = MAIN_MainInit();
|
||||||
|
|
||||||
|
if (create_flags & CREATE_NEW_CONSOLE)
|
||||||
|
AllocConsole();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
1226
server/console.c
1226
server/console.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Wine server consoles
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 Eric Pouech
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WINE_SERVER_CONSOLE_H
|
||||||
|
#define __WINE_SERVER_CONSOLE_H
|
||||||
|
|
||||||
|
struct screen_buffer;
|
||||||
|
struct console_input_events;
|
||||||
|
|
||||||
|
struct console_input
|
||||||
|
{
|
||||||
|
struct object obj; /* object header */
|
||||||
|
int num_proc; /* number of processes attached to this console */
|
||||||
|
struct process *renderer; /* console renderer thread */
|
||||||
|
int mode; /* input mode */
|
||||||
|
struct screen_buffer *active; /* active screen buffer */
|
||||||
|
int recnum; /* number of input records */
|
||||||
|
void *records; /* input records */
|
||||||
|
struct console_input_events *evt; /* synchronization event with renderer */
|
||||||
|
WCHAR *title; /* console title */
|
||||||
|
WCHAR **history; /* lines history */
|
||||||
|
int history_size; /* number of entries in history array */
|
||||||
|
int history_index; /* number of used entries in history array */
|
||||||
|
int history_mode; /* mode of history (non zero means remove doubled strings */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* console functions */
|
||||||
|
|
||||||
|
extern void inherit_console(struct process *parent, struct process *process, handle_t hconin);
|
||||||
|
extern int free_console( struct process *process );
|
||||||
|
|
||||||
|
#endif /* __WINE_SERVER_CONSOLE_H */
|
|
@ -14,6 +14,7 @@
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "request.h"
|
#include "request.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_CONTINUED };
|
enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_CONTINUED };
|
||||||
|
|
||||||
|
@ -411,6 +412,11 @@ static int debugger_attach( struct process *process, struct thread *debugger )
|
||||||
for (thread = debugger; thread; thread = thread->process->debugger)
|
for (thread = debugger; thread; thread = thread->process->debugger)
|
||||||
if (thread->process == process) goto error;
|
if (thread->process == process) goto error;
|
||||||
|
|
||||||
|
/* don't let a debugger debug its console... won't work */
|
||||||
|
if (debugger->process->console &&
|
||||||
|
debugger->process->console->renderer == process &&
|
||||||
|
process->console) goto error;
|
||||||
|
|
||||||
suspend_process( process );
|
suspend_process( process );
|
||||||
|
|
||||||
/* we must have been able to attach all threads */
|
/* we must have been able to attach all threads */
|
||||||
|
|
|
@ -494,7 +494,7 @@ DECL_HANDLER(alloc_file_handle)
|
||||||
if ((file = create_file_for_fd( fd, req->access, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
if ((file = create_file_for_fd( fd, req->access, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
0, DRIVE_UNKNOWN )))
|
0, DRIVE_UNKNOWN )))
|
||||||
{
|
{
|
||||||
req->handle = alloc_handle( current->process, file, req->access, 0 );
|
req->handle = alloc_handle( current->process, file, req->access, req->inherit );
|
||||||
release_object( file );
|
release_object( file );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,6 +355,7 @@ struct object *get_handle_obj( struct process *process, handle_t handle,
|
||||||
if (!(entry = get_handle( process, handle ))) return NULL;
|
if (!(entry = get_handle( process, handle ))) return NULL;
|
||||||
if ((entry->access & access) != access)
|
if ((entry->access & access) != access)
|
||||||
{
|
{
|
||||||
|
fprintf( stderr, "handle %d access %08x denied (%08x)\n", handle, access, entry->access );
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -376,6 +377,7 @@ int get_handle_fd( struct process *process, handle_t handle, unsigned int access
|
||||||
if (!(entry = get_handle( process, handle ))) return -1;
|
if (!(entry = get_handle( process, handle ))) return -1;
|
||||||
if ((entry->access & access) != access)
|
if ((entry->access & access) != access)
|
||||||
{
|
{
|
||||||
|
fprintf( stderr, "handle %d access %08x denied (%08x)\n", handle, access, entry->access );
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,11 +155,6 @@ extern void file_set_error(void);
|
||||||
|
|
||||||
int get_serial_async_timeout(struct object *obj, int type, int count);
|
int get_serial_async_timeout(struct object *obj, int type, int count);
|
||||||
|
|
||||||
/* console functions */
|
|
||||||
|
|
||||||
extern int alloc_console( struct process *process );
|
|
||||||
extern int free_console( struct process *process );
|
|
||||||
|
|
||||||
/* debugger functions */
|
/* debugger functions */
|
||||||
|
|
||||||
extern int set_process_debugger( struct process *process, struct thread *debugger );
|
extern int set_process_debugger( struct process *process, struct thread *debugger );
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "request.h"
|
#include "request.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
/* process structure */
|
/* process structure */
|
||||||
|
|
||||||
|
@ -101,12 +102,18 @@ static int set_process_console( struct process *process, struct process *parent,
|
||||||
{
|
{
|
||||||
if (process->create_flags & CREATE_NEW_CONSOLE)
|
if (process->create_flags & CREATE_NEW_CONSOLE)
|
||||||
{
|
{
|
||||||
if (!alloc_console( process )) return 0;
|
/* let the process init do the allocation */
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
else if (parent && !(process->create_flags & DETACHED_PROCESS))
|
else if (parent && !(process->create_flags & DETACHED_PROCESS))
|
||||||
{
|
{
|
||||||
if (parent->console_in) process->console_in = grab_object( parent->console_in );
|
/* FIXME: some better error checking should be done...
|
||||||
if (parent->console_out) process->console_out = grab_object( parent->console_out );
|
* like if hConOut and hConIn are console handles, then they should be on the same
|
||||||
|
* physical console
|
||||||
|
*/
|
||||||
|
inherit_console( parent, process,
|
||||||
|
(info->inherit_all || (info->start_flags & STARTF_USESTDHANDLES)) ?
|
||||||
|
info->hstdin : 0 );
|
||||||
}
|
}
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
|
@ -129,13 +136,20 @@ static int set_process_console( struct process *process, struct process *parent,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* no parent, use handles to the console for stdio */
|
if (process->console)
|
||||||
req->hstdin = alloc_handle( process, process->console_in,
|
{
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
req->hstdin = alloc_handle( process, process->console,
|
||||||
req->hstdout = alloc_handle( process, process->console_out,
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
req->hstdout = alloc_handle( process, process->console->active,
|
||||||
req->hstderr = alloc_handle( process, process->console_out,
|
GENERIC_READ | GENERIC_WRITE, 1 );
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
req->hstderr = alloc_handle( process, process->console->active,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, 1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no parent, let the caller decide what to do */
|
||||||
|
req->hstdin = req->hstdout = req->hstderr = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* some handles above may have been invalid; this is not an error */
|
/* some handles above may have been invalid; this is not an error */
|
||||||
if (get_error() == STATUS_INVALID_HANDLE) clear_error();
|
if (get_error() == STATUS_INVALID_HANDLE) clear_error();
|
||||||
|
@ -152,6 +166,7 @@ struct thread *create_process( int fd )
|
||||||
if (!(process = alloc_object( &process_ops, fd ))) return NULL;
|
if (!(process = alloc_object( &process_ops, fd ))) return NULL;
|
||||||
process->next = NULL;
|
process->next = NULL;
|
||||||
process->prev = NULL;
|
process->prev = NULL;
|
||||||
|
process->parent = NULL;
|
||||||
process->thread_list = NULL;
|
process->thread_list = NULL;
|
||||||
process->debugger = NULL;
|
process->debugger = NULL;
|
||||||
process->handles = NULL;
|
process->handles = NULL;
|
||||||
|
@ -161,8 +176,7 @@ struct thread *create_process( int fd )
|
||||||
process->affinity = 1;
|
process->affinity = 1;
|
||||||
process->suspend = 0;
|
process->suspend = 0;
|
||||||
process->create_flags = 0;
|
process->create_flags = 0;
|
||||||
process->console_in = NULL;
|
process->console = NULL;
|
||||||
process->console_out = NULL;
|
|
||||||
process->init_event = NULL;
|
process->init_event = NULL;
|
||||||
process->idle_event = NULL;
|
process->idle_event = NULL;
|
||||||
process->queue = NULL;
|
process->queue = NULL;
|
||||||
|
@ -173,6 +187,7 @@ struct thread *create_process( int fd )
|
||||||
process->exe.file = NULL;
|
process->exe.file = NULL;
|
||||||
process->exe.dbg_offset = 0;
|
process->exe.dbg_offset = 0;
|
||||||
process->exe.dbg_size = 0;
|
process->exe.dbg_size = 0;
|
||||||
|
|
||||||
gettimeofday( &process->start_time, NULL );
|
gettimeofday( &process->start_time, NULL );
|
||||||
if ((process->next = first_process) != NULL) process->next->prev = process;
|
if ((process->next = first_process) != NULL) process->next->prev = process;
|
||||||
first_process = process;
|
first_process = process;
|
||||||
|
@ -222,10 +237,11 @@ static void init_process( int ppid, struct init_process_request *req )
|
||||||
fatal_protocol_error( current, "init_process: called twice?\n" );
|
fatal_protocol_error( current, "init_process: called twice?\n" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
process->parent = (struct process *)grab_object( parent );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the process flags */
|
/* set the process flags */
|
||||||
process->create_flags = info ? info->create_flags : CREATE_NEW_CONSOLE;
|
process->create_flags = info ? info->create_flags : 0;
|
||||||
|
|
||||||
/* create the handle table */
|
/* create the handle table */
|
||||||
if (parent && info->inherit_all)
|
if (parent && info->inherit_all)
|
||||||
|
@ -288,6 +304,8 @@ static void process_destroy( struct object *obj )
|
||||||
|
|
||||||
/* we can't have a thread remaining */
|
/* we can't have a thread remaining */
|
||||||
assert( !process->thread_list );
|
assert( !process->thread_list );
|
||||||
|
if (process->console) release_object( process->console );
|
||||||
|
if (process->parent) release_object( process->parent );
|
||||||
if (process->next) process->next->prev = process->prev;
|
if (process->next) process->next->prev = process->prev;
|
||||||
if (process->prev) process->prev->next = process->next;
|
if (process->prev) process->prev->next = process->next;
|
||||||
else first_process = process->next;
|
else first_process = process->next;
|
||||||
|
@ -304,9 +322,8 @@ static void process_dump( struct object *obj, int verbose )
|
||||||
struct process *process = (struct process *)obj;
|
struct process *process = (struct process *)obj;
|
||||||
assert( obj->ops == &process_ops );
|
assert( obj->ops == &process_ops );
|
||||||
|
|
||||||
fprintf( stderr, "Process next=%p prev=%p console=%p/%p handles=%p\n",
|
fprintf( stderr, "Process next=%p prev=%p handles=%p\n",
|
||||||
process->next, process->prev, process->console_in, process->console_out,
|
process->next, process->prev, process->handles );
|
||||||
process->handles );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_signaled( struct object *obj, struct thread *thread )
|
static int process_signaled( struct object *obj, struct thread *thread )
|
||||||
|
@ -418,6 +435,25 @@ static void process_unload_dll( struct process *process, void *base )
|
||||||
set_error( STATUS_INVALID_PARAMETER );
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* kill all processes being attached to a console renderer */
|
||||||
|
static void kill_console_processes( struct process *renderer, int exit_code )
|
||||||
|
{
|
||||||
|
for (;;) /* restart from the beginning of the list every time */
|
||||||
|
{
|
||||||
|
struct process *process = first_process;
|
||||||
|
|
||||||
|
/* find the first process being attached to 'renderer' and still running */
|
||||||
|
while (process &&
|
||||||
|
(process == renderer || !process->console ||
|
||||||
|
process->console->renderer != renderer || !process->running_threads))
|
||||||
|
{
|
||||||
|
process = process->next;
|
||||||
|
}
|
||||||
|
if (!process) break;
|
||||||
|
kill_process( process, NULL, exit_code );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* a process has been killed (i.e. its last thread died) */
|
/* a process has been killed (i.e. its last thread died) */
|
||||||
static void process_killed( struct process *process )
|
static void process_killed( struct process *process )
|
||||||
{
|
{
|
||||||
|
@ -425,7 +461,13 @@ static void process_killed( struct process *process )
|
||||||
gettimeofday( &process->end_time, NULL );
|
gettimeofday( &process->end_time, NULL );
|
||||||
if (process->handles) release_object( process->handles );
|
if (process->handles) release_object( process->handles );
|
||||||
process->handles = NULL;
|
process->handles = NULL;
|
||||||
|
|
||||||
|
/* close the console attached to this process, if any */
|
||||||
free_console( process );
|
free_console( process );
|
||||||
|
|
||||||
|
/* close the processes using process as renderer, if any */
|
||||||
|
kill_console_processes( process, 0 );
|
||||||
|
|
||||||
while (process->exe.next)
|
while (process->exe.next)
|
||||||
{
|
{
|
||||||
struct process_dll *dll = process->exe.next;
|
struct process_dll *dll = process->exe.next;
|
||||||
|
@ -508,6 +550,7 @@ void resume_process( struct process *process )
|
||||||
void kill_process( struct process *process, struct thread *skip, int exit_code )
|
void kill_process( struct process *process, struct thread *skip, int exit_code )
|
||||||
{
|
{
|
||||||
struct thread *thread = process->thread_list;
|
struct thread *thread = process->thread_list;
|
||||||
|
|
||||||
while (thread)
|
while (thread)
|
||||||
{
|
{
|
||||||
struct thread *next = thread->proc_next;
|
struct thread *next = thread->proc_next;
|
||||||
|
@ -532,6 +575,7 @@ void kill_debugged_processes( struct thread *debugger, int exit_code )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* get all information about a process */
|
/* get all information about a process */
|
||||||
static void get_process_info( struct process *process, struct get_process_info_request *req )
|
static void get_process_info( struct process *process, struct get_process_info_request *req )
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct process
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
struct process *next; /* system-wide process list */
|
struct process *next; /* system-wide process list */
|
||||||
struct process *prev;
|
struct process *prev;
|
||||||
|
struct process *parent; /* parent process */
|
||||||
struct thread *thread_list; /* head of the thread list */
|
struct thread *thread_list; /* head of the thread list */
|
||||||
struct thread *debugger; /* thread debugging this process */
|
struct thread *debugger; /* thread debugging this process */
|
||||||
struct object *handles; /* handle entries */
|
struct object *handles; /* handle entries */
|
||||||
|
@ -41,8 +42,7 @@ struct process
|
||||||
int affinity; /* process affinity mask */
|
int affinity; /* process affinity mask */
|
||||||
int suspend; /* global process suspend count */
|
int suspend; /* global process suspend count */
|
||||||
int create_flags; /* process creation flags */
|
int create_flags; /* process creation flags */
|
||||||
struct object *console_in; /* console input */
|
struct console_input*console; /* console input */
|
||||||
struct object *console_out; /* console output */
|
|
||||||
struct event *init_event; /* event for init done */
|
struct event *init_event; /* event for init done */
|
||||||
struct event *idle_event; /* event for input idle */
|
struct event *idle_event; /* event for input idle */
|
||||||
struct msg_queue *queue; /* main message queue */
|
struct msg_queue *queue; /* main message queue */
|
||||||
|
@ -55,7 +55,6 @@ struct process
|
||||||
struct process_snapshot
|
struct process_snapshot
|
||||||
{
|
{
|
||||||
struct process *process; /* process ptr */
|
struct process *process; /* process ptr */
|
||||||
struct process *parent; /* process parent */
|
|
||||||
int count; /* process refcount */
|
int count; /* process refcount */
|
||||||
int threads; /* number of threads */
|
int threads; /* number of threads */
|
||||||
int priority; /* priority class */
|
int priority; /* priority class */
|
||||||
|
|
|
@ -533,6 +533,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
||||||
/* Allocate a file handle for a Unix fd */
|
/* Allocate a file handle for a Unix fd */
|
||||||
@REQ(alloc_file_handle)
|
@REQ(alloc_file_handle)
|
||||||
unsigned int access; /* wanted access rights */
|
unsigned int access; /* wanted access rights */
|
||||||
|
int inherit; /* inherit flag */
|
||||||
int fd; /* file descriptor on the client side */
|
int fd; /* file descriptor on the client side */
|
||||||
@REPLY
|
@REPLY
|
||||||
handle_t handle; /* handle to the file */
|
handle_t handle; /* handle to the file */
|
||||||
|
@ -685,13 +686,14 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Allocate a console for the current process */
|
/* Allocate a console (only used by a console renderer) */
|
||||||
@REQ(alloc_console)
|
@REQ(alloc_console)
|
||||||
unsigned int access; /* wanted access rights */
|
unsigned int access; /* wanted access rights */
|
||||||
int inherit; /* inherit flag */
|
int inherit; /* inherit flag */
|
||||||
|
void* pid; /* pid of process which shall be attached to the console */
|
||||||
@REPLY
|
@REPLY
|
||||||
handle_t handle_in; /* handle to console input */
|
handle_t handle_in; /* handle to console input */
|
||||||
handle_t handle_out; /* handle to console output */
|
handle_t event; /* handle to renderer events change notification */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
@ -700,22 +702,67 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Open a handle to the process console */
|
#define CONSOLE_RENDERER_NONE_EVENT 0x00
|
||||||
@REQ(open_console)
|
#define CONSOLE_RENDERER_TITLE_EVENT 0x01
|
||||||
int output; /* input or output? */
|
#define CONSOLE_RENDERER_ACTIVE_SB_EVENT 0x02
|
||||||
unsigned int access; /* wanted access rights */
|
#define CONSOLE_RENDERER_SB_RESIZE_EVENT 0x03
|
||||||
int inherit; /* inherit flag */
|
#define CONSOLE_RENDERER_UPDATE_EVENT 0x04
|
||||||
|
#define CONSOLE_RENDERER_CURSOR_POS_EVENT 0x05
|
||||||
|
#define CONSOLE_RENDERER_CURSOR_GEOM_EVENT 0x06
|
||||||
|
#define CONSOLE_RENDERER_DISPLAY_EVENT 0x07
|
||||||
|
#define CONSOLE_RENDERER_EXIT_EVENT 0x08
|
||||||
|
struct console_renderer_event
|
||||||
|
{
|
||||||
|
short event;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct update
|
||||||
|
{
|
||||||
|
short top;
|
||||||
|
short bottom;
|
||||||
|
} update;
|
||||||
|
struct resize
|
||||||
|
{
|
||||||
|
short width;
|
||||||
|
short height;
|
||||||
|
} resize;
|
||||||
|
struct cursor_pos
|
||||||
|
{
|
||||||
|
short x;
|
||||||
|
short y;
|
||||||
|
} cursor_pos;
|
||||||
|
struct cursor_geom
|
||||||
|
{
|
||||||
|
short visible;
|
||||||
|
short size;
|
||||||
|
} cursor_geom;
|
||||||
|
struct display
|
||||||
|
{
|
||||||
|
short left;
|
||||||
|
short top;
|
||||||
|
short width;
|
||||||
|
short height;
|
||||||
|
} display;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* retrieve console events for the renderer */
|
||||||
|
@REQ(get_console_renderer_events)
|
||||||
|
handle_t handle; /* handle to console input events */
|
||||||
@REPLY
|
@REPLY
|
||||||
handle_t handle; /* handle to the console */
|
VARARG(data,bytes); /* the various console_renderer_events */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Set a console file descriptor */
|
/* Open a handle to the process console */
|
||||||
@REQ(set_console_fd)
|
@REQ(open_console)
|
||||||
|
int from; /* 0 (resp 1) input (resp output) of current process console */
|
||||||
|
/* otherwise console_in handle to get active screen buffer? */
|
||||||
|
unsigned int access; /* wanted access rights */
|
||||||
|
int inherit; /* inherit flag */
|
||||||
|
int share; /* share mask (only for output handles) */
|
||||||
|
@REPLY
|
||||||
handle_t handle; /* handle to the console */
|
handle_t handle; /* handle to the console */
|
||||||
int fd_in; /* file descriptor to use as input */
|
|
||||||
int fd_out; /* file descriptor to use as output */
|
|
||||||
int pid; /* pid of xterm (hack) */
|
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
@ -734,28 +781,104 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* Set info about a console (input only) */
|
||||||
|
@REQ(set_console_input_info)
|
||||||
|
handle_t handle; /* handle to console input, or 0 for process' console */
|
||||||
|
int mask; /* setting mask (see below) */
|
||||||
|
handle_t active_sb; /* active screen buffer */
|
||||||
|
int history_mode; /* whether we duplicate lines in history */
|
||||||
|
int history_size; /* number of lines in history */
|
||||||
|
VARARG(title,unicode_str); /* console title */
|
||||||
|
@END
|
||||||
|
#define SET_CONSOLE_INPUT_INFO_ACTIVE_SB 0x01
|
||||||
|
#define SET_CONSOLE_INPUT_INFO_TITLE 0x02
|
||||||
|
#define SET_CONSOLE_INPUT_INFO_HISTORY_MODE 0x04
|
||||||
|
#define SET_CONSOLE_INPUT_INFO_HISTORY_SIZE 0x08
|
||||||
|
|
||||||
|
|
||||||
|
/* Get info about a console (input only) */
|
||||||
|
@REQ(get_console_input_info)
|
||||||
|
handle_t handle; /* handle to console input, or 0 for process' console */
|
||||||
|
@REPLY
|
||||||
|
int history_mode; /* whether we duplicate lines in history */
|
||||||
|
int history_size; /* number of lines in history */
|
||||||
|
int history_index; /* number of used lines in history */
|
||||||
|
VARARG(title,unicode_str); /* console title */
|
||||||
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* appends a string to console's history */
|
||||||
|
@REQ(append_console_input_history)
|
||||||
|
handle_t handle; /* handle to console input, or 0 for process' console */
|
||||||
|
VARARG(line,unicode_str); /* line to add */
|
||||||
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* appends a string to console's history */
|
||||||
|
@REQ(get_console_input_history)
|
||||||
|
handle_t handle; /* handle to console input, or 0 for process' console */
|
||||||
|
int index; /* index to get line from */
|
||||||
|
@REPLY
|
||||||
|
VARARG(line,unicode_str); /* line to add */
|
||||||
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* creates a new screen buffer on process' console */
|
||||||
|
@REQ(create_console_output)
|
||||||
|
handle_t handle_in; /* handle to console input, or 0 for process' console */
|
||||||
|
int access; /* wanted access rights */
|
||||||
|
int share; /* sharing credentials */
|
||||||
|
int inherit; /* inherit flag */
|
||||||
|
@REPLY
|
||||||
|
handle_t handle_out; /* handle to the screen buffer */
|
||||||
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Set info about a console (output only) */
|
/* Set info about a console (output only) */
|
||||||
@REQ(set_console_info)
|
@REQ(set_console_output_info)
|
||||||
handle_t handle; /* handle to the console */
|
handle_t handle; /* handle to the console */
|
||||||
int mask; /* setting mask (see below) */
|
int mask; /* setting mask (see below) */
|
||||||
int cursor_size; /* size of cursor (percentage filled) */
|
short int cursor_size; /* size of cursor (percentage filled) */
|
||||||
int cursor_visible;/* cursor visibility flag */
|
short int cursor_visible;/* cursor visibility flag */
|
||||||
VARARG(title,string); /* console title */
|
short int cursor_x; /* position of cursor (x, y) */
|
||||||
|
short int cursor_y;
|
||||||
|
short int width; /* width of the screen buffer */
|
||||||
|
short int height; /* height of the screen buffer */
|
||||||
|
short int attr; /* default attribute */
|
||||||
|
short int win_left; /* window actually displayed by renderer */
|
||||||
|
short int win_top; /* the rect area is expressed withing the */
|
||||||
|
short int win_right; /* boundaries of the screen buffer */
|
||||||
|
short int win_bottom;
|
||||||
|
short int max_width; /* maximum size (width x height) for the window */
|
||||||
|
short int max_height;
|
||||||
@END
|
@END
|
||||||
#define SET_CONSOLE_INFO_CURSOR 0x01
|
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM 0x01
|
||||||
#define SET_CONSOLE_INFO_TITLE 0x02
|
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS 0x02
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_SIZE 0x04
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_ATTR 0x08
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW 0x10
|
||||||
|
#define SET_CONSOLE_OUTPUT_INFO_MAX_SIZE 0x20
|
||||||
|
|
||||||
|
|
||||||
/* Get info about a console (output only) */
|
/* Get info about a console (output only) */
|
||||||
@REQ(get_console_info)
|
@REQ(get_console_output_info)
|
||||||
handle_t handle; /* handle to the console */
|
handle_t handle; /* handle to the console */
|
||||||
@REPLY
|
@REPLY
|
||||||
int cursor_size; /* size of cursor (percentage filled) */
|
short int cursor_size; /* size of cursor (percentage filled) */
|
||||||
int cursor_visible;/* cursor visibility flag */
|
short int cursor_visible;/* cursor visibility flag */
|
||||||
int pid; /* pid of xterm (hack) */
|
short int cursor_x; /* position of cursor (x, y) */
|
||||||
VARARG(title,string); /* console title */
|
short int cursor_y;
|
||||||
|
short int width; /* width of the screen buffer */
|
||||||
|
short int height; /* height of the screen buffer */
|
||||||
|
short int attr; /* default attribute */
|
||||||
|
short int win_left; /* window actually displayed by renderer */
|
||||||
|
short int win_top; /* the rect area is expressed withing the */
|
||||||
|
short int win_right; /* boundaries of the screen buffer */
|
||||||
|
short int win_bottom;
|
||||||
|
short int max_width; /* maximum size (width x height) for the window */
|
||||||
|
short int max_height;
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Add input records to a console input queue */
|
/* Add input records to a console input queue */
|
||||||
@REQ(write_console_input)
|
@REQ(write_console_input)
|
||||||
handle_t handle; /* handle to the console input */
|
handle_t handle; /* handle to the console input */
|
||||||
|
@ -764,6 +887,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
||||||
int written; /* number of records written */
|
int written; /* number of records written */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Fetch input records from a console input queue */
|
/* Fetch input records from a console input queue */
|
||||||
@REQ(read_console_input)
|
@REQ(read_console_input)
|
||||||
handle_t handle; /* handle to the console input */
|
handle_t handle; /* handle to the console input */
|
||||||
|
@ -774,6 +898,49 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* write data (chars and/or attributes) in a screen buffer */
|
||||||
|
@REQ(write_console_output)
|
||||||
|
handle_t handle; /* handle to the console input */
|
||||||
|
int mode; /* 0 for text, 1, for attributes, 2 for both */
|
||||||
|
/* bit3 (4) set if uniform pattern in data */
|
||||||
|
short int x; /* position where to start writing */
|
||||||
|
short int y;
|
||||||
|
VARARG(data,bytes); /* info to write */
|
||||||
|
@REPLY
|
||||||
|
int written; /* number of bytes actually written */
|
||||||
|
@END
|
||||||
|
#define WRITE_CONSOLE_MODE_TEXT 0x00
|
||||||
|
#define WRITE_CONSOLE_MODE_ATTR 0x01
|
||||||
|
#define WRITE_CONSOLE_MODE_TEXTATTR 0x02
|
||||||
|
#define WRITE_CONSOLE_MODE_TEXTSTDATTR 0x03
|
||||||
|
#define WRITE_CONSOLE_MODE_UNIFORM 0x04
|
||||||
|
|
||||||
|
|
||||||
|
/* read data (chars and/or attrubutes) from a screen buffer */
|
||||||
|
@REQ(read_console_output)
|
||||||
|
handle_t handle; /* handle to the console input */
|
||||||
|
short int x; /* position (x,y) where to start reading from */
|
||||||
|
short int y;
|
||||||
|
short int w; /* size of area to read from (width x height) */
|
||||||
|
short int h;
|
||||||
|
@REPLY
|
||||||
|
short int eff_w; /* effective width read */
|
||||||
|
short int eff_h; /* effective height read */
|
||||||
|
VARARG(data,bytes);
|
||||||
|
@END
|
||||||
|
|
||||||
|
/* move a rect (of data) in screen buffer content */
|
||||||
|
@REQ(move_console_output)
|
||||||
|
handle_t handle; /* handle to the console output */
|
||||||
|
short int x_src; /* position (x, y) of rect to start moving from */
|
||||||
|
short int y_src;
|
||||||
|
short int x_dst; /* position (x, y) of rect to move to */
|
||||||
|
short int y_dst;
|
||||||
|
short int w; /* size of the rect (width, height) to move */
|
||||||
|
short int h;
|
||||||
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Create a change notification */
|
/* Create a change notification */
|
||||||
@REQ(create_change_notification)
|
@REQ(create_change_notification)
|
||||||
int subtree; /* watch all the subtree */
|
int subtree; /* watch all the subtree */
|
||||||
|
|
|
@ -118,14 +118,22 @@ DECL_HANDLER(get_socket_event);
|
||||||
DECL_HANDLER(enable_socket_event);
|
DECL_HANDLER(enable_socket_event);
|
||||||
DECL_HANDLER(alloc_console);
|
DECL_HANDLER(alloc_console);
|
||||||
DECL_HANDLER(free_console);
|
DECL_HANDLER(free_console);
|
||||||
|
DECL_HANDLER(get_console_renderer_events);
|
||||||
DECL_HANDLER(open_console);
|
DECL_HANDLER(open_console);
|
||||||
DECL_HANDLER(set_console_fd);
|
|
||||||
DECL_HANDLER(get_console_mode);
|
DECL_HANDLER(get_console_mode);
|
||||||
DECL_HANDLER(set_console_mode);
|
DECL_HANDLER(set_console_mode);
|
||||||
DECL_HANDLER(set_console_info);
|
DECL_HANDLER(set_console_input_info);
|
||||||
DECL_HANDLER(get_console_info);
|
DECL_HANDLER(get_console_input_info);
|
||||||
|
DECL_HANDLER(append_console_input_history);
|
||||||
|
DECL_HANDLER(get_console_input_history);
|
||||||
|
DECL_HANDLER(create_console_output);
|
||||||
|
DECL_HANDLER(set_console_output_info);
|
||||||
|
DECL_HANDLER(get_console_output_info);
|
||||||
DECL_HANDLER(write_console_input);
|
DECL_HANDLER(write_console_input);
|
||||||
DECL_HANDLER(read_console_input);
|
DECL_HANDLER(read_console_input);
|
||||||
|
DECL_HANDLER(write_console_output);
|
||||||
|
DECL_HANDLER(read_console_output);
|
||||||
|
DECL_HANDLER(move_console_output);
|
||||||
DECL_HANDLER(create_change_notification);
|
DECL_HANDLER(create_change_notification);
|
||||||
DECL_HANDLER(create_mapping);
|
DECL_HANDLER(create_mapping);
|
||||||
DECL_HANDLER(open_mapping);
|
DECL_HANDLER(open_mapping);
|
||||||
|
@ -264,14 +272,22 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
(req_handler)req_enable_socket_event,
|
(req_handler)req_enable_socket_event,
|
||||||
(req_handler)req_alloc_console,
|
(req_handler)req_alloc_console,
|
||||||
(req_handler)req_free_console,
|
(req_handler)req_free_console,
|
||||||
|
(req_handler)req_get_console_renderer_events,
|
||||||
(req_handler)req_open_console,
|
(req_handler)req_open_console,
|
||||||
(req_handler)req_set_console_fd,
|
|
||||||
(req_handler)req_get_console_mode,
|
(req_handler)req_get_console_mode,
|
||||||
(req_handler)req_set_console_mode,
|
(req_handler)req_set_console_mode,
|
||||||
(req_handler)req_set_console_info,
|
(req_handler)req_set_console_input_info,
|
||||||
(req_handler)req_get_console_info,
|
(req_handler)req_get_console_input_info,
|
||||||
|
(req_handler)req_append_console_input_history,
|
||||||
|
(req_handler)req_get_console_input_history,
|
||||||
|
(req_handler)req_create_console_output,
|
||||||
|
(req_handler)req_set_console_output_info,
|
||||||
|
(req_handler)req_get_console_output_info,
|
||||||
(req_handler)req_write_console_input,
|
(req_handler)req_write_console_input,
|
||||||
(req_handler)req_read_console_input,
|
(req_handler)req_read_console_input,
|
||||||
|
(req_handler)req_write_console_output,
|
||||||
|
(req_handler)req_read_console_output,
|
||||||
|
(req_handler)req_move_console_output,
|
||||||
(req_handler)req_create_change_notification,
|
(req_handler)req_create_change_notification,
|
||||||
(req_handler)req_create_mapping,
|
(req_handler)req_create_mapping,
|
||||||
(req_handler)req_open_mapping,
|
(req_handler)req_open_mapping,
|
||||||
|
|
203
server/trace.c
203
server/trace.c
|
@ -721,6 +721,7 @@ static void dump_create_file_reply( const struct create_file_request *req )
|
||||||
static void dump_alloc_file_handle_request( const struct alloc_file_handle_request *req )
|
static void dump_alloc_file_handle_request( const struct alloc_file_handle_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " access=%08x,", req->access );
|
fprintf( stderr, " access=%08x,", req->access );
|
||||||
|
fprintf( stderr, " inherit=%d,", req->inherit );
|
||||||
fprintf( stderr, " fd=%d", req->fd );
|
fprintf( stderr, " fd=%d", req->fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,24 +882,37 @@ static void dump_enable_socket_event_request( const struct enable_socket_event_r
|
||||||
static void dump_alloc_console_request( const struct alloc_console_request *req )
|
static void dump_alloc_console_request( const struct alloc_console_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " access=%08x,", req->access );
|
fprintf( stderr, " access=%08x,", req->access );
|
||||||
fprintf( stderr, " inherit=%d", req->inherit );
|
fprintf( stderr, " inherit=%d,", req->inherit );
|
||||||
|
fprintf( stderr, " pid=%p", req->pid );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_alloc_console_reply( const struct alloc_console_request *req )
|
static void dump_alloc_console_reply( const struct alloc_console_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle_in=%d,", req->handle_in );
|
fprintf( stderr, " handle_in=%d,", req->handle_in );
|
||||||
fprintf( stderr, " handle_out=%d", req->handle_out );
|
fprintf( stderr, " event=%d", req->event );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_free_console_request( const struct free_console_request *req )
|
static void dump_free_console_request( const struct free_console_request *req )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_get_console_renderer_events_request( const struct get_console_renderer_events_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_console_renderer_events_reply( const struct get_console_renderer_events_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " data=" );
|
||||||
|
cur_pos += dump_varargs_bytes( req );
|
||||||
|
}
|
||||||
|
|
||||||
static void dump_open_console_request( const struct open_console_request *req )
|
static void dump_open_console_request( const struct open_console_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " output=%d,", req->output );
|
fprintf( stderr, " from=%d,", req->from );
|
||||||
fprintf( stderr, " access=%08x,", req->access );
|
fprintf( stderr, " access=%08x,", req->access );
|
||||||
fprintf( stderr, " inherit=%d", req->inherit );
|
fprintf( stderr, " inherit=%d,", req->inherit );
|
||||||
|
fprintf( stderr, " share=%d", req->share );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_open_console_reply( const struct open_console_request *req )
|
static void dump_open_console_reply( const struct open_console_request *req )
|
||||||
|
@ -906,14 +920,6 @@ static void dump_open_console_reply( const struct open_console_request *req )
|
||||||
fprintf( stderr, " handle=%d", req->handle );
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_set_console_fd_request( const struct set_console_fd_request *req )
|
|
||||||
{
|
|
||||||
fprintf( stderr, " handle=%d,", req->handle );
|
|
||||||
fprintf( stderr, " fd_in=%d,", req->fd_in );
|
|
||||||
fprintf( stderr, " fd_out=%d,", req->fd_out );
|
|
||||||
fprintf( stderr, " pid=%d", req->pid );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_get_console_mode_request( const struct get_console_mode_request *req )
|
static void dump_get_console_mode_request( const struct get_console_mode_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%d", req->handle );
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
@ -930,28 +936,102 @@ static void dump_set_console_mode_request( const struct set_console_mode_request
|
||||||
fprintf( stderr, " mode=%d", req->mode );
|
fprintf( stderr, " mode=%d", req->mode );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_set_console_info_request( const struct set_console_info_request *req )
|
static void dump_set_console_input_info_request( const struct set_console_input_info_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " mask=%d,", req->mask );
|
||||||
|
fprintf( stderr, " active_sb=%d,", req->active_sb );
|
||||||
|
fprintf( stderr, " history_mode=%d,", req->history_mode );
|
||||||
|
fprintf( stderr, " history_size=%d,", req->history_size );
|
||||||
|
fprintf( stderr, " title=" );
|
||||||
|
cur_pos += dump_varargs_unicode_str( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_console_input_info_request( const struct get_console_input_info_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_console_input_info_reply( const struct get_console_input_info_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " history_mode=%d,", req->history_mode );
|
||||||
|
fprintf( stderr, " history_size=%d,", req->history_size );
|
||||||
|
fprintf( stderr, " history_index=%d,", req->history_index );
|
||||||
|
fprintf( stderr, " title=" );
|
||||||
|
cur_pos += dump_varargs_unicode_str( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_append_console_input_history_request( const struct append_console_input_history_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " line=" );
|
||||||
|
cur_pos += dump_varargs_unicode_str( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_console_input_history_request( const struct get_console_input_history_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " index=%d", req->index );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_console_input_history_reply( const struct get_console_input_history_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " line=" );
|
||||||
|
cur_pos += dump_varargs_unicode_str( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_create_console_output_request( const struct create_console_output_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle_in=%d,", req->handle_in );
|
||||||
|
fprintf( stderr, " access=%d,", req->access );
|
||||||
|
fprintf( stderr, " share=%d,", req->share );
|
||||||
|
fprintf( stderr, " inherit=%d", req->inherit );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_create_console_output_reply( const struct create_console_output_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle_out=%d", req->handle_out );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_set_console_output_info_request( const struct set_console_output_info_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%d,", req->handle );
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
fprintf( stderr, " mask=%d,", req->mask );
|
fprintf( stderr, " mask=%d,", req->mask );
|
||||||
fprintf( stderr, " cursor_size=%d,", req->cursor_size );
|
fprintf( stderr, " cursor_size=%d,", req->cursor_size );
|
||||||
fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
|
fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
|
||||||
fprintf( stderr, " title=" );
|
fprintf( stderr, " cursor_x=%d,", req->cursor_x );
|
||||||
cur_pos += dump_varargs_string( req );
|
fprintf( stderr, " cursor_y=%d,", req->cursor_y );
|
||||||
|
fprintf( stderr, " width=%d,", req->width );
|
||||||
|
fprintf( stderr, " height=%d,", req->height );
|
||||||
|
fprintf( stderr, " attr=%d,", req->attr );
|
||||||
|
fprintf( stderr, " win_left=%d,", req->win_left );
|
||||||
|
fprintf( stderr, " win_top=%d,", req->win_top );
|
||||||
|
fprintf( stderr, " win_right=%d,", req->win_right );
|
||||||
|
fprintf( stderr, " win_bottom=%d,", req->win_bottom );
|
||||||
|
fprintf( stderr, " max_width=%d,", req->max_width );
|
||||||
|
fprintf( stderr, " max_height=%d", req->max_height );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_get_console_info_request( const struct get_console_info_request *req )
|
static void dump_get_console_output_info_request( const struct get_console_output_info_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%d", req->handle );
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_get_console_info_reply( const struct get_console_info_request *req )
|
static void dump_get_console_output_info_reply( const struct get_console_output_info_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " cursor_size=%d,", req->cursor_size );
|
fprintf( stderr, " cursor_size=%d,", req->cursor_size );
|
||||||
fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
|
fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
|
||||||
fprintf( stderr, " pid=%d,", req->pid );
|
fprintf( stderr, " cursor_x=%d,", req->cursor_x );
|
||||||
fprintf( stderr, " title=" );
|
fprintf( stderr, " cursor_y=%d,", req->cursor_y );
|
||||||
cur_pos += dump_varargs_string( req );
|
fprintf( stderr, " width=%d,", req->width );
|
||||||
|
fprintf( stderr, " height=%d,", req->height );
|
||||||
|
fprintf( stderr, " attr=%d,", req->attr );
|
||||||
|
fprintf( stderr, " win_left=%d,", req->win_left );
|
||||||
|
fprintf( stderr, " win_top=%d,", req->win_top );
|
||||||
|
fprintf( stderr, " win_right=%d,", req->win_right );
|
||||||
|
fprintf( stderr, " win_bottom=%d,", req->win_bottom );
|
||||||
|
fprintf( stderr, " max_width=%d,", req->max_width );
|
||||||
|
fprintf( stderr, " max_height=%d", req->max_height );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_write_console_input_request( const struct write_console_input_request *req )
|
static void dump_write_console_input_request( const struct write_console_input_request *req )
|
||||||
|
@ -979,6 +1059,49 @@ static void dump_read_console_input_reply( const struct read_console_input_reque
|
||||||
cur_pos += dump_varargs_input_records( req );
|
cur_pos += dump_varargs_input_records( req );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_write_console_output_request( const struct write_console_output_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " mode=%d,", req->mode );
|
||||||
|
fprintf( stderr, " x=%d,", req->x );
|
||||||
|
fprintf( stderr, " y=%d,", req->y );
|
||||||
|
fprintf( stderr, " data=" );
|
||||||
|
cur_pos += dump_varargs_bytes( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_write_console_output_reply( const struct write_console_output_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " written=%d", req->written );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_read_console_output_request( const struct read_console_output_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " x=%d,", req->x );
|
||||||
|
fprintf( stderr, " y=%d,", req->y );
|
||||||
|
fprintf( stderr, " w=%d,", req->w );
|
||||||
|
fprintf( stderr, " h=%d", req->h );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_read_console_output_reply( const struct read_console_output_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " eff_w=%d,", req->eff_w );
|
||||||
|
fprintf( stderr, " eff_h=%d,", req->eff_h );
|
||||||
|
fprintf( stderr, " data=" );
|
||||||
|
cur_pos += dump_varargs_bytes( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_move_console_output_request( const struct move_console_output_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " x_src=%d,", req->x_src );
|
||||||
|
fprintf( stderr, " y_src=%d,", req->y_src );
|
||||||
|
fprintf( stderr, " x_dst=%d,", req->x_dst );
|
||||||
|
fprintf( stderr, " y_dst=%d,", req->y_dst );
|
||||||
|
fprintf( stderr, " w=%d,", req->w );
|
||||||
|
fprintf( stderr, " h=%d", req->h );
|
||||||
|
}
|
||||||
|
|
||||||
static void dump_create_change_notification_request( const struct create_change_notification_request *req )
|
static void dump_create_change_notification_request( const struct create_change_notification_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " subtree=%d,", req->subtree );
|
fprintf( stderr, " subtree=%d,", req->subtree );
|
||||||
|
@ -1955,14 +2078,22 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_enable_socket_event_request,
|
(dump_func)dump_enable_socket_event_request,
|
||||||
(dump_func)dump_alloc_console_request,
|
(dump_func)dump_alloc_console_request,
|
||||||
(dump_func)dump_free_console_request,
|
(dump_func)dump_free_console_request,
|
||||||
|
(dump_func)dump_get_console_renderer_events_request,
|
||||||
(dump_func)dump_open_console_request,
|
(dump_func)dump_open_console_request,
|
||||||
(dump_func)dump_set_console_fd_request,
|
|
||||||
(dump_func)dump_get_console_mode_request,
|
(dump_func)dump_get_console_mode_request,
|
||||||
(dump_func)dump_set_console_mode_request,
|
(dump_func)dump_set_console_mode_request,
|
||||||
(dump_func)dump_set_console_info_request,
|
(dump_func)dump_set_console_input_info_request,
|
||||||
(dump_func)dump_get_console_info_request,
|
(dump_func)dump_get_console_input_info_request,
|
||||||
|
(dump_func)dump_append_console_input_history_request,
|
||||||
|
(dump_func)dump_get_console_input_history_request,
|
||||||
|
(dump_func)dump_create_console_output_request,
|
||||||
|
(dump_func)dump_set_console_output_info_request,
|
||||||
|
(dump_func)dump_get_console_output_info_request,
|
||||||
(dump_func)dump_write_console_input_request,
|
(dump_func)dump_write_console_input_request,
|
||||||
(dump_func)dump_read_console_input_request,
|
(dump_func)dump_read_console_input_request,
|
||||||
|
(dump_func)dump_write_console_output_request,
|
||||||
|
(dump_func)dump_read_console_output_request,
|
||||||
|
(dump_func)dump_move_console_output_request,
|
||||||
(dump_func)dump_create_change_notification_request,
|
(dump_func)dump_create_change_notification_request,
|
||||||
(dump_func)dump_create_mapping_request,
|
(dump_func)dump_create_mapping_request,
|
||||||
(dump_func)dump_open_mapping_request,
|
(dump_func)dump_open_mapping_request,
|
||||||
|
@ -2098,14 +2229,22 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)dump_alloc_console_reply,
|
(dump_func)dump_alloc_console_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
|
(dump_func)dump_get_console_renderer_events_reply,
|
||||||
(dump_func)dump_open_console_reply,
|
(dump_func)dump_open_console_reply,
|
||||||
(dump_func)0,
|
|
||||||
(dump_func)dump_get_console_mode_reply,
|
(dump_func)dump_get_console_mode_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)dump_get_console_info_reply,
|
(dump_func)dump_get_console_input_info_reply,
|
||||||
|
(dump_func)0,
|
||||||
|
(dump_func)dump_get_console_input_history_reply,
|
||||||
|
(dump_func)dump_create_console_output_reply,
|
||||||
|
(dump_func)0,
|
||||||
|
(dump_func)dump_get_console_output_info_reply,
|
||||||
(dump_func)dump_write_console_input_reply,
|
(dump_func)dump_write_console_input_reply,
|
||||||
(dump_func)dump_read_console_input_reply,
|
(dump_func)dump_read_console_input_reply,
|
||||||
|
(dump_func)dump_write_console_output_reply,
|
||||||
|
(dump_func)dump_read_console_output_reply,
|
||||||
|
(dump_func)0,
|
||||||
(dump_func)dump_create_change_notification_reply,
|
(dump_func)dump_create_change_notification_reply,
|
||||||
(dump_func)dump_create_mapping_reply,
|
(dump_func)dump_create_mapping_reply,
|
||||||
(dump_func)dump_open_mapping_reply,
|
(dump_func)dump_open_mapping_reply,
|
||||||
|
@ -2241,14 +2380,22 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"enable_socket_event",
|
"enable_socket_event",
|
||||||
"alloc_console",
|
"alloc_console",
|
||||||
"free_console",
|
"free_console",
|
||||||
|
"get_console_renderer_events",
|
||||||
"open_console",
|
"open_console",
|
||||||
"set_console_fd",
|
|
||||||
"get_console_mode",
|
"get_console_mode",
|
||||||
"set_console_mode",
|
"set_console_mode",
|
||||||
"set_console_info",
|
"set_console_input_info",
|
||||||
"get_console_info",
|
"get_console_input_info",
|
||||||
|
"append_console_input_history",
|
||||||
|
"get_console_input_history",
|
||||||
|
"create_console_output",
|
||||||
|
"set_console_output_info",
|
||||||
|
"get_console_output_info",
|
||||||
"write_console_input",
|
"write_console_input",
|
||||||
"read_console_input",
|
"read_console_input",
|
||||||
|
"write_console_output",
|
||||||
|
"read_console_output",
|
||||||
|
"move_console_output",
|
||||||
"create_change_notification",
|
"create_change_notification",
|
||||||
"create_mapping",
|
"create_mapping",
|
||||||
"open_mapping",
|
"open_mapping",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
%formats =
|
%formats =
|
||||||
(
|
(
|
||||||
"int" => "%d",
|
"int" => "%d",
|
||||||
|
"short int" => "%d",
|
||||||
"char" => "%c",
|
"char" => "%c",
|
||||||
"unsigned char" => "%02x",
|
"unsigned char" => "%02x",
|
||||||
"unsigned short"=> "%04x",
|
"unsigned short"=> "%04x",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
DEFS = @DLLFLAGS@ -D__WINE__
|
DEFS = @DLLFLAGS@ -D__WINE__ -DBINDIR="\"$(bindir)\""
|
||||||
TOPSRCDIR = @top_srcdir@
|
TOPSRCDIR = @top_srcdir@
|
||||||
TOPOBJDIR = ..
|
TOPOBJDIR = ..
|
||||||
SRCDIR = @srcdir@
|
SRCDIR = @srcdir@
|
||||||
|
@ -8,6 +8,7 @@ MODULE = win32
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
console.c \
|
console.c \
|
||||||
device.c \
|
device.c \
|
||||||
|
editline.c \
|
||||||
except.c \
|
except.c \
|
||||||
file.c \
|
file.c \
|
||||||
init.c \
|
init.c \
|
||||||
|
|
2998
win32/console.c
2998
win32/console.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,708 @@
|
||||||
|
/*
|
||||||
|
* line edition function for Win32 console
|
||||||
|
*
|
||||||
|
* Copyright 2001 Eric Pouech
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wincon.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "debugtools.h"
|
||||||
|
|
||||||
|
DEFAULT_DEBUG_CHANNEL(console);
|
||||||
|
|
||||||
|
/* console.c */
|
||||||
|
extern int CONSOLE_GetHistory(int idx, WCHAR* buf, int buf_len);
|
||||||
|
extern BOOL CONSOLE_AppendHistory(const WCHAR *p);
|
||||||
|
extern unsigned int CONSOLE_GetNumHistoryEntries(void);
|
||||||
|
|
||||||
|
struct WCEL_Context;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WCHAR val; /* vk or unicode char */
|
||||||
|
void (*func)(struct WCEL_Context* ctx);
|
||||||
|
} KeyEntry;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD keyState; /* keyState (from INPUT_RECORD) to match */
|
||||||
|
BOOL chkChar; /* check vk or char */
|
||||||
|
KeyEntry* entries; /* array of entries */
|
||||||
|
} KeyMap;
|
||||||
|
|
||||||
|
typedef struct WCEL_Context {
|
||||||
|
WCHAR* line; /* the line being edited */
|
||||||
|
size_t alloc; /* number of WCHAR in line */
|
||||||
|
unsigned len; /* number of chars in line */
|
||||||
|
unsigned ofs; /* offset for cursor in current line */
|
||||||
|
WCHAR* yanked; /* yanked line */
|
||||||
|
unsigned mark; /* marked point (emacs mode only) */
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO csbi; /* current state (initial cursor, window size, attribute) */
|
||||||
|
HANDLE hConIn;
|
||||||
|
HANDLE hConOut;
|
||||||
|
unsigned done : 1, /* to 1 when we're done with editing */
|
||||||
|
error : 1; /* to 1 when an error occurred in the editing */
|
||||||
|
unsigned histSize;
|
||||||
|
unsigned histPos;
|
||||||
|
WCHAR* histCurr;
|
||||||
|
} WCEL_Context;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void WCEL_Dump(WCEL_Context* ctx, const char* pfx)
|
||||||
|
{
|
||||||
|
MESSAGE("%s: [line=%s[alloc=%u] ofs=%u len=%u start=(%d,%d) mask=%c%c\n"
|
||||||
|
"\t\thist=(size=%u pos=%u curr=%s)\n",
|
||||||
|
pfx, debugstr_w(ctx->line), ctx->alloc, ctx->ofs, ctx->len,
|
||||||
|
ctx->csbi.dwCursorPosition.X, ctx->csbi.dwCursorPosition.Y,
|
||||||
|
ctx->done ? 'D' : 'd', ctx->error ? 'E' : 'e',
|
||||||
|
ctx->histSize, ctx->histPos, debugstr_w(ctx->histCurr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
*
|
||||||
|
* Console helper functions
|
||||||
|
*
|
||||||
|
* ====================================================================*/
|
||||||
|
|
||||||
|
static BOOL WCEL_Get(WCEL_Context* ctx, INPUT_RECORD* ir)
|
||||||
|
{
|
||||||
|
DWORD retv;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* data available ? */
|
||||||
|
if (ReadConsoleInputW(ctx->hConIn, ir, 1, &retv) && retv == 1)
|
||||||
|
return TRUE;
|
||||||
|
/* then wait... */
|
||||||
|
switch (WaitForSingleObject(ctx->hConIn, INFINITE))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* we have checked that hConIn was a console handle (could be sb) */
|
||||||
|
ERR("Shouldn't happen\n");
|
||||||
|
/* fall thru */
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
ctx->error = 1;
|
||||||
|
ERR("hmm bad situation\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void WCEL_Beep(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
Beep(400, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline COORD WCEL_GetCoord(WCEL_Context* ctx, int ofs)
|
||||||
|
{
|
||||||
|
COORD c;
|
||||||
|
c.X = ctx->csbi.dwCursorPosition.X + ofs;
|
||||||
|
c.Y = ctx->csbi.dwCursorPosition.Y;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void WCEL_GetRect(WCEL_Context* ctx, LPSMALL_RECT sr, int beg, int end)
|
||||||
|
{
|
||||||
|
sr->Left = ctx->csbi.dwCursorPosition.X + beg;
|
||||||
|
sr->Top = ctx->csbi.dwCursorPosition.Y;
|
||||||
|
sr->Right = ctx->csbi.dwCursorPosition.X + end;
|
||||||
|
sr->Bottom = ctx->csbi.dwCursorPosition.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
*
|
||||||
|
* context manipulation functions
|
||||||
|
*
|
||||||
|
* ====================================================================*/
|
||||||
|
|
||||||
|
static BOOL WCEL_Grow(WCEL_Context* ctx, size_t len)
|
||||||
|
{
|
||||||
|
if (ctx->csbi.dwCursorPosition.X + ctx->ofs + len >= ctx->csbi.dwSize.X)
|
||||||
|
{
|
||||||
|
FIXME("Current implementation doesn't allow edition to spray across several lines\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->len + len >= ctx->alloc)
|
||||||
|
{
|
||||||
|
WCHAR* newline;
|
||||||
|
newline = HeapReAlloc(GetProcessHeap(), 0, ctx->line, sizeof(WCHAR) * (ctx->alloc + 32));
|
||||||
|
if (!newline) return FALSE;
|
||||||
|
ctx->line = newline;
|
||||||
|
ctx->alloc += 32;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_DeleteString(WCEL_Context* ctx, int beg, int end)
|
||||||
|
{
|
||||||
|
SMALL_RECT scl, clp;
|
||||||
|
CHAR_INFO ci;
|
||||||
|
|
||||||
|
if (end < ctx->len)
|
||||||
|
memmove(&ctx->line[beg], &ctx->line[end], (ctx->len - end) * sizeof(WCHAR));
|
||||||
|
/* make the source rect bigger than the actual rect to that the part outside the clip
|
||||||
|
* rect (before the scroll) will get redrawn after the scroll
|
||||||
|
*/
|
||||||
|
WCEL_GetRect(ctx, &scl, end, ctx->len + end - beg);
|
||||||
|
WCEL_GetRect(ctx, &clp, beg, ctx->len);
|
||||||
|
|
||||||
|
ci.Char.UnicodeChar = ' ';
|
||||||
|
ci.Attributes = ctx->csbi.wAttributes;
|
||||||
|
ScrollConsoleScreenBufferW(ctx->hConOut, &scl, &clp, WCEL_GetCoord(ctx, beg), &ci);
|
||||||
|
|
||||||
|
ctx->len -= end - beg;
|
||||||
|
ctx->line[ctx->len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_InsertString(WCEL_Context* ctx, const WCHAR* str)
|
||||||
|
{
|
||||||
|
size_t len = lstrlenW(str);
|
||||||
|
|
||||||
|
if (!len || !WCEL_Grow(ctx, len)) return;
|
||||||
|
if (ctx->len > ctx->ofs)
|
||||||
|
memmove(&ctx->line[ctx->ofs + len], &ctx->line[ctx->ofs], (ctx->len - ctx->ofs) * sizeof(WCHAR));
|
||||||
|
memcpy(&ctx->line[ctx->ofs], str, len * sizeof(WCHAR));
|
||||||
|
ctx->len += len;
|
||||||
|
ctx->line[ctx->len] = 0;
|
||||||
|
WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs], ctx->len - ctx->ofs,
|
||||||
|
WCEL_GetCoord(ctx, ctx->ofs), NULL);
|
||||||
|
ctx->ofs += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_InsertChar(WCEL_Context* ctx, WCHAR c)
|
||||||
|
{
|
||||||
|
WCHAR buffer[2];
|
||||||
|
|
||||||
|
/* do not insert 0..31 control characters */
|
||||||
|
if (c < ' ')
|
||||||
|
{
|
||||||
|
if (c != '\t') return;
|
||||||
|
}
|
||||||
|
buffer[0] = c;
|
||||||
|
buffer[1] = 0;
|
||||||
|
WCEL_InsertString(ctx, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_SaveYank(WCEL_Context* ctx, int beg, int end)
|
||||||
|
{
|
||||||
|
int len = end - beg;
|
||||||
|
ctx->yanked = HeapReAlloc(GetProcessHeap(), 0, ctx->yanked, (len + 1) * sizeof(WCHAR));
|
||||||
|
if (!ctx->yanked) return;
|
||||||
|
memcpy(ctx->yanked, &ctx->line[beg], len * sizeof(WCHAR));
|
||||||
|
ctx->yanked[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME NTDLL doesn't export iswalnum, and I don't want to link in msvcrt when most
|
||||||
|
* of the data lay in unicode lib
|
||||||
|
*/
|
||||||
|
static inline BOOL WCEL_iswalnum(WCHAR wc)
|
||||||
|
{
|
||||||
|
return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int WCEL_GetLeftWordTransition(WCEL_Context* ctx, int ofs)
|
||||||
|
{
|
||||||
|
ofs--;
|
||||||
|
while (ofs >= 0 && !WCEL_iswalnum(ctx->line[ofs])) ofs--;
|
||||||
|
while (ofs >= 0 && WCEL_iswalnum(ctx->line[ofs])) ofs--;
|
||||||
|
if (ofs >= 0) ofs++;
|
||||||
|
return max(ofs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int WCEL_GetRightWordTransition(WCEL_Context* ctx, int ofs)
|
||||||
|
{
|
||||||
|
ofs++;
|
||||||
|
while (ofs <= ctx->len && !WCEL_iswalnum(ctx->line[ofs])) ofs++;
|
||||||
|
while (ofs <= ctx->len && WCEL_iswalnum(ctx->line[ofs])) ofs++;
|
||||||
|
return min(ofs, ctx->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static WCHAR* WCEL_GetHistory(WCEL_Context* ctx, int idx)
|
||||||
|
{
|
||||||
|
WCHAR* ptr;
|
||||||
|
|
||||||
|
if (idx == ctx->histSize - 1)
|
||||||
|
{
|
||||||
|
ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(ctx->histCurr) + 1) * sizeof(WCHAR));
|
||||||
|
lstrcpyW(ptr, ctx->histCurr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int len = CONSOLE_GetHistory(idx, NULL, 0);
|
||||||
|
|
||||||
|
if ((ptr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
|
||||||
|
{
|
||||||
|
CONSOLE_GetHistory(idx, ptr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_HistoryInit(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
ctx->histPos = CONSOLE_GetNumHistoryEntries();
|
||||||
|
ctx->histSize = ctx->histPos + 1;
|
||||||
|
ctx->histCurr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToHist(WCEL_Context* ctx, int idx)
|
||||||
|
{
|
||||||
|
WCHAR* data = WCEL_GetHistory(ctx, idx);
|
||||||
|
int len = lstrlenW(data) + 1;
|
||||||
|
|
||||||
|
/* save current line edition for recall when needed (FIXME seems broken to me) */
|
||||||
|
if (ctx->histPos == ctx->histSize - 1)
|
||||||
|
{
|
||||||
|
if (ctx->histCurr) HeapFree(GetProcessHeap(), 0, ctx->histCurr);
|
||||||
|
ctx->histCurr = HeapAlloc(GetProcessHeap(), 0, (ctx->len + 1) * sizeof(WCHAR));
|
||||||
|
memcpy(ctx->histCurr, ctx->line, (ctx->len + 1) * sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
/* need to clean also the screen if new string is shorter than old one */
|
||||||
|
WCEL_DeleteString(ctx, 0, ctx->len);
|
||||||
|
ctx->ofs = 0;
|
||||||
|
/* insert new string */
|
||||||
|
if (WCEL_Grow(ctx, len))
|
||||||
|
{
|
||||||
|
WCEL_InsertString(ctx, data);
|
||||||
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
|
ctx->histPos = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
*
|
||||||
|
* basic edition functions
|
||||||
|
*
|
||||||
|
* ====================================================================*/
|
||||||
|
|
||||||
|
static void WCEL_Done(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (!WCEL_Grow(ctx, 1)) return;
|
||||||
|
ctx->line[ctx->len++] = '\n';
|
||||||
|
ctx->line[ctx->len] = 0;
|
||||||
|
WriteConsoleA(ctx->hConOut, "\n", 1, NULL, NULL);
|
||||||
|
ctx->done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveLeft(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->ofs > 0) ctx->ofs--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveRight(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->ofs < ctx->len) ctx->ofs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToLeftWord(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
int new_ofs = WCEL_GetLeftWordTransition(ctx, ctx->ofs);
|
||||||
|
if (new_ofs != ctx->ofs) ctx->ofs = new_ofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToRightWord(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
int new_ofs = WCEL_GetRightWordTransition(ctx, ctx->ofs);
|
||||||
|
if (new_ofs != ctx->ofs) ctx->ofs = new_ofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToBeg(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
ctx->ofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToEnd(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
ctx->ofs = ctx->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_SetMark(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
ctx->mark = ctx->ofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_ExchangeMark(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
unsigned tmp;
|
||||||
|
|
||||||
|
if (ctx->mark > ctx->len) return;
|
||||||
|
tmp = ctx->ofs;
|
||||||
|
ctx->ofs = ctx->mark;
|
||||||
|
ctx->mark = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_CopyMarkedZone(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
unsigned beg, end;
|
||||||
|
|
||||||
|
if (ctx->mark > ctx->len || ctx->mark == ctx->ofs) return;
|
||||||
|
if (ctx->mark > ctx->ofs)
|
||||||
|
{
|
||||||
|
beg = ctx->ofs; end = ctx->mark;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beg = ctx->mark; end = ctx->ofs;
|
||||||
|
}
|
||||||
|
WCEL_SaveYank(ctx, beg, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_TransposeChar(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
WCHAR c;
|
||||||
|
|
||||||
|
if (!ctx->ofs || ctx->ofs == ctx->len) return;
|
||||||
|
|
||||||
|
c = ctx->line[ctx->ofs];
|
||||||
|
ctx->line[ctx->ofs] = ctx->line[ctx->ofs - 1];
|
||||||
|
ctx->line[ctx->ofs - 1] = c;
|
||||||
|
|
||||||
|
WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs - 1], 2, WCEL_GetCoord(ctx, ctx->ofs - 1), NULL);
|
||||||
|
ctx->ofs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_TransposeWords(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
FIXME("NIY\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_LowerCaseWord(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
int new_ofs = WCEL_GetRightWordTransition(ctx, ctx->ofs);
|
||||||
|
if (new_ofs != ctx->ofs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = ctx->ofs; i <= new_ofs; i++)
|
||||||
|
ctx->line[i] = tolowerW(ctx->line[i]);
|
||||||
|
WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs], new_ofs - ctx->ofs + 1,
|
||||||
|
WCEL_GetCoord(ctx, ctx->ofs), NULL);
|
||||||
|
ctx->ofs = new_ofs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_UpperCaseWord(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
int new_ofs = WCEL_GetRightWordTransition(ctx, ctx->ofs);
|
||||||
|
if (new_ofs != ctx->ofs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = ctx->ofs; i <= new_ofs; i++)
|
||||||
|
ctx->line[i] = toupperW(ctx->line[i]);
|
||||||
|
WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs], new_ofs - ctx->ofs + 1,
|
||||||
|
WCEL_GetCoord(ctx, ctx->ofs), NULL);
|
||||||
|
ctx->ofs = new_ofs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_CapitalizeWord(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
int new_ofs = WCEL_GetRightWordTransition(ctx, ctx->ofs);
|
||||||
|
if (new_ofs != ctx->ofs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ctx->line[ctx->ofs] = toupperW(ctx->line[ctx->ofs]);
|
||||||
|
for (i = ctx->ofs + 1; i <= new_ofs; i++)
|
||||||
|
ctx->line[i] = tolowerW(ctx->line[i]);
|
||||||
|
WriteConsoleOutputCharacterW(ctx->hConOut, &ctx->line[ctx->ofs], new_ofs - ctx->ofs + 1,
|
||||||
|
WCEL_GetCoord(ctx, ctx->ofs), NULL);
|
||||||
|
ctx->ofs = new_ofs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_Yank(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
WCEL_InsertString(ctx, ctx->yanked);
|
||||||
|
HeapFree(GetProcessHeap(), 0, ctx->yanked);
|
||||||
|
ctx->yanked = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_KillToEndOfLine(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
WCEL_SaveYank(ctx, ctx->ofs, ctx->len);
|
||||||
|
WCEL_DeleteString(ctx, ctx->ofs, ctx->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_KillMarkedZone(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
unsigned beg, end;
|
||||||
|
|
||||||
|
if (ctx->mark > ctx->len || ctx->mark == ctx->ofs) return;
|
||||||
|
if (ctx->mark > ctx->ofs)
|
||||||
|
{
|
||||||
|
beg = ctx->ofs; end = ctx->mark;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beg = ctx->mark; end = ctx->ofs;
|
||||||
|
}
|
||||||
|
WCEL_SaveYank(ctx, beg, end);
|
||||||
|
WCEL_DeleteString(ctx, beg, end);
|
||||||
|
ctx->ofs = beg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_DeletePrevChar(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->ofs)
|
||||||
|
{
|
||||||
|
WCEL_DeleteString(ctx, ctx->ofs - 1, ctx->ofs);
|
||||||
|
ctx->ofs--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_DeleteCurrChar(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->ofs < ctx->len)
|
||||||
|
WCEL_DeleteString(ctx, ctx->ofs, ctx->ofs + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_DeleteLeftWord(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
int new_ofs = WCEL_GetLeftWordTransition(ctx, ctx->ofs);
|
||||||
|
if (new_ofs != ctx->ofs)
|
||||||
|
{
|
||||||
|
WCEL_DeleteString(ctx, new_ofs, ctx->ofs);
|
||||||
|
ctx->ofs = new_ofs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_DeleteRightWord(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
int new_ofs = WCEL_GetRightWordTransition(ctx, ctx->ofs);
|
||||||
|
if (new_ofs != ctx->ofs)
|
||||||
|
{
|
||||||
|
WCEL_DeleteString(ctx, ctx->ofs, new_ofs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToPrevHist(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->histPos) WCEL_MoveToHist(ctx, ctx->histPos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToNextHist(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->histPos < ctx->histSize - 1) WCEL_MoveToHist(ctx, ctx->histPos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToFirstHist(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->histPos != 0) WCEL_MoveToHist(ctx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WCEL_MoveToLastHist(WCEL_Context* ctx)
|
||||||
|
{
|
||||||
|
if (ctx->histPos != ctx->histSize - 1) WCEL_MoveToHist(ctx, ctx->histSize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
*
|
||||||
|
* Key Maps
|
||||||
|
*
|
||||||
|
* ====================================================================*/
|
||||||
|
|
||||||
|
#define CTRL(x) ((x) - '@')
|
||||||
|
static KeyEntry StdKeyMap[] =
|
||||||
|
{
|
||||||
|
{/*BACK*/0x08, WCEL_DeletePrevChar },
|
||||||
|
{/*RETURN*/0x0d, WCEL_Done },
|
||||||
|
{/*DEL*/127, WCEL_DeleteCurrChar },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static KeyEntry EmacsKeyMapCtrl[] =
|
||||||
|
{
|
||||||
|
{ CTRL('@'), WCEL_SetMark },
|
||||||
|
{ CTRL('A'), WCEL_MoveToBeg },
|
||||||
|
{ CTRL('B'), WCEL_MoveLeft },
|
||||||
|
/* C */
|
||||||
|
{ CTRL('D'), WCEL_DeleteCurrChar },
|
||||||
|
{ CTRL('E'), WCEL_MoveToEnd },
|
||||||
|
{ CTRL('F'), WCEL_MoveRight },
|
||||||
|
{ CTRL('G'), WCEL_Beep },
|
||||||
|
{ CTRL('H'), WCEL_DeletePrevChar },
|
||||||
|
/* I: meaningless (or tab ???) */
|
||||||
|
{ CTRL('J'), WCEL_Done },
|
||||||
|
{ CTRL('K'), WCEL_KillToEndOfLine },
|
||||||
|
/* L: [NIY] redraw the whole stuff */
|
||||||
|
{ CTRL('M'), WCEL_Done },
|
||||||
|
{ CTRL('N'), WCEL_MoveToNextHist },
|
||||||
|
/* O; insert line... meaningless */
|
||||||
|
{ CTRL('P'), WCEL_MoveToPrevHist },
|
||||||
|
/* Q: [NIY] quoting... */
|
||||||
|
/* R: [NIY] search backwards... */
|
||||||
|
/* S: [NIY] search forwards... */
|
||||||
|
{ CTRL('T'), WCEL_TransposeChar },
|
||||||
|
/* U: [NIY] set repeat count... */
|
||||||
|
/* V: paragraph down... meaningless */
|
||||||
|
{ CTRL('W'), WCEL_KillMarkedZone },
|
||||||
|
{ CTRL('X'), WCEL_ExchangeMark },
|
||||||
|
{ CTRL('Y'), WCEL_Yank },
|
||||||
|
/* Z: meaningless */
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static KeyEntry EmacsKeyMapAlt[] =
|
||||||
|
{
|
||||||
|
{/*DEL*/127, WCEL_DeleteLeftWord },
|
||||||
|
{ '<', WCEL_MoveToFirstHist },
|
||||||
|
{ '>', WCEL_MoveToLastHist },
|
||||||
|
{ '?', WCEL_Beep },
|
||||||
|
{ 'b', WCEL_MoveToLeftWord },
|
||||||
|
{ 'c', WCEL_CapitalizeWord },
|
||||||
|
{ 'd', WCEL_DeleteRightWord },
|
||||||
|
{ 'f', WCEL_MoveToRightWord },
|
||||||
|
{ 'l', WCEL_LowerCaseWord },
|
||||||
|
{ 't', WCEL_TransposeWords },
|
||||||
|
{ 'u', WCEL_UpperCaseWord },
|
||||||
|
{ 'w', WCEL_CopyMarkedZone },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static KeyEntry EmacsKeyMapExtended[] =
|
||||||
|
{
|
||||||
|
{/*VK_PRIOR*/0x21, WCEL_MoveToPrevHist },
|
||||||
|
{/*VK_NEXT*/0x22, WCEL_MoveToNextHist },
|
||||||
|
{/*VK_RIGHT*/0x27, WCEL_MoveRight },
|
||||||
|
{/*VK_LEFT*/0x25, WCEL_MoveLeft },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static KeyMap EmacsKeyMap[] =
|
||||||
|
{
|
||||||
|
{0x00000000, 1, StdKeyMap},
|
||||||
|
{0x00000001, 1, EmacsKeyMapAlt}, /* left alt */
|
||||||
|
{0x00000002, 1, EmacsKeyMapAlt}, /* right alt */
|
||||||
|
{0x00000004, 1, EmacsKeyMapCtrl}, /* left ctrl */
|
||||||
|
{0x00000008, 1, EmacsKeyMapCtrl}, /* right ctrl */
|
||||||
|
{0x00000100, 0, EmacsKeyMapExtended},
|
||||||
|
{0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static KeyEntry Win32KeyMapExtended[] =
|
||||||
|
{
|
||||||
|
{/*VK_LEFT*/ 0x25, WCEL_MoveLeft },
|
||||||
|
{/*VK_RIGHT*/0x27, WCEL_MoveRight },
|
||||||
|
{/*VK_HOME*/ 0x24, WCEL_MoveToBeg },
|
||||||
|
{/*VK_END*/ 0x23, WCEL_MoveToEnd },
|
||||||
|
{/*VK_UP*/ 0x26, WCEL_MoveToPrevHist },
|
||||||
|
{/*VK_DOWN*/ 0x28, WCEL_MoveToNextHist },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static KeyEntry Win32KeyMapCtrlExtended[] =
|
||||||
|
{
|
||||||
|
{/*VK_LEFT*/ 0x25, WCEL_MoveToLeftWord },
|
||||||
|
{/*VK_RIGHT*/0x27, WCEL_MoveToRightWord },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyMap Win32KeyMap[] =
|
||||||
|
{
|
||||||
|
{0x00000000, 1, StdKeyMap},
|
||||||
|
{0x00000100, 0, Win32KeyMapExtended},
|
||||||
|
{0x00000104, 0, Win32KeyMapCtrlExtended},
|
||||||
|
{0x00000108, 0, Win32KeyMapCtrlExtended},
|
||||||
|
{0, 0, 0}
|
||||||
|
};
|
||||||
|
#undef CTRL
|
||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
*
|
||||||
|
* Read line master function
|
||||||
|
*
|
||||||
|
* ====================================================================*/
|
||||||
|
|
||||||
|
WCHAR* CONSOLE_Readline(HANDLE hConsoleIn, int use_emacs)
|
||||||
|
{
|
||||||
|
WCEL_Context ctx;
|
||||||
|
INPUT_RECORD ir;
|
||||||
|
KeyMap* km;
|
||||||
|
KeyEntry* ke;
|
||||||
|
unsigned ofs;
|
||||||
|
void (*func)(struct WCEL_Context* ctx);
|
||||||
|
|
||||||
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
|
ctx.hConIn = hConsoleIn;
|
||||||
|
WCEL_HistoryInit(&ctx);
|
||||||
|
if ((ctx.hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
|
||||||
|
OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE ||
|
||||||
|
!GetConsoleScreenBufferInfo(ctx.hConOut, &ctx.csbi))
|
||||||
|
return NULL;
|
||||||
|
if (!WCEL_Grow(&ctx, 1))
|
||||||
|
{
|
||||||
|
CloseHandle(ctx.hConOut);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctx.line[0] = 0;
|
||||||
|
|
||||||
|
/* EPP WCEL_Dump(&ctx, "init"); */
|
||||||
|
|
||||||
|
while (!ctx.done && !ctx.error && WCEL_Get(&ctx, &ir))
|
||||||
|
{
|
||||||
|
if (ir.EventType != KEY_EVENT || !ir.Event.KeyEvent.bKeyDown) continue;
|
||||||
|
TRACE("key%s repeatCount=%u, keyCode=%02x scanCode=%02x char=%02x keyState=%08lx\n",
|
||||||
|
ir.Event.KeyEvent.bKeyDown ? "Down" : "Up ", ir.Event.KeyEvent.wRepeatCount,
|
||||||
|
ir.Event.KeyEvent.wVirtualKeyCode, ir.Event.KeyEvent.wVirtualScanCode,
|
||||||
|
ir.Event.KeyEvent.uChar.UnicodeChar, ir.Event.KeyEvent.dwControlKeyState);
|
||||||
|
|
||||||
|
/* EPP WCEL_Dump(&ctx, "before func"); */
|
||||||
|
ofs = ctx.ofs;
|
||||||
|
|
||||||
|
func = NULL;
|
||||||
|
for (km = (use_emacs) ? EmacsKeyMap : Win32KeyMap; km->entries != NULL; km++)
|
||||||
|
{
|
||||||
|
if (km->keyState != ir.Event.KeyEvent.dwControlKeyState)
|
||||||
|
continue;
|
||||||
|
if (km->chkChar)
|
||||||
|
{
|
||||||
|
for (ke = &km->entries[0]; ke->func != 0; ke++)
|
||||||
|
if (ke->val == ir.Event.KeyEvent.uChar.UnicodeChar) break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (ke = &km->entries[0]; ke->func != 0; ke++)
|
||||||
|
if (ke->val == ir.Event.KeyEvent.wVirtualKeyCode) break;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (ke->func)
|
||||||
|
{
|
||||||
|
func = ke->func;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func)
|
||||||
|
(func)(&ctx);
|
||||||
|
else if (!(ir.Event.KeyEvent.dwControlKeyState & (ENHANCED_KEY|LEFT_ALT_PRESSED)))
|
||||||
|
WCEL_InsertChar(&ctx, ir.Event.KeyEvent.uChar.UnicodeChar);
|
||||||
|
else TRACE("Dropped event\n");
|
||||||
|
|
||||||
|
/* EPP WCEL_Dump(&ctx, "after func"); */
|
||||||
|
if (ctx.ofs != ofs)
|
||||||
|
SetConsoleCursorPosition(ctx.hConOut, WCEL_GetCoord(&ctx, ctx.ofs));
|
||||||
|
}
|
||||||
|
if (ctx.error)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, ctx.line);
|
||||||
|
ctx.line = NULL;
|
||||||
|
}
|
||||||
|
if (ctx.line)
|
||||||
|
CONSOLE_AppendHistory(ctx.line);
|
||||||
|
|
||||||
|
CloseHandle(ctx.hConOut);
|
||||||
|
if (ctx.histCurr) HeapFree(GetProcessHeap(), 0, ctx.histCurr);
|
||||||
|
return ctx.line;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue