Implemented console modes

svn path=/trunk/; revision=1264
This commit is contained in:
Phillip Susi
2000-07-11 04:09:25 +00:00
parent 041f614e06
commit cc05ca5acb
6 changed files with 199 additions and 27 deletions
+21
View File
@@ -152,6 +152,22 @@ typedef struct
CHAR Attrib;
} CSRSS_SET_ATTRIB_REQUEST, *PCSRSS_SET_ATTRIB_REQUEST;
typedef struct
{
HANDLE ConsoleHandle;
DWORD Mode;
} CSRSS_SET_CONSOLE_MODE_REQUEST, *PCSRSS_SET_CONSOLE_MODE_REQUEST;
typedef struct
{
HANDLE ConsoleHandle;
} CSRSS_GET_CONSOLE_MODE_REQUEST, *PCSRSS_GET_CONSOLE_MODE_REQUEST;
typedef struct
{
DWORD ConsoleMode;
} CSRSS_GET_CONSOLE_MODE_REPLY, *PCSRSS_GET_CONSOLE_MODE_REPLY;
#define CSRSS_MAX_WRITE_CONSOLE_REQUEST (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_REQUEST))
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST ))
@@ -176,6 +192,8 @@ typedef struct
#define CSRSS_GET_CURSOR_INFO (0xE)
#define CSRSS_SET_CURSOR_INFO (0xF)
#define CSRSS_SET_ATTRIB (0x10)
#define CSRSS_GET_MODE (0x11)
#define CSRSS_SET_MODE (0x12)
typedef struct
{
@@ -197,6 +215,8 @@ typedef struct
CSRSS_SET_CURSOR_INFO_REQUEST SetCursorInfoRequest;
CSRSS_GET_CURSOR_INFO_REQUEST GetCursorInfoRequest;
CSRSS_SET_ATTRIB_REQUEST SetAttribRequest;
CSRSS_SET_CONSOLE_MODE_REQUEST SetConsoleModeRequest;
CSRSS_GET_CONSOLE_MODE_REQUEST GetConsoleModeRequest;
} Data;
} CSRSS_API_REQUEST, *PCSRSS_API_REQUEST;
@@ -216,6 +236,7 @@ typedef struct
CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REPLY WriteConsoleOutputCharReply;
CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REPLY WriteConsoleOutputAttribReply;
CSRSS_GET_CURSOR_INFO_REPLY GetCursorInfoReply;
CSRSS_GET_CONSOLE_MODE_REPLY GetConsoleModeReply;
} Data;
} CSRSS_API_REPLY, *PCSRSS_API_REPLY;
+8 -7
View File
@@ -14,13 +14,14 @@
#define __INCLUDE_CONSOLE_H
/* GetConsoleMode */
#define ENABLE_LINE_INPUT (2)
#define ENABLE_ECHO_INPUT (4)
#define ENABLE_PROCESSED_INPUT (1)
#define ENABLE_WINDOW_INPUT (8)
#define ENABLE_MOUSE_INPUT (16)
#define ENABLE_PROCESSED_OUTPUT (1)
#define ENABLE_WRAP_AT_EOL_OUTPUT (2)
#define ENABLE_LINE_INPUT (0x02)
#define ENABLE_ECHO_INPUT (0x04)
#define ENABLE_PROCESSED_INPUT (0x01)
#define ENABLE_WINDOW_INPUT (0x08)
#define ENABLE_MOUSE_INPUT (0x0f)
#define CONSOLE_MODE_VALID (0x1f)
#define ENABLE_PROCESSED_OUTPUT (0x01)
#define ENABLE_WRAP_AT_EOL_OUTPUT (0x02)
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
+29 -5
View File
@@ -1,4 +1,4 @@
/* $Id: console.c,v 1.24 2000/07/01 17:07:00 ea Exp $
/* $Id: console.c,v 1.25 2000/07/11 04:06:42 phreak Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
@@ -801,8 +801,20 @@ GetConsoleMode(
LPDWORD lpMode
)
{
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
CSRSS_API_REQUEST Request;
CSRSS_API_REPLY Reply;
NTSTATUS Status;
Request.Type = CSRSS_GET_MODE;
Request.Data.GetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
{
SetLastErrorByStatus ( Status );
return FALSE;
}
*lpMode = Reply.Data.GetConsoleModeReply.ConsoleMode;
return TRUE;
}
@@ -895,8 +907,20 @@ SetConsoleMode(
DWORD dwMode
)
{
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return FALSE;
CSRSS_API_REQUEST Request;
CSRSS_API_REPLY Reply;
NTSTATUS Status;
Request.Type = CSRSS_SET_MODE;
Request.Data.SetConsoleModeRequest.ConsoleHandle = hConsoleHandle;
Request.Data.SetConsoleModeRequest.Mode = dwMode;
Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) )
{
SetLastErrorByStatus ( Status );
return FALSE;
}
return TRUE;
}
+7
View File
@@ -32,6 +32,9 @@ typedef struct CSRSS_CONSOLE_t
BYTE DefaultAttrib; /* default char attribute */
LIST_ENTRY InputEvents; /* List head for input event queue */
CONSOLE_CURSOR_INFO CursorInfo;
DWORD ConsoleMode;
WORD WaitingChars;
WORD WaitingLines; /* number of chars and lines in input queue */
} CSRSS_CONSOLE, *PCSRSS_CONSOLE;
typedef struct
@@ -94,6 +97,10 @@ NTSTATUS CsrSetCursorInfo( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST R
NTSTATUS CsrSetTextAttrib( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
NTSTATUS CsrSetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
NTSTATUS CsrGetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
/* print.c */
VOID DisplayString(LPCWSTR lpwString);
VOID PrintString (char* fmt, ...);
+131 -14
View File
@@ -1,4 +1,4 @@
/* $Id: conio.c,v 1.9 2000/07/07 01:16:50 phreak Exp $
/* $Id: conio.c,v 1.10 2000/07/11 04:09:25 phreak Exp $
*
* reactos/subsys/csrss/api/conio.c
*
@@ -105,7 +105,7 @@ NTSTATUS CsrReadConsole(PCSRSS_PROCESS_DATA ProcessData,
{
ConsoleInput *Input;
PCHAR Buffer;
int i;
int i = 0;
ULONG nNumberOfCharsToRead;
PCSRSS_CONSOLE Console;
NTSTATUS Status;
@@ -128,16 +128,34 @@ NTSTATUS CsrReadConsole(PCSRSS_PROCESS_DATA ProcessData,
return Status;
}
RtlEnterCriticalSection( &ActiveConsoleLock );
for (i=0; i<nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++ )
{
Input = (ConsoleInput *)Console->InputEvents.Flink;
Input->ListEntry.Blink->Flink = Input->ListEntry.Flink;
Input->ListEntry.Flink->Blink = Input->ListEntry.Blink;
if( Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE && Input->InputEvent.Event.KeyEvent.uChar.AsciiChar )
Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
else i--;
RtlFreeHeap( CsrssApiHeap, 0, Input );
}
if( !(Console->ConsoleMode & ENABLE_LINE_INPUT) || Console->WaitingLines )
for (; i<nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++ )
{
// remove input event from queue
Input = (ConsoleInput *)Console->InputEvents.Flink;
Input->ListEntry.Blink->Flink = Input->ListEntry.Flink;
Input->ListEntry.Flink->Blink = Input->ListEntry.Blink;
// only pay attention to valid ascii chars, on key down
if( Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
Input->InputEvent.Event.KeyEvent.uChar.AsciiChar )
{
Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
// process newline on line buffered mode
if( Console->ConsoleMode & ENABLE_LINE_INPUT &&
Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
{
Console->WaitingChars--;
Console->WaitingLines--;
RtlFreeHeap( CsrssApiHeap, 0, Input );
i++;
break;
}
}
else i--;
Console->WaitingChars--;
RtlFreeHeap( CsrssApiHeap, 0, Input );
}
Buffer[i] = 0;
RtlLeaveCriticalSection( &ActiveConsoleLock );
LpcReply->Data.ReadConsoleReply.NrCharactersRead = i;
LpcReply->Status = i ? STATUS_SUCCESS : STATUS_PENDING;
@@ -282,7 +300,10 @@ NTSTATUS CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData,
Console->CurrentX = 0;
Console->CurrentY = 0;
Console->ReferenceCount = 0;
Console->WaitingChars = 0;
Console->WaitingLines = 0;
Console->Type = CSRSS_CONSOLE_MAGIC;
Console->ConsoleMode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
Console->Buffer = RtlAllocateHeap( CsrssApiHeap, 0, Console->MaxX * Console->MaxY * 2 );
if( Console->Buffer == 0 )
return STATUS_INSUFFICIENT_RESOURCES;
@@ -486,6 +507,7 @@ VOID Console_Api( DWORD RefreshEvent )
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
HANDLE Events[2]; // 0 = keyboard, 1 = refresh
int c;
Events[0] = 0;
Status = NtCreateEvent( &Events[0], STANDARD_RIGHTS_ALL, NULL, FALSE, FALSE );
@@ -586,11 +608,48 @@ VOID Console_Api( DWORD RefreshEvent )
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
// echo to screen if enabled, but do not echo '\b' if there are no keys in buffer to delete
if( ActiveConsole->ConsoleMode & ENABLE_ECHO_INPUT &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar &&
( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\b' ||
ActiveConsole->InputEvents.Flink != &ActiveConsole->InputEvents ) )
{
CsrpWriteConsole( ActiveConsole, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
}
// process special keys if enabled
if( ActiveConsole->ConsoleMode & ENABLE_PROCESSED_INPUT )
switch( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar )
{
case '\b':
if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
for( c = 0; c < 2; c++ )
{
ConsoleInput *Input = ActiveConsole->InputEvents.Blink;
CHECKPOINT1;
ActiveConsole->InputEvents.Blink->Blink->Flink = &ActiveConsole->InputEvents;
ActiveConsole->InputEvents.Blink = ActiveConsole->InputEvents.Blink->Blink;
RtlFreeHeap( CsrssApiHeap, 0, Input );
}
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
RtlLeaveCriticalSection( &ActiveConsoleLock );
continue;
}
// add event to the queue
KeyEventRecord->ListEntry.Flink = &ActiveConsole->InputEvents;
KeyEventRecord->ListEntry.Blink = ActiveConsole->InputEvents.Blink;
ActiveConsole->InputEvents.Blink->Flink = &KeyEventRecord->ListEntry;
ActiveConsole->InputEvents.Blink = &KeyEventRecord->ListEntry;
NtSetEvent( ActiveConsole->ActiveEvent, 0 );
// if line input mode is enabled, only wake the client on enter key up
if( !(ActiveConsole->ConsoleMode & ENABLE_LINE_INPUT ) ||
( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE ) )
{
NtSetEvent( ActiveConsole->ActiveEvent, 0 );
ActiveConsole->WaitingLines++;
}
ActiveConsole->WaitingChars++;
RtlLeaveCriticalSection( &ActiveConsoleLock );
}
}
@@ -713,6 +772,7 @@ NTSTATUS CsrFillOutputChar( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST
if( Console == ActiveConsole )
CsrDrawConsole( Console );
RtlLeaveCriticalSection( &ActiveConsoleLock );
return Reply->Status;
}
NTSTATUS CsrReadInputEvent( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
@@ -735,12 +795,19 @@ NTSTATUS CsrReadInputEvent( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST
return Status;
}
RtlEnterCriticalSection( &ActiveConsoleLock );
if( Console->InputEvents.Flink != &Console->InputEvents )
// only get input if there is input, and we are not in line input mode, or if we are, if we have a whole line
if( Console->InputEvents.Flink != &Console->InputEvents &&
( !Console->ConsoleMode & ENABLE_LINE_INPUT || Console->WaitingLines ) )
{
Input = (ConsoleInput *)Console->InputEvents.Flink;
Input->ListEntry.Blink->Flink = Input->ListEntry.Flink;
Input->ListEntry.Flink->Blink = Input->ListEntry.Blink;
Reply->Data.ReadInputReply.Input = Input->InputEvent;
if( Console->ConsoleMode & ENABLE_LINE_INPUT &&
Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE &&
Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
Console->WaitingLines--;
Console->WaitingChars--;
RtlFreeHeap( CsrssApiHeap, 0, Input );
Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents) ? TRUE : FALSE;
Status = STATUS_SUCCESS;
@@ -914,6 +981,56 @@ NTSTATUS CsrSetTextAttrib( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST R
return Reply->Status = STATUS_SUCCESS;
}
NTSTATUS CsrSetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
{
NTSTATUS Status;
PCSRSS_CONSOLE Console;
Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
if( Request->Data.SetConsoleModeRequest.Mode & (~CONSOLE_MODE_VALID) ||
( Request->Data.SetConsoleModeRequest.Mode & (ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT) &&
!( Request->Data.SetConsoleModeRequest.Mode & ENABLE_LINE_INPUT ) ) )
{
Reply->Status = STATUS_INVALID_PARAMETER;
return Reply->Status;
}
Status = CsrGetObject( ProcessData, Request->Data.SetConsoleModeRequest.ConsoleHandle, (Object_t **)&Console );
if( !NT_SUCCESS( Status ) )
{
Reply->Status = Status;
return Status;
}
RtlEnterCriticalSection( &ActiveConsoleLock );
Console->ConsoleMode = Request->Data.SetConsoleModeRequest.Mode;
RtlLeaveCriticalSection( &ActiveConsoleLock );
Reply->Status = STATUS_SUCCESS;
return Reply->Status;
}
NTSTATUS CsrGetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
{
NTSTATUS Status;
PCSRSS_CONSOLE Console;
Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
Status = CsrGetObject( ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle, (Object_t **)&Console );
if( !NT_SUCCESS( Status ) )
{
Reply->Status = Status;
return Status;
}
RtlEnterCriticalSection( &ActiveConsoleLock );
Reply->Data.GetConsoleModeReply.ConsoleMode = Console->ConsoleMode;
RtlLeaveCriticalSection( &ActiveConsoleLock );
Reply->Status = STATUS_SUCCESS;
return Reply->Status;
}
+3 -1
View File
@@ -1,4 +1,4 @@
/* $Id: wapi.c,v 1.8 2000/05/26 05:40:20 phreak Exp $
/* $Id: wapi.c,v 1.9 2000/07/11 04:09:25 phreak Exp $
*
* reactos/subsys/csrss/api/wapi.c
*
@@ -42,6 +42,8 @@ static const CsrFunc CsrFuncs[] = {
CsrGetCursorInfo,
CsrSetCursorInfo,
CsrSetTextAttrib,
CsrGetConsoleMode,
CsrSetConsoleMode,
0 };
static void Thread_Api2(HANDLE ServerPort)