#include "stdafx.h" #include "KUIDefine.h" #include "KUIParser.h" #include "KUIFactory.h" //#include "KUIUtil.h" #pragma warning(disable:4267) #pragma warning(disable:4312) namespace KTOKEN_HANDLER { const int KTOKEN_BEGIN = 40; const int KTOKEN_END = 41; const int KTOKEN_ID = 42; const int KTOKEN_ANI = 43; const int KTOKEN_SPR = 44; const int KTOKEN_FRAME = 45; const int KTOKEN_RECT = 46; const int KTOKEN_POS = 47; const int KTOKEN_CAPTION = 48; const int KTOKEN_TOOLTIP = 49; const int KTOKEN_STYLE = 50; const int KTOKEN_FLAG = 51; const int KTOKEN_ANCHOR = 52; const int KTOKEN_ADD_BUTTON = 53; const int KTOKEN_GENWND = 54; } BEGIN_KTOKEN_MAP(KUIParser) ON_KTOKEN("begin",KTOKEN_BEGIN,&KUIParser::_OnBeginToken) ON_KTOKEN("end",KTOKEN_END,&KUIParser::_OnEndToken) ON_KTOKEN("id",KTOKEN_ID, &KUIParser::_OnPropetyToken) ON_KTOKEN("ani",KTOKEN_ANI, &KUIParser::_OnPropetyToken) ON_KTOKEN("spr",KTOKEN_SPR, &KUIParser::_OnPropetyToken) ON_KTOKEN("frame",KTOKEN_FRAME, &KUIParser::_OnPropetyToken) ON_KTOKEN("rect",KTOKEN_RECT, &KUIParser::_OnPropetyToken) ON_KTOKEN("pos",KTOKEN_POS, &KUIParser::_OnPropetyToken) ON_KTOKEN("caption", KTOKEN_CAPTION, &KUIParser::_OnPropetyToken) //ON_KTOKEN("tooltip",KTOKEN_TOOLTIP,&KUIParser::_OnPropetyToken) ON_KTOKEN("info",KTOKEN_TOOLTIP,&KUIParser::_OnPropetyToken) ON_KTOKEN("style", KTOKEN_STYLE, &KUIParser::_OnPropetyToken) ON_KTOKEN("flag",KTOKEN_FLAG,&KUIParser::_OnPropetyToken) ON_KTOKEN("anchor",KTOKEN_ANCHOR,&KUIParser::_OnPropetyToken) ON_KTOKEN("add_button",KTOKEN_ADD_BUTTON,&KUIParser::_OnPropetyToken) ON_KTOKEN("genwnd", KTOKEN_GENWND, &KUIParser::_OnGenWndCreate ) END_KTOKEN_MAP() namespace { std::map MAP_STYLE; std::map MAP_FLAG; std::map MAP_ANCHOR; struct MAPPING_INFO { DWORD dwFlag; std::string sName; }; void registerMappingInfo(std::map& mapInfo, MAPPING_INFO* pInfoArray, int nCount) { for(int i = 0; i < nCount; ++i) mapInfo.insert( std::make_pair( pInfoArray[i].sName, pInfoArray[i].dwFlag) ); } bool initMapInfo() { MAPPING_INFO STYLE_ARRAY[] = { // GenWnd { KSTYLE_NOCLOSE, "KSTYLE_NOCLOSE" }, { KSTYLE_NOMINIMIZE, "KSTYLE_NOMINIMIZE" }, { KSTYLE_NORESIZE, "KSTYLE_NORESIZE" }, { KSTYLE_NOTITLE, "KSTYLE_NOTITLE" }, { KSTYLE_NOSTATUSBAR, "KSTYLE_NOSTATUSBAR" }, { KSTYLE_VSCROLL, "KSTYLE_VSCROLL"}, { KSTYLE_HSCROLL, "KSTYLE_HSCROLL"}, { KSTYLE_NOFRAME, "KSTYLE_NOFRAME"}, { KSTYLE_NOTOPFRAME, "KSTYLE_NOTOPFRAME"}, { KSTYLE_NOBACKGROUND, "KSTYLE_NOBACKGROUND"}, { KSTYLE_RESIZE_LEFT, "KSTYLE_RESIZE_LEFT"}, { KSTYLE_RESIZE_TOP, "KSTYLE_RESIZE_TOP"}, { KSTYLE_MOVE_BY_TITLEBAR, "KSTYLE_MOVE_BY_TITLEBAR"}, { KSTYLE_MOVE_BY_TOPFRAME, "KSTYLE_MOVE_BY_TOPFRAME"}, { KSTYLE_MOVE_BY_ALL, "KSTYLE_MOVE_BY_ALL"}, { KSTYLE_MOVE_BY_CUSTOM, "KSTYLE_MOVE_BY_CUSTOM"}, { KSTYLE_NO_CLIPPING, "KSTYLE_NO_CLIPPING"}, { KSTYLE_VERTICAL_REPEAT, "KSTYLE_VERTICAL_REPEAT"}, { KSTYLE_HORIZONTAL_REPEAT, "KSTYLE_HORIZONTAL_REPEAT"}, { KSTYLE_SPR_CAPTION, "KSTYLE_SPR_CAPTION"}, { KSTYLE_ALPHA_SHOW, "KSTYLE_ALPHA_SHOW" }, // button { KSTYLE_BUTTON_LEFTSIDE, "KSTYLE_BUTTON_LEFTSIDE"}, { KSTYLE_BUTTON_RIGHTSIDE, "KSTYLE_BUTTON_RIGHTSIDE"}, { KSTYLE_BUTTON_CANDRAG, "KSTYLE_BUTTON_CANDRAG"}, { KSTYLE_BUTTON_VERTICAL, "KSTYLE_BUTTON_VERTICAL"}, { KSTYLE_CHECK_CAPTION_RIGHT, "KSTYLE_CHECK_CAPTION_RIGHT"}, // status bar { KSTYLE_SB_NOLEFTSIDE, "KSTYLE_SB_NOLEFTSIDE"}, { KSTYLE_SB_NORIGHTSIDE, "KSTYLE_SB_NORIGHTSIDE"}, // Tab Control { KSTYLE_TAB_VERTICAL, "KSTYLE_TAB_VERTICAL"}, // Number Control { KSTYLE_NUMBER_LEFT, "KSTYLE_NUMBER_LEFT"}, { KSTYLE_NUMBER_CENTER, "KSTYLE_NUMBER_CENTER"}, { KSTYLE_NUMBER_RIGHT, "KSTYLE_NUMBER_RIGHT"}, // Gauge Control { KSTYLE_GAUGE_WITH_GRADUATION, "KSTYLE_GAUGE_WITH_GRADUATION" }, // Msg Control { KSTYLE_MSG_VERTICAL_REPEAT, "KSTYLE_MSG_VERTICAL_REPEAT"}, { KSTYLE_MSG_HORIZONTAL_REPEAT, "KSTYLE_MSG_HORIZONTAL_REPEAT"}, }; registerMappingInfo( MAP_STYLE, STYLE_ARRAY, _countof(STYLE_ARRAY) ); MAPPING_INFO FLAG_ARRAY[] = { // GenWnd { KFLAG_NO_GET_MESSAGE, "KFLAG_NO_GET_MESSAGE" }, { KFLAG_GET_PASS_MESSAGE, "KFLAG_GET_PASS_MESSAGE" }, { KFLAG_CAN_DRAG, "KFLAG_CAN_DRAG" }, { KFLAG_SINGLE_LINE, "KFLAG_SINGLE_LINE" }, { KFLAG_NO_GET_FOCUS, "KFLAG_NO_GET_FOCUS" }, }; registerMappingInfo(MAP_FLAG ,FLAG_ARRAY, _countof(FLAG_ARRAY)); MAPPING_INFO ANCHOR_ARRAY[] = { // GenWnd { KANCHOR_LEFT, "KANCHOR_LEFT" }, { KANCHOR_RIGHT, "KANCHOR_RIGHT" }, { KANCHOR_TOP, "KANCHOR_TOP" }, { KANCHOR_BOTTOM, "KANCHOR_BOTTOM" }, }; registerMappingInfo(MAP_ANCHOR, ANCHOR_ARRAY, _countof(ANCHOR_ARRAY)); return true; } DWORD getStringToDWORD(LPCSTR lpszName, std::map& mapInfo) { std::map::iterator it = mapInfo.find( std::string ( lpszName ) ); if( it == mapInfo.end() ) return 0; return it->second; } bool bInitMapInfo = initMapInfo(); }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KUIParser Implement ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// KUIParser::KUIParser() { static char Whitespacechr[] = {'\n', '\r', ' ', '\t', '|'}; static char Tokendata[] = { KTOKEN_HANDLER::KTOKEN_COMMA, ',' , KTOKEN_HANDLER::KTOKEN_ASSIGN, '=' , KTOKEN_HANDLER::KTOKEN_SEMI_COLON, ';' , }; m_TokenParser.SetWhiteSpaceChar(Whitespacechr, _countof(Whitespacechr) ); m_TokenParser.SetTokenChar(Tokendata, _countof(Tokendata) ); _InitializeTokenMap(); Clear(); } KUIParser::~KUIParser() { Clear(); } void KUIParser::Clear() { m_bErrorFound = false; m_nStage = KSTAGE_CONTROL_START; m_nSubStage = 0; m_pParentObj = NULL; SAFE_DELETE_VECTOR( m_vtParseObj ); } bool KUIParser::DoParsing(KStream& stream) { Clear(); m_TokenParser.LoadStream(stream); return !m_bErrorFound; } DWORD KUIParser::GetParseObjCount() { return m_vtParseObj.size(); } KUIWndParseObject* KUIParser::GetParseObject(DWORD dwIndex) { if( dwIndex >= m_vtParseObj.size() ) { assert(false && "Invalid Index"); return NULL; } return m_vtParseObj[dwIndex]; } K_TOKEN_CALL void KUIParser::_OnNoTokenFound(DWORD dwStringPointer, DWORD dwLineCount,DWORD dwReserve1) { LPCSTR lpszToken = reinterpret_cast(dwStringPointer); // Create 상태다 switch( m_nStage) { case KSTAGE_CONTROL_CREATE: // 찾을수 없는 control if( false == KUIFactory::GetInstance()->IsRegister( lpszToken) ) { // 무조건 Error _ErrMsgBox("파싱 에러 %d Line. 등록되지 않은 Control 입니다", dwLineCount); return; } m_CurrentArg.lpszClassName = lpszToken; m_nStage = KSTAGE_CONTROL_PROPERTY; break; case KSTAGE_CONTROL_ASSIGN: _DoAssign( lpszToken, dwLineCount); break; default: _ErrMsgBox("파싱 에러 %d Line. 알수 없는 Token ( %s ) 입니다", dwLineCount, lpszToken); assert( 0 && "NUI 파싱 에러" ); return; } } K_TOKEN_CALL void KUIParser::_OnCharTokenFound(DWORD dwCharType, DWORD dwLineCount, DWORD dwReserve1) { switch( dwCharType ) { case KTOKEN_HANDLER::KTOKEN_SEMI_COLON: { _CheckStageError(KSTAGE_CONTROL_ASSIGN, dwLineCount); m_nStage = KSTAGE_CONTROL_PROPERTY; } break; default: break; } } K_TOKEN_CALL void KUIParser::_OnTokenEnd() { if( m_nStage != KSTAGE_CONTROL_START) _ErrMsgBox(" end 를 빼먹었습니다"); } K_TOKEN_CALL void KUIParser::_OnBeginToken(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve2) { _CheckStageError(KSTAGE_CONTROL_START, dwLineCount); m_nStage = KSTAGE_CONTROL_CREATE; // Argument 초기화 m_CurrentArg = KUIWND_CREATE_ARG(); } K_TOKEN_CALL void KUIParser::_OnEndToken(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve2) { _CheckStageError(KSTAGE_CONTROL_PROPERTY,dwLineCount); m_nStage = KSTAGE_CONTROL_START; if( NULL == m_pParentObj) return; if (m_CurrentArg.lpszClassName != "genwnd" ) m_pParentObj->AddChildObj( m_CurrentArg ); else m_pParentObj->SetCreateArg( m_CurrentArg ); } K_TOKEN_CALL void KUIParser::_OnPropetyToken(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve1) { _CheckStageError(KSTAGE_CONTROL_PROPERTY,dwLineCount); m_nStage = KSTAGE_CONTROL_ASSIGN; m_nSubStage = dwTokenID; } K_TOKEN_CALL void KUIParser::_OnGenWndCreate(DWORD dwTokenID, DWORD dwLineCount,DWORD dwReserve1) { _CheckStageError(KSTAGE_CONTROL_CREATE,dwLineCount); m_nStage = KSTAGE_CONTROL_PROPERTY; m_pParentObj = new KUIWndParseObject; m_CurrentArg.lpszClassName = "genwnd"; m_vtParseObj.push_back( m_pParentObj) ; } void KUIParser::_DoAssign(LPCSTR lpszToken, DWORD dwLineCount) { _CheckStageError(KSTAGE_CONTROL_ASSIGN, dwLineCount); int IntValue = ::atoi( lpszToken); using namespace KTOKEN_HANDLER; switch ( m_nSubStage) { case KTOKEN_ID: m_CurrentArg.lpszID = lpszToken; break; case KTOKEN_ANI: m_CurrentArg.lpszAniName = lpszToken; break; case KTOKEN_SPR: m_CurrentArg.lpszSprName = lpszToken; break; case KTOKEN_FRAME: m_CurrentArg.nFrameIndex = IntValue; break; case KTOKEN_RECT: { static int nRectCount = 0; static int nRectArray[4]; nRectArray[nRectCount] = IntValue; nRectCount++; if(nRectCount == 4) { m_CurrentArg.rcRect = KRect(nRectArray[0], nRectArray[1], nRectArray[2], nRectArray[3]); nRectCount = 0; } } break; case KTOKEN_POS: { static int nPosCount = 0; static int nPosArray[2]; nPosArray[nPosCount] = IntValue; nPosCount++; if(nPosCount == 2) { m_CurrentArg.rcRect = KRect(nPosArray[0], nPosArray[1], -1, -1); nPosCount = 0; } } break; case KTOKEN_CAPTION: m_CurrentArg.lpszCaption = lpszToken; break; case KTOKEN_TOOLTIP: m_CurrentArg.lpszToolTip = lpszToken; break; case KTOKEN_STYLE: { DWORD dwStyle = getStringToDWORD( lpszToken, MAP_STYLE); if( dwStyle == 0) _ErrMsgBox( "파싱 에러 %d. 잘못된 Style (%s) 입니다.", dwLineCount, lpszToken); m_CurrentArg.dwStyle |= dwStyle; } break; case KTOKEN_FLAG: { DWORD dwFlag = getStringToDWORD( lpszToken, MAP_FLAG); if( dwFlag == 0) _ErrMsgBox( "파싱 에러 %d. 잘못된 Flag (%s) 입니다.", dwLineCount, lpszToken); m_CurrentArg.dwFlag |= dwFlag; } break; case KTOKEN_ANCHOR: { DWORD dwAnchor = getStringToDWORD( lpszToken, MAP_ANCHOR); if( dwAnchor == 0) _ErrMsgBox( "파싱 에러 %d. 잘못된 Anchor (%s) 입니다.", dwAnchor, lpszToken); m_CurrentArg.dwAnchor |= dwAnchor; } break; case KTOKEN_ADD_BUTTON: break; default: _CheckStageError( -1, dwLineCount); break; } } void KUIParser::_CheckStageError(int nStage, DWORD dwLineNumber) { if(m_nStage != nStage) { char buff[512]; switch( nStage) { case KSTAGE_CONTROL_START: sprintf(buff, "begin의 시작전에 잘 못된 값이 존재합니다"); break; case KSTAGE_CONTROL_CREATE: sprintf(buff, "begin Keyword가 필요합니다"); break; case KSTAGE_CONTROL_PROPERTY: sprintf(buff, " ; (semi colon)을 빼먹거나 Control을 생성하지 않았습니다"); break; case KSTAGE_CONTROL_ASSIGN: sprintf(buff, "Control의 속성을 지정하는 Keyword 이후에 사용해야 합니다"); break; default: sprintf(buff, "알수 없는 오류입니다"); break; } _ErrMsgBox( "파싱 에러 %d Line. %s", dwLineNumber, buff); } } void KUIParser::_ErrMsgBox(LPCSTR lpszString, ...) { #ifndef NDEBUG #ifndef _RELEASE char szBuf[1024]; va_list va; va_start( va, lpszString ); _vsnprintf( szBuf, _countof(szBuf), lpszString, va ); va_end( va ); MessageBox( NULL, szBuf, "Error", MB_OK); #endif #endif m_bErrorFound = true; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KUIWndParseObject Implement ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// KUIWndParseObject::KUIWndParseObject() { } KUIWndParseObject::~KUIWndParseObject() { SAFE_DELETE_VECTOR( m_vtChildParseObj ); } DWORD KUIWndParseObject::GetChildCount() { return m_vtChildParseObj.size(); } KUIWndParseObject* KUIWndParseObject::GetChildParseObj(DWORD dwIndex) { if( dwIndex >= m_vtChildParseObj.size() ) { assert(false && "Invalid Index"); return NULL; } return m_vtChildParseObj[dwIndex]; } KUIWndParseObject* KUIWndParseObject::AddChildObj(const KUIWND_CREATE_ARG& arg) { KUIWndParseObject* pObj = new KUIWndParseObject; pObj->SetCreateArg( arg ); m_vtChildParseObj.push_back( pObj ); return m_vtChildParseObj.back(); } const KUIWND_CREATE_ARG& KUIWndParseObject::GetCreateArg() const { return m_CreateArg; } KUIWND_CREATE_ARG& KUIWndParseObject::GetCreateArg() { return m_CreateArg; } void KUIWndParseObject::SetCreateArg(const KUIWND_CREATE_ARG& arg) { m_CreateArg = arg; }