423 lines
9.6 KiB
C++
423 lines
9.6 KiB
C++
#include "stdafx.h"
|
||
#include "Resource.h"
|
||
#include "Logger.h"
|
||
#include "NpcHtmlMessageDlg.h"
|
||
#include "L2Client.h"
|
||
|
||
extern HINSTANCE g_hInst;
|
||
|
||
NpcHtmlMessageDlg::NpcHtmlMessageDlg( void *pvL2Client )
|
||
{
|
||
m_hDlg = m_hWndParent = NULL;
|
||
m_html = NULL;
|
||
m_itemID = m_questID = 0;
|
||
m_npc = NULL;
|
||
m_pvL2Client = pvL2Client;
|
||
// childs
|
||
m_hWndHtml = m_hWndCombo = m_hWndBypassText = NULL;
|
||
}
|
||
|
||
NpcHtmlMessageDlg::~NpcHtmlMessageDlg()
|
||
{
|
||
destroyDialog();
|
||
if( m_html )
|
||
{
|
||
free( m_html );
|
||
m_html = NULL;
|
||
}
|
||
}
|
||
|
||
bool NpcHtmlMessageDlg::createDialog( HWND hWndParent )
|
||
{
|
||
m_hWndParent = hWndParent;
|
||
m_hDlg = CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_NPCHTML), hWndParent,
|
||
NpcHtmlMessageDlgProc, (LPARAM)this );
|
||
if( m_hDlg ) return true;
|
||
// error
|
||
m_hWndParent = NULL;
|
||
return false;
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::destroyDialog()
|
||
{
|
||
if( m_hDlg )
|
||
{
|
||
DestroyWindow( m_hDlg );
|
||
m_hDlg = NULL;
|
||
}
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::showWindow( bool bShow )
|
||
{
|
||
if( m_hDlg )
|
||
{
|
||
if( bShow ) ShowWindow( m_hDlg, SW_SHOWNORMAL );
|
||
else ShowWindow( m_hDlg, SW_HIDE );
|
||
}
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::displayNPCHTML( const TCHAR *html, L2Npc *pNpc,
|
||
unsigned int itemID, unsigned int questID )
|
||
{
|
||
if( !html ) return;
|
||
//
|
||
m_itemID = itemID;
|
||
m_questID = questID;
|
||
m_npc = pNpc;
|
||
if( m_html ) free( m_html );
|
||
m_html = _tcsdup( html );
|
||
//
|
||
NpcHtmlMessageDlg::wnd_initHtml( m_hDlg );
|
||
showWindow( true );
|
||
}
|
||
|
||
|
||
|
||
class NpcHtmlLink
|
||
{
|
||
public:
|
||
NpcHtmlLink() { text[0] = 0; bypass[0] = 0; next = NULL; }
|
||
~NpcHtmlLink() { if( next ) delete next; }
|
||
public:
|
||
wchar_t text[128];
|
||
wchar_t bypass[128];
|
||
NpcHtmlLink *next;
|
||
};
|
||
|
||
class NpcHtmlInfo
|
||
{
|
||
public:
|
||
NpcHtmlInfo()
|
||
{
|
||
html = NULL;
|
||
head = NULL;
|
||
}
|
||
~NpcHtmlInfo()
|
||
{
|
||
if( html ) free( html );
|
||
html = NULL;
|
||
if( head ) delete head;
|
||
head = NULL;
|
||
}
|
||
public:
|
||
wchar_t *html;
|
||
NpcHtmlLink *head;
|
||
};
|
||
|
||
void process_bypass( NpcHtmlInfo *info, wchar_t *tagHeader, wchar_t *tagTextStart )
|
||
{
|
||
// a action="bypass -h npc_268437990_Quest 1106_teleport_to_fantasy_isle" msg="811;Fantasy Island"
|
||
//log_error( LOG_OK, "[%S] [%S]\n", tagHeader, tagTextStart );
|
||
wchar_t bypass[128] = {0};
|
||
wchar_t *pbypass = bypass;
|
||
wchar_t text[128] = {0};
|
||
wchar_t *ptext = text;
|
||
wchar_t *w = wcschr( tagHeader, L'\"' );
|
||
if( !w ) return;
|
||
w++;
|
||
while( (*w) != L'\"' ) { (*pbypass) = (*w); pbypass++, w++; }
|
||
(*pbypass) = 0;
|
||
w = tagTextStart;
|
||
while( (*w) != L'<' ) { (*ptext) = (*w); ptext++, w++; }
|
||
(*ptext) = 0;
|
||
//
|
||
NpcHtmlLink *adding = new NpcHtmlLink();
|
||
wcscpy( adding->bypass, bypass );
|
||
wcscpy( adding->text, text );
|
||
adding->next = NULL;
|
||
//
|
||
if( !info->head ) info->head = adding;
|
||
else
|
||
{
|
||
NpcHtmlLink *cur = info->head;
|
||
while( cur->next ) cur = cur->next;
|
||
cur->next = adding;
|
||
}
|
||
}
|
||
|
||
NpcHtmlInfo *parse_NpcHtml( wchar_t *html )
|
||
{
|
||
if( !html ) return NULL;
|
||
NpcHtmlInfo *info = new NpcHtmlInfo();
|
||
//
|
||
info->html = (wchar_t *)malloc( 20480 );
|
||
if( !info->html ) { delete info; return NULL; }
|
||
info->html[0] = 0;
|
||
//
|
||
wchar_t *phtml = html;
|
||
wchar_t *pinfohtml = info->html;
|
||
wchar_t curChar = phtml[0];
|
||
wchar_t tagHeader[256] = {0};
|
||
wchar_t *ptagHeader = tagHeader;
|
||
bool in_tag = false;
|
||
//
|
||
const int maxCharsInLine = 40;
|
||
int curCharsInLine = 0;
|
||
bool break_next_space = false;
|
||
//
|
||
while( curChar )
|
||
{
|
||
curChar = (*phtml);
|
||
if( curChar == L'<' )
|
||
{
|
||
in_tag = true;
|
||
phtml++;
|
||
tagHeader[0] = (*phtml);
|
||
ptagHeader = tagHeader;
|
||
ptagHeader++;
|
||
phtml++;
|
||
}
|
||
else if( curChar == L'>' )
|
||
{
|
||
(*ptagHeader) = 0;
|
||
in_tag = false;
|
||
phtml++;
|
||
// parse passed tag
|
||
if( (_wcsicmp( tagHeader, L"br" ) == 0) || (_wcsicmp( tagHeader, L"br1" ) == 0) )
|
||
{
|
||
(*pinfohtml) = L'\r';
|
||
pinfohtml++;
|
||
(*pinfohtml) = L'\n';
|
||
pinfohtml++;
|
||
(*pinfohtml) = 0;
|
||
curCharsInLine = 0;
|
||
break_next_space = false;
|
||
}
|
||
else if( (wcsstr( tagHeader, L"a " ) == tagHeader) || (wcsstr( tagHeader, L"A " ) == tagHeader) )
|
||
{
|
||
process_bypass( info, tagHeader, phtml );
|
||
}
|
||
}
|
||
else if( (curChar == L'\r') || (curChar == L'\n') || (curChar == L' ') || (curChar == L'\t') )
|
||
{
|
||
if( break_next_space ) // insert line break
|
||
{
|
||
(*pinfohtml) = L'\r';
|
||
pinfohtml++;
|
||
(*pinfohtml) = L'\n';
|
||
pinfohtml++;
|
||
(*pinfohtml) = 0;
|
||
curCharsInLine = 0; // new line started
|
||
break_next_space = false; // we should not break at next whitespace )
|
||
}
|
||
// append space instead of \r, \n, \t
|
||
else if( curChar == L' ' )
|
||
{
|
||
if( in_tag )
|
||
{
|
||
(*ptagHeader) = L' ';
|
||
ptagHeader++;
|
||
(*ptagHeader) = 0;
|
||
}
|
||
else
|
||
{
|
||
(*pinfohtml) = L' ';
|
||
pinfohtml++;
|
||
}
|
||
}
|
||
phtml++;
|
||
}
|
||
else
|
||
{
|
||
if( !in_tag )
|
||
{
|
||
if( curChar != L'\n' && curChar != L'\r' )
|
||
{
|
||
(*pinfohtml) = curChar;
|
||
pinfohtml++;
|
||
(*pinfohtml) = 0;
|
||
//
|
||
curCharsInLine++;
|
||
if( curCharsInLine >= maxCharsInLine ) break_next_space = true;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
(*ptagHeader) = curChar;
|
||
ptagHeader++;
|
||
(*ptagHeader) = 0;
|
||
}
|
||
phtml++;
|
||
}
|
||
}
|
||
//
|
||
return info;
|
||
}
|
||
|
||
struct NpcHtmlDlgSt
|
||
{
|
||
NpcHtmlMessageDlg *cls;
|
||
NpcHtmlInfo *htmlInfo;
|
||
};
|
||
|
||
INT_PTR CALLBACK NpcHtmlMessageDlg::NpcHtmlMessageDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||
{
|
||
switch( uMsg )
|
||
{
|
||
case WM_INITDIALOG:
|
||
{
|
||
// get ptr to class
|
||
NpcHtmlMessageDlg *cls = (NpcHtmlMessageDlg *)lParam;
|
||
// save all info as window user data
|
||
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)malloc( sizeof(NpcHtmlDlgSt) );
|
||
st->cls = cls; // pointer to class
|
||
st->htmlInfo = NULL; // no html and links at this time
|
||
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)st );
|
||
// get children
|
||
cls->m_hWndHtml = GetDlgItem( hDlg, IDC_EDIT1 );
|
||
cls->m_hWndCombo = GetDlgItem( hDlg, IDC_COMBO1 );
|
||
cls->m_hWndBypassText = GetDlgItem( hDlg, IDC_EDIT2 );
|
||
} break;
|
||
case WM_COMMAND:
|
||
{
|
||
switch( LOWORD( wParam ) )
|
||
{
|
||
case IDCANCEL: NpcHtmlMessageDlg::wnd_onCancel( hDlg ); break;
|
||
case IDOK: NpcHtmlMessageDlg::wnd_onOK( hDlg ); break;
|
||
case IDC_COMBO1:
|
||
{
|
||
int code = HIWORD(wParam);
|
||
if( code == CBN_SELCHANGE ) NpcHtmlMessageDlg::wnd_onCombo1SelChange( hDlg );
|
||
} break;
|
||
}
|
||
return FALSE; // message was not processed
|
||
} break;
|
||
case WM_DESTROY: NpcHtmlMessageDlg::wnd_onDestroy( hDlg ); break;
|
||
case WM_KEYDOWN:
|
||
{
|
||
log_error( LOG_ERROR, "NpcHtmlMessageDlgProc(): WM_KEYDOWN\n" );
|
||
} break;
|
||
default: return FALSE; break;
|
||
}
|
||
return TRUE; // message was processed
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::wnd_initHtml( HWND hDlg )
|
||
{
|
||
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
|
||
if( !st ) return;
|
||
|
||
// set dlg title
|
||
if( st->cls->m_npc )
|
||
{
|
||
TCHAR title[512] = {0};
|
||
wsprintf( title, TEXT("%s (%s)"), st->cls->m_npc->charName, st->cls->m_npc->charTitle );
|
||
SetWindowText( hDlg, title );
|
||
}
|
||
else SetWindowText( hDlg, TEXT("NpcHtmlMessage") );
|
||
|
||
// clear prev. html
|
||
SetWindowText( st->cls->m_hWndHtml, TEXT("no text") );
|
||
if( st->htmlInfo )
|
||
{
|
||
delete st->htmlInfo;
|
||
st->htmlInfo = NULL;
|
||
}
|
||
|
||
// parse and set html
|
||
NpcHtmlInfo *htmlInfo = parse_NpcHtml( st->cls->m_html );
|
||
st->htmlInfo = htmlInfo; // pointer to html info...
|
||
if( st->htmlInfo )
|
||
SetDlgItemText( hDlg, IDC_EDIT1, st->htmlInfo->html );
|
||
|
||
// init combobox
|
||
ComboBox_ResetContent( st->cls->m_hWndCombo );
|
||
if( st->htmlInfo )
|
||
{
|
||
NpcHtmlLink *cur = st->htmlInfo->head;
|
||
while( cur )
|
||
{
|
||
ComboBox_AddString( st->cls->m_hWndCombo, cur->text );
|
||
cur = cur->next;
|
||
}
|
||
}
|
||
|
||
// init bypass text
|
||
SetWindowText( st->cls->m_hWndBypassText, TEXT("") );
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::wnd_onCancel( HWND hDlg )
|
||
{
|
||
ShowWindow( hDlg, SW_HIDE );
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::wnd_onOK( HWND hDlg )
|
||
{
|
||
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
|
||
if( !st ) return;
|
||
// save selection and post message to notify window
|
||
int cur_sel = ComboBox_GetCurSel( st->cls->m_hWndCombo );
|
||
if( cur_sel == -1 ) return;
|
||
//
|
||
ShowWindow( hDlg, SW_HIDE );
|
||
//
|
||
int nPassed = 0;
|
||
NpcHtmlLink *cur = st->htmlInfo->head;
|
||
while( cur )
|
||
{
|
||
if( nPassed == cur_sel )
|
||
{
|
||
if( cur->bypass )
|
||
{
|
||
// send request bypass to server
|
||
class L2Client *pcl = (L2Client *)st->cls->m_pvL2Client;
|
||
if( wcsstr( cur->bypass, L"bypass -h " ) )
|
||
{
|
||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> "bypass -h " <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
pcl->send_RequestBypassToServer( cur->bypass + 10 /*wcslen( L"bypass -h " )*/ );
|
||
}
|
||
else if( wcsstr( cur->bypass, L"link " ) )
|
||
{
|
||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> "link " <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
pcl->send_RequestLinkHtml( cur->bypass + 5 /*wcslen( L"link " )*/ );
|
||
}
|
||
else
|
||
{
|
||
log_error( LOG_ERROR, "Possibly wrong bypass in HTML from server!\n[%S]\n", cur->bypass );
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
cur = cur->next;
|
||
nPassed++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::wnd_onCombo1SelChange( HWND hDlg )
|
||
{
|
||
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
|
||
if( !st ) return;
|
||
int cur_sel = ComboBox_GetCurSel( st->cls->m_hWndCombo );
|
||
if( cur_sel == -1 ) return;
|
||
//
|
||
if( !st->htmlInfo ) return;
|
||
int nPassed = 0;
|
||
NpcHtmlLink *cur = st->htmlInfo->head;
|
||
while( cur )
|
||
{
|
||
if( nPassed == cur_sel )
|
||
{
|
||
SetWindowText( st->cls->m_hWndBypassText, cur->bypass );
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
cur = cur->next;
|
||
nPassed++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void NpcHtmlMessageDlg::wnd_onDestroy( HWND hDlg )
|
||
{
|
||
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
|
||
if( !st ) return;
|
||
delete st->htmlInfo;
|
||
st->htmlInfo = NULL;
|
||
free( st );
|
||
SetWindowLongPtr( hDlg, GWLP_USERDATA, 0 );
|
||
}
|