Implemented support for console titles

Display console title while swapping consoles with alt-tab
Use alt-tab now instead of alt-q

svn path=/trunk/; revision=1997
This commit is contained in:
Phillip Susi 2001-06-22 02:11:44 +00:00
parent 4eb1d89866
commit 3e22e847c2
4 changed files with 204 additions and 44 deletions

View file

@ -196,13 +196,26 @@ typedef struct
CLIENT_ID Cid;
} CSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY, * PCSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY;
typedef struct
{
HANDLE Console;
DWORD Length;
WCHAR Title[1];
} CSRSS_SET_TITLE_REQUEST, *PCSRSS_SET_TITLE_REQUEST;
#define CSRSS_MAX_WRITE_CONSOLE_REQUEST (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_REQUEST))
#define CSRSS_MAX_SET_TITLE_REQUEST (MAX_MESSAGE_DATA - sizeof( HANDLE ) - sizeof( DWORD ) - sizeof( ULONG ) - sizeof( LPC_MESSAGE_HEADER ))
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST ))
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB ((MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST )) / 2)
#define CSRSS_MAX_READ_CONSOLE_REQUEST (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_READ_CONSOLE_REQUEST ))
#define CSRSS_MAX_TITLE_LENGTH 50
#define CSRSS_CREATE_PROCESS (0x0)
#define CSRSS_TERMINATE_PROCESS (0x1)
#define CSRSS_WRITE_CONSOLE (0x2)
@ -224,6 +237,7 @@ typedef struct
#define CSRSS_SET_MODE (0x12)
#define CSRSS_CREATE_SCREEN_BUFFER (0x13)
#define CSRSS_SET_SCREEN_BUFFER (0x14)
#define CSRSS_SET_TITLE (0x15)
typedef struct
{
@ -249,6 +263,7 @@ typedef struct
CSRSS_GET_CONSOLE_MODE_REQUEST GetConsoleModeRequest;
CSRSS_CREATE_SCREEN_BUFFER_REQUEST CreateScreenBufferRequest;
CSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST SetActiveScreenBufferRequest;
CSRSS_SET_TITLE_REQUEST SetTitleRequest;
} Data;
} CSRSS_API_REQUEST, *PCSRSS_API_REQUEST;

View file

@ -1,4 +1,4 @@
/* $Id: console.c,v 1.32 2001/04/04 22:21:30 dwelch Exp $
/* $Id: console.c,v 1.33 2001/06/22 02:11:43 phreak Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
@ -1814,8 +1814,43 @@ SetConsoleTitleW(
LPCWSTR lpConsoleTitle
)
{
/* --- TO DO --- */
return FALSE;
PCSRSS_API_REQUEST Request;
CSRSS_API_REPLY Reply;
NTSTATUS Status;
unsigned int c;
Request = RtlAllocateHeap(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
if (Request == NULL)
{
return(FALSE);
}
Request->Type = CSRSS_SET_TITLE;
Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE );
for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
// add null
Request->Data.SetTitleRequest.Title[c] = 0;
Request->Data.SetTitleRequest.Length = c;
Status = CsrClientCallServer(Request,
&Reply,
sizeof(CSRSS_SET_TITLE_REQUEST) +
c +
sizeof( LPC_MESSAGE_HEADER ) +
sizeof( ULONG ),
sizeof(CSRSS_API_REPLY));
if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
{
RtlFreeHeap( GetProcessHeap(), 0, Request );
SetLastErrorByStatus (Status);
return(FALSE);
}
RtlFreeHeap( GetProcessHeap(), 0, Request );
return TRUE;
}
@ -1831,36 +1866,43 @@ SetConsoleTitleA(
LPCSTR lpConsoleTitle
)
{
wchar_t WideTitle [MAX_CONSOLE_TITLE_LENGTH];
char AnsiTitle [MAX_CONSOLE_TITLE_LENGTH];
INT nWideTitle;
if (!lpConsoleTitle) return FALSE;
ZeroMemory( WideTitle, sizeof WideTitle );
nWideTitle = lstrlenA(lpConsoleTitle);
if (!lstrcpynA(
AnsiTitle,
lpConsoleTitle,
nWideTitle
))
{
return FALSE;
}
AnsiTitle[nWideTitle] = '\0';
#if 0
if ( MultiByteToWideChar(
CP_ACP, // ANSI code page
MB_PRECOMPOSED, // character-type options
AnsiTitle, // address of string to map
nWideTitle, // number of characters in string
(LPWSTR) WideTitle, // address of wide-character buffer
(-1) // size of buffer: -1=...\0
))
{
return SetConsoleTitleW( (LPWSTR) WideTitle );
}
#endif
return FALSE;
PCSRSS_API_REQUEST Request;
CSRSS_API_REPLY Reply;
NTSTATUS Status;
unsigned int c;
Request = RtlAllocateHeap(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
if (Request == NULL)
{
return(FALSE);
}
Request->Type = CSRSS_SET_TITLE;
Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE );
for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
// add null
Request->Data.SetTitleRequest.Title[c] = 0;
Request->Data.SetTitleRequest.Length = c;
Status = CsrClientCallServer(Request,
&Reply,
sizeof(CSRSS_SET_TITLE_REQUEST) +
c +
sizeof( LPC_MESSAGE_HEADER ) +
sizeof( ULONG ),
sizeof(CSRSS_API_REPLY));
if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
{
RtlFreeHeap( GetProcessHeap(), 0, Request );
SetLastErrorByStatus (Status);
return(FALSE);
}
RtlFreeHeap( GetProcessHeap(), 0, Request );
return TRUE;
}

View file

@ -62,6 +62,7 @@ typedef struct CSRSS_CONSOLE_t
PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
WORD Mode; /* Console mode flags */
WORD EchoCount; /* count of chars to echo, in line buffered mode */
UNICODE_STRING Title; /* Title of console */
} CSRSS_CONSOLE, *PCSRSS_CONSOLE;
typedef struct
@ -132,6 +133,8 @@ NTSTATUS CsrCreateScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQU
NTSTATUS CsrSetScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
NTSTATUS CsrSetTitle( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
/* print.c */
VOID DisplayString(LPCWSTR lpwString);
VOID PrintString (char* fmt, ...);

View file

@ -1,4 +1,4 @@
/* $Id: conio.c,v 1.18 2001/06/18 03:07:37 phreak Exp $
/* $Id: conio.c,v 1.19 2001/06/22 02:11:44 phreak Exp $
*
* reactos/subsys/csrss/api/conio.c
*
@ -353,7 +353,7 @@ NTSTATUS CsrInitConsoleScreenBuffer( PCSRSS_SCREEN_BUFFER Console )
Console->Header.Type = CSRSS_SCREEN_BUFFER_MAGIC;
Console->Header.ReferenceCount = 0;
Console->MaxX = PhysicalConsoleSize.X;
Console->MaxY = PhysicalConsoleSize.Y;
Console->MaxY = PhysicalConsoleSize.Y * 2;
Console->ShowX = 0;
Console->ShowY = 0;
Console->CurrentX = 0;
@ -389,6 +389,11 @@ VOID CsrDeleteScreenBuffer( PCSRSS_SCREEN_BUFFER Buffer )
NTSTATUS CsrInitConsole(PCSRSS_CONSOLE Console)
{
NTSTATUS Status;
Console->Title.MaximumLength = Console->Title.Length = 0;
Console->Title.Buffer = 0;
RtlCreateUnicodeString( &Console->Title, L"Command Prompt" );
Console->Header.ReferenceCount = 0;
Console->WaitingChars = 0;
@ -506,6 +511,7 @@ VOID CsrDrawConsole( PCSRSS_SCREEN_BUFFER Buff )
VOID CsrDeleteConsole( PCSRSS_CONSOLE Console )
{
ConsoleInput *Event;
DPRINT1( "CsrDeleteConsole\n" );
RtlEnterCriticalSection( &ActiveConsoleLock );
/* Drain input event queue */
while( Console->InputEvents.Flink != &Console->InputEvents )
@ -532,6 +538,7 @@ VOID CsrDeleteConsole( PCSRSS_CONSOLE Console )
if( !--Console->ActiveBuffer->Header.ReferenceCount )
CsrDeleteScreenBuffer( Console->ActiveBuffer );
NtClose( Console->ActiveEvent );
RtlFreeUnicodeString( &Console->Title );
RtlFreeHeap( CsrssApiHeap, 0, Console );
}
@ -602,6 +609,7 @@ VOID Console_Api( DWORD RefreshEvent )
HANDLE Events[2]; // 0 = keyboard, 1 = refresh
int c;
int updown;
PCSRSS_CONSOLE SwapConsole = 0; // console we are thinking about swapping with
Events[0] = 0;
Status = NtCreateEvent( &Events[0], STANDARD_RIGHTS_ALL, NULL, FALSE, FALSE );
@ -649,23 +657,91 @@ VOID Console_Api( DWORD RefreshEvent )
else break;
}
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&& KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == 'q' )
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&& KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_TAB )
if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
{
ANSI_STRING Title;
void * Buffer;
COORD *pos;
unsigned int src, dst;
/* alt-tab, swap consoles */
RtlEnterCriticalSection( &ActiveConsoleLock );
if( ActiveConsole->Next != ActiveConsole )
ActiveConsole = ActiveConsole->Next;
CsrDrawConsole( ActiveConsole->ActiveBuffer );
RtlLeaveCriticalSection( &ActiveConsoleLock );
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
// move SwapConsole to next console, and print its title
RtlEnterCriticalSection( &ActiveConsoleLock );
if( !SwapConsole )
SwapConsole = ActiveConsole;
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED )
SwapConsole = SwapConsole->Prev;
else SwapConsole = SwapConsole->Next;
Title.MaximumLength = RtlUnicodeStringToAnsiSize( &SwapConsole->Title );
Title.Length = 0;
Buffer = RtlAllocateHeap( CsrssApiHeap,
0,
sizeof( COORD ) + Title.MaximumLength );
pos = (COORD *)Buffer;
Title.Buffer = Buffer + sizeof( COORD );
/* this does not seem to work
RtlUnicodeStringToAnsiString( &Title, &SwapConsole->Title, FALSE ); */
// temp hack
for( src = 0, dst = 0; src < SwapConsole->Title.Length; src++, dst++ )
Title.Buffer[dst] = (char)SwapConsole->Title.Buffer[dst];
pos->Y = PhysicalConsoleSize.Y / 2;
pos->X = ( PhysicalConsoleSize.X - Title.MaximumLength ) / 2;
// redraw the console to clear off old title
CsrDrawConsole( ActiveConsole->ActiveBuffer );
Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
0,
0,
Buffer,
sizeof (COORD) + Title.MaximumLength );
if( !NT_SUCCESS( Status ) )
{
DPRINT1( "Error writing to console\n" );
}
RtlFreeHeap( CsrssApiHeap, 0, Buffer );
RtlLeaveCriticalSection( &ActiveConsoleLock );
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
else {
RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
continue;
}
else if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
else if( SwapConsole &&
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_MENU &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE )
{
// alt key released, swap consoles
PCSRSS_CONSOLE tmp;
RtlEnterCriticalSection( &ActiveConsoleLock );
if( SwapConsole != ActiveConsole )
{
// first remove swapconsole from the list
SwapConsole->Prev->Next = SwapConsole->Next;
SwapConsole->Next->Prev = SwapConsole->Prev;
// now insert before activeconsole
SwapConsole->Next = ActiveConsole;
SwapConsole->Prev = ActiveConsole->Prev;
ActiveConsole->Prev->Next = SwapConsole;
ActiveConsole->Prev = SwapConsole;
}
ActiveConsole = SwapConsole;
SwapConsole = 0;
CsrDrawConsole( ActiveConsole->ActiveBuffer );
RtlLeaveCriticalSection( &ActiveConsoleLock );
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
{
if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
{
@ -787,6 +863,8 @@ VOID Console_Api( DWORD RefreshEvent )
}
}
ActiveConsole->WaitingChars++;
if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT) )
NtSetEvent( ActiveConsole->ActiveEvent, 0 );
RtlLeaveCriticalSection( &ActiveConsoleLock );
}
}
@ -1296,3 +1374,25 @@ NTSTATUS CsrSetScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST
RtlLeaveCriticalSection( &ActiveConsoleLock );
return Reply->Status;
}
NTSTATUS CsrSetTitle( 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);
RtlEnterCriticalSection( &ActiveConsoleLock );
Status = CsrGetObject( ProcessData, Request->Data.SetTitleRequest.Console, (Object_t **)&Console );
if( !NT_SUCCESS( Status ) )
Reply->Status = Status;
else {
// copy title to console
RtlFreeUnicodeString( &Console->Title );
RtlCreateUnicodeString( &Console->Title, Request->Data.SetTitleRequest.Title );
Reply->Status = STATUS_SUCCESS;
}
RtlLeaveCriticalSection( &ActiveConsoleLock );
return Reply->Status;
}