You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
436 lines
11 KiB
436 lines
11 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "vguitextwindow.h" |
|
#include <networkstringtabledefs.h> |
|
#include <cdll_client_int.h> |
|
#include <clientmode_shared.h> |
|
|
|
#include <vgui/IScheme.h> |
|
#include <vgui/ILocalize.h> |
|
#include <vgui/ISurface.h> |
|
#include <filesystem.h> |
|
#include <KeyValues.h> |
|
#include <convar.h> |
|
#include <vgui_controls/ImageList.h> |
|
|
|
#include <vgui_controls/TextEntry.h> |
|
#include <vgui_controls/Button.h> |
|
|
|
#include <game/client/iviewport.h> |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
using namespace vgui; |
|
extern INetworkStringTable *g_pStringTableInfoPanel; |
|
|
|
#define TEMP_HTML_FILE "textwindow_temp.html" |
|
|
|
ConVar cl_disablehtmlmotd( "cl_disablehtmlmotd", "0", FCVAR_ARCHIVE, "Disable HTML motds." ); |
|
|
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration |
|
// of options. Passing a command string is dangerous and allowed a server network |
|
// message to run arbitrary commands on the client. |
|
//============================================================================= |
|
CON_COMMAND( showinfo, "Shows a info panel: <type> <title> <message> [<command number>]" ) |
|
{ |
|
if ( !gViewPortInterface ) |
|
return; |
|
|
|
if ( args.ArgC() < 4 ) |
|
return; |
|
|
|
IViewPortPanel * panel = gViewPortInterface->FindPanelByName( PANEL_INFO ); |
|
|
|
if ( panel ) |
|
{ |
|
KeyValues *kv = new KeyValues("data"); |
|
kv->SetInt( "type", Q_atoi(args[ 1 ]) ); |
|
kv->SetString( "title", args[ 2 ] ); |
|
kv->SetString( "message", args[ 3 ] ); |
|
|
|
if ( args.ArgC() == 5 ) |
|
kv->SetString( "command", args[ 4 ] ); |
|
|
|
panel->SetData( kv ); |
|
|
|
gViewPortInterface->ShowPanel( panel, true ); |
|
|
|
kv->deleteThis(); |
|
} |
|
else |
|
{ |
|
Msg("Couldn't find info panel.\n" ); |
|
} |
|
} |
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CTextWindow::CTextWindow(IViewPort *pViewPort) : Frame(NULL, PANEL_INFO ) |
|
{ |
|
// initialize dialog |
|
m_pViewPort = pViewPort; |
|
|
|
// SetTitle("", true); |
|
|
|
m_szTitle[0] = '\0'; |
|
m_szMessage[0] = '\0'; |
|
m_szMessageFallback[0] = '\0'; |
|
m_nExitCommand = TEXTWINDOW_CMD_NONE; |
|
m_bShownURL = false; |
|
m_bUnloadOnDismissal = false; |
|
|
|
// load the new scheme early!! |
|
SetScheme("ClientScheme"); |
|
SetMoveable(false); |
|
SetSizeable(false); |
|
SetProportional(true); |
|
|
|
// hide the system buttons |
|
SetTitleBarVisible( false ); |
|
|
|
m_pTextMessage = new TextEntry( this, "TextMessage" ); |
|
m_pHTMLMessage = new CMOTDHTML( this,"HTMLMessage" ); |
|
m_pTitleLabel = new Label( this, "MessageTitle", "Message Title" ); |
|
m_pOK = new Button(this, "ok", "#PropertyDialog_OK"); |
|
|
|
m_pOK->SetCommand("okay"); |
|
m_pTextMessage->SetMultiline( true ); |
|
m_nContentType = TYPE_TEXT; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTextWindow::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings("Resource/UI/TextWindow.res"); |
|
|
|
Reset(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destructor |
|
//----------------------------------------------------------------------------- |
|
CTextWindow::~CTextWindow() |
|
{ |
|
// remove temp file again |
|
g_pFullFileSystem->RemoveFile( TEMP_HTML_FILE, "DEFAULT_WRITE_PATH" ); |
|
} |
|
|
|
void CTextWindow::Reset( void ) |
|
{ |
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [Forrest] Replace strange hard-coded default message with hard-coded error message. |
|
//============================================================================= |
|
V_strcpy_safe( m_szTitle, "Error loading info message." ); |
|
V_strcpy_safe( m_szMessage, "" ); |
|
V_strcpy_safe( m_szMessageFallback, "" ); |
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
m_nExitCommand = TEXTWINDOW_CMD_NONE; |
|
m_nContentType = TYPE_TEXT; |
|
m_bShownURL = false; |
|
m_bUnloadOnDismissal = false; |
|
Update(); |
|
} |
|
|
|
void CTextWindow::ShowText( const char *text ) |
|
{ |
|
m_pTextMessage->SetVisible( true ); |
|
m_pTextMessage->SetText( text ); |
|
m_pTextMessage->GotoTextStart(); |
|
} |
|
|
|
void CTextWindow::ShowURL( const char *URL, bool bAllowUserToDisable ) |
|
{ |
|
#ifdef _DEBUG |
|
Msg( "CTextWindow::ShowURL( %s )\n", URL ); |
|
#endif |
|
|
|
ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal(); |
|
if ( ( bAllowUserToDisable && cl_disablehtmlmotd.GetBool() ) || !mode->IsHTMLInfoPanelAllowed() ) |
|
{ |
|
Warning( "Blocking HTML info panel '%s'; Using plaintext instead.\n", URL ); |
|
|
|
// User has disabled HTML TextWindows. Show the fallback as text only. |
|
if ( g_pStringTableInfoPanel ) |
|
{ |
|
int index = g_pStringTableInfoPanel->FindStringIndex( "motd_text" ); |
|
if ( index != ::INVALID_STRING_INDEX ) |
|
{ |
|
int length = 0; |
|
const char *data = (const char *)g_pStringTableInfoPanel->GetStringUserData( index, &length ); |
|
if ( data && data[0] ) |
|
{ |
|
m_pHTMLMessage->SetVisible( false ); |
|
ShowText( data ); |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
|
|
m_pHTMLMessage->SetVisible( true ); |
|
m_pHTMLMessage->OpenURL( URL, NULL ); |
|
m_bShownURL = true; |
|
} |
|
|
|
void CTextWindow::ShowIndex( const char *entry ) |
|
{ |
|
const char *data = NULL; |
|
int length = 0; |
|
|
|
if ( NULL == g_pStringTableInfoPanel ) |
|
return; |
|
|
|
int index = g_pStringTableInfoPanel->FindStringIndex( m_szMessage ); |
|
|
|
if ( index != ::INVALID_STRING_INDEX ) |
|
data = (const char *)g_pStringTableInfoPanel->GetStringUserData( index, &length ); |
|
|
|
if ( !data || !data[0] ) |
|
return; // nothing to show |
|
|
|
// is this a web URL ? |
|
if ( !Q_strncmp( data, "http://", 7 ) || !Q_strncmp( data, "https://", 8 ) ) |
|
{ |
|
ShowURL( data ); |
|
return; |
|
} |
|
|
|
// try to figure out if this is HTML or not |
|
if ( data[0] != '<' ) |
|
{ |
|
ShowText( data ); |
|
return; |
|
} |
|
|
|
// data is a HTML, we have to write to a file and then load the file |
|
FileHandle_t hFile = g_pFullFileSystem->Open( TEMP_HTML_FILE, "wb", "DEFAULT_WRITE_PATH" ); |
|
|
|
if ( hFile == FILESYSTEM_INVALID_HANDLE ) |
|
return; |
|
|
|
g_pFullFileSystem->Write( data, length, hFile ); |
|
g_pFullFileSystem->Close( hFile ); |
|
|
|
if ( g_pFullFileSystem->Size( TEMP_HTML_FILE ) != (unsigned int)length ) |
|
return; // something went wrong while writing |
|
|
|
ShowFile( TEMP_HTML_FILE ); |
|
} |
|
|
|
void CTextWindow::ShowFile( const char *filename ) |
|
{ |
|
if ( Q_stristr( filename, ".htm" ) || Q_stristr( filename, ".html" ) ) |
|
{ |
|
// it's a local HTML file |
|
char localURL[ _MAX_PATH + 7 ]; |
|
Q_strncpy( localURL, "file://", sizeof( localURL ) ); |
|
|
|
char pPathData[ _MAX_PATH ]; |
|
g_pFullFileSystem->GetLocalPath( filename, pPathData, sizeof(pPathData) ); |
|
Q_strncat( localURL, pPathData, sizeof( localURL ), COPY_ALL_CHARACTERS ); |
|
|
|
ShowURL( localURL ); |
|
} |
|
else |
|
{ |
|
// read from local text from file |
|
FileHandle_t f = g_pFullFileSystem->Open( m_szMessage, "rb", "GAME" ); |
|
|
|
if ( !f ) |
|
return; |
|
|
|
char buffer[2048]; |
|
|
|
int size = MIN( g_pFullFileSystem->Size( f ), sizeof(buffer)-1 ); // just allow 2KB |
|
|
|
g_pFullFileSystem->Read( buffer, size, f ); |
|
g_pFullFileSystem->Close( f ); |
|
|
|
buffer[size]=0; //terminate string |
|
|
|
ShowText( buffer ); |
|
} |
|
} |
|
|
|
void CTextWindow::Update( void ) |
|
{ |
|
SetTitle( m_szTitle, false ); |
|
|
|
m_pTitleLabel->SetText( m_szTitle ); |
|
|
|
if ( m_pHTMLMessage ) |
|
m_pHTMLMessage->SetVisible( false ); |
|
m_pTextMessage->SetVisible( false ); |
|
|
|
if ( m_nContentType == TYPE_INDEX ) |
|
{ |
|
ShowIndex( m_szMessage ); |
|
} |
|
else if ( m_nContentType == TYPE_URL ) |
|
{ |
|
if ( !Q_strncmp( m_szMessage, "http://", 7 ) || !Q_strncmp( m_szMessage, "https://", 8 ) || !Q_stricmp( m_szMessage, "about:blank" ) ) |
|
{ |
|
ShowURL( m_szMessage ); |
|
} |
|
else |
|
{ |
|
// We should have trapped this at a higher level |
|
Assert( !"URL protocol is missing or blocked" ); |
|
} |
|
} |
|
else if ( m_nContentType == TYPE_FILE ) |
|
{ |
|
ShowFile( m_szMessage ); |
|
} |
|
else if ( m_nContentType == TYPE_TEXT ) |
|
{ |
|
ShowText( m_szMessage ); |
|
} |
|
else |
|
{ |
|
DevMsg("CTextWindow::Update: unknown content type %i\n", m_nContentType ); |
|
} |
|
} |
|
|
|
void CTextWindow::OnCommand( const char *command ) |
|
{ |
|
if (!Q_strcmp(command, "okay")) |
|
{ |
|
//============================================================================= |
|
// HPE_BEGIN: |
|
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration |
|
// of options. Passing a command string is dangerous and allowed a server network |
|
// message to run arbitrary commands on the client. |
|
//============================================================================= |
|
const char *pszCommand = NULL; |
|
switch ( m_nExitCommand ) |
|
{ |
|
case TEXTWINDOW_CMD_NONE: |
|
break; |
|
|
|
case TEXTWINDOW_CMD_JOINGAME: |
|
pszCommand = "joingame"; |
|
break; |
|
|
|
case TEXTWINDOW_CMD_CHANGETEAM: |
|
pszCommand = "changeteam"; |
|
break; |
|
|
|
case TEXTWINDOW_CMD_IMPULSE101: |
|
pszCommand = "impulse 101"; |
|
break; |
|
|
|
case TEXTWINDOW_CMD_MAPINFO: |
|
pszCommand = "mapinfo"; |
|
break; |
|
|
|
case TEXTWINDOW_CMD_CLOSED_HTMLPAGE: |
|
pszCommand = "closed_htmlpage"; |
|
break; |
|
|
|
case TEXTWINDOW_CMD_CHOOSETEAM: |
|
pszCommand = "chooseteam"; |
|
break; |
|
|
|
default: |
|
DevMsg("CTextWindow::OnCommand: unknown exit command value %i\n", m_nExitCommand ); |
|
break; |
|
} |
|
|
|
if ( pszCommand != NULL ) |
|
{ |
|
engine->ClientCmd_Unrestricted( pszCommand ); |
|
} |
|
//============================================================================= |
|
// HPE_END |
|
//============================================================================= |
|
|
|
m_pViewPort->ShowPanel( this, false ); |
|
} |
|
|
|
BaseClass::OnCommand(command); |
|
} |
|
|
|
void CTextWindow::OnKeyCodePressed( vgui::KeyCode code ) |
|
{ |
|
if ( code == KEY_XBUTTON_A || code == KEY_XBUTTON_B || code == STEAMCONTROLLER_A || code == STEAMCONTROLLER_B ) |
|
{ |
|
OnCommand( "okay" ); |
|
return; |
|
} |
|
|
|
BaseClass::OnKeyCodePressed(code); |
|
} |
|
|
|
void CTextWindow::SetData(KeyValues *data) |
|
{ |
|
SetData( data->GetInt( "type" ), data->GetString( "title" ), data->GetString( "msg" ), data->GetString( "msg_fallback" ), data->GetInt( "cmd" ), data->GetBool( "unload" ) ); |
|
} |
|
|
|
void CTextWindow::SetData( int type, const char *title, const char *message, const char *message_fallback, int command, bool bUnload ) |
|
{ |
|
Q_strncpy( m_szTitle, title, sizeof( m_szTitle ) ); |
|
Q_strncpy( m_szMessage, message, sizeof( m_szMessage ) ); |
|
Q_strncpy( m_szMessageFallback, message_fallback, sizeof( m_szMessageFallback ) ); |
|
|
|
m_nExitCommand = command; |
|
|
|
m_nContentType = type; |
|
m_bUnloadOnDismissal = bUnload; |
|
|
|
Update(); |
|
} |
|
|
|
void CTextWindow::ShowPanel( bool bShow ) |
|
{ |
|
if ( BaseClass::IsVisible() == bShow ) |
|
return; |
|
|
|
m_pViewPort->ShowBackGround( bShow ); |
|
|
|
if ( bShow ) |
|
{ |
|
Activate(); |
|
SetMouseInputEnabled( true ); |
|
} |
|
else |
|
{ |
|
SetVisible( false ); |
|
SetMouseInputEnabled( false ); |
|
|
|
if ( m_bUnloadOnDismissal && m_bShownURL && m_pHTMLMessage ) |
|
{ |
|
m_pHTMLMessage->OpenURL( "about:blank", NULL ); |
|
m_bShownURL = false; |
|
} |
|
} |
|
} |
|
|
|
bool CTextWindow::CMOTDHTML::OnStartRequest( const char *url, const char *target, const char *pchPostData, bool bIsRedirect ) |
|
{ |
|
if ( Q_strstr( url, "steam://" ) ) |
|
return false; |
|
|
|
return BaseClass::OnStartRequest( url, target, pchPostData, bIsRedirect ); |
|
}
|
|
|