#include "StdAfx.h" #include "EtUILineEditBox.h" #include "EtUIIME.h" #include "strsafe.h" #ifdef _DEBUG #define new new(_NORMAL_BLOCK,__FILE__,__LINE__) #endif CEtUILineEditBox::CEtUILineEditBox( CEtUIDialog *pParent ) : CEtUIControl( pParent ) { m_Property.UIType = UI_CONTROL_LINE_EDITBOX; m_bCaretOn = true; m_fCaretBlinkTime = GetCaretBlinkTime() * 0.001f; QueryPerformanceCounter( &m_liLastBlinkTime ); m_bInsertMode = true; m_bMouseDrag = false; m_nCurLine = -1; m_nSelStartPos = 0; m_nSelEndPos = 0; m_nSelStartLine = 0; m_nOriginSelStartPos = 0; m_nOriginSelEndPos = 0; m_nSelEndLine = 0; m_fCompositionWidth = 0.0f; m_nMaxTextLength = MAX_COMPSTRING_SIZE; } CEtUILineEditBox::~CEtUILineEditBox(void) { DeleteBufferList(); } void CEtUILineEditBox::DeleteBufferList() { std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { SAFE_DELETE( (*iter) ); } m_listBuffer.clear(); } void CEtUILineEditBox::Initialize( SUIControlProperty *pProperty ) { CEtUIControl::Initialize( pProperty ); UpdateRects(); } void CEtUILineEditBox::SetTemplate( int nTemplateIndex ) { CEtUIControl::SetTemplate( nTemplateIndex ); SUIElement *pElement = GetElement(0); if( pElement ) { //m_pFont = m_pParent->GetFont( pElement->nFontIndex, pElement->nFontHeight ); if( AddLine( NULL ) ) DownCurrentLine(); } } void CEtUILineEditBox::Focus( bool bFocus ) { CEtUIControl::Focus( bFocus ); CEtUIControl::SetFocusEditBox( IsFocus() ); ResetCaretBlink(); if (IsFocus() == false && IsTextSelected()) { SBufferInfo* pLine = GetLine(m_nSelEndLine); if (pLine) { m_nSelStartPos = m_nSelEndPos = pLine->nCaretPos; m_nOriginSelStartPos = m_nOriginSelEndPos = pLine->nOriginCaretPos; m_nSelStartLine = m_nSelEndLine; } } } //void CEtUILineEditBox::SetText( LPCWSTR wszText, bool bSelected ) //{ // ASSERT( wszText != NULL ); // // m_Buffer.SetText( wszText ); // m_nFirstVisible = 0; // // PlaceCaret( m_Buffer.GetTextSize() ); // if( bSelected ) // { // m_nSelStart = 0; // } // else // { // m_nSelStart = m_nCaret; // } //} HRESULT CEtUILineEditBox::GetTextCopy( LPWSTR strDest, UINT bufferCount ) { ASSERT( strDest ); std::wstring strTemp; std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { int nBufferSize = (*iter)->pUniBuffer->GetBufferSize(); if( nBufferSize ) { strTemp += (*iter)->pUniBuffer->GetBuffer(); if( (*iter)->pNextLine == NULL ) { strTemp += L"\n"; } } else { strTemp += L"\n"; } } if( bufferCount != 0 ) { //wcscpy_s( strDest, bufferCount, strTemp.c_str() ); StringCchCopyW(strDest, bufferCount, strTemp.c_str()); } return S_OK; } HRESULT CEtUILineEditBox::GetOriginTextCopy( LPWSTR strDest, UINT bufferCount ) { ASSERT( strDest ); std::wstring strTemp; std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { int nBufferSize = (*iter)->pOriginUniBuffer->GetTextSize(); if( nBufferSize ) { strTemp += (*iter)->pOriginUniBuffer->GetBuffer(); if( (*iter)->pNextLine == NULL ) { strTemp += L"\n"; } } else { strTemp += L"\n"; } } if( bufferCount != 0 ) { StringCchCopyW(strDest, bufferCount, strTemp.c_str()); } return S_OK; } void CEtUILineEditBox::ClearText() { m_nSelStartPos = 0; m_nSelEndPos = 0; m_nOriginSelStartPos = 0; m_nOriginSelEndPos = 0; m_nSelStartLine = 0; m_nSelEndLine = 0; DeleteBufferList(); if( AddLine( NULL ) ) DownCurrentLine(); } bool CEtUILineEditBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) { if( !IsEnable() || !IsShow() ) { return false; } bool bHandled(false); SBufferInfo *pBufferInfo(NULL); pBufferInfo = GetCurrentLine(); if( !pBufferInfo ) return false; switch( uMsg ) { case WM_KEYDOWN: { switch( wParam ) { case VK_TAB: break; case VK_HOME: { PlaceCaretBegin( pBufferInfo ); if( GetKeyState( VK_SHIFT ) >= 0 ) { SetSelectStartPos(); } else { SetSelectEndPos(); } ResetCaretBlink(); bHandled = true; } break; case VK_END: { PlaceCaretEnd( pBufferInfo ); if( GetKeyState( VK_SHIFT ) >= 0 ) { SetSelectStartPos(); } else { SetSelectEndPos(); } ResetCaretBlink(); bHandled = true; } break; case VK_INSERT: { m_bInsertMode = !m_bInsertMode; } break; case VK_DELETE: { if( IsTextSelected() ) { DeleteSelectionText(); } else { if( pBufferInfo->IsEndCaret() ) { SBufferInfo *pNextLine = GetLine( m_nCurLine+1 ); if( pNextLine ) { PasteTrailFromLine( pBufferInfo, pNextLine ); } } else { if( !CheckTagTextRemove( pBufferInfo, pBufferInfo->nCaretPos ) ) { RemoveOriginCharLine( pBufferInfo, pBufferInfo->nOriginCaretPos ); RemoveCharLine( pBufferInfo, pBufferInfo->nCaretPos ); } } } ResetCaretBlink(); bHandled = true; } break; case VK_LEFT: { if( pBufferInfo->nCaretPos > 0 ) { PlaceCaret( pBufferInfo, pBufferInfo->nCaretPos - 1 ); } else { SBufferInfo *pBufferInfoInner = GetLine( m_nCurLine-1 ); if( pBufferInfoInner ) { UpCurrentLine(); PlaceCaretEnd( pBufferInfoInner ); } } if( GetKeyState( VK_SHIFT ) >= 0 ) { SetSelectStartPos(); } else { SetSelectEndPos(); } ResetCaretBlink(); bHandled = true; } break; case VK_RIGHT: { if( pBufferInfo->nCaretPos < pBufferInfo->GetTextSize() ) { PlaceCaret( pBufferInfo, pBufferInfo->nCaretPos + 1 ); } else { SBufferInfo *pBufferInfoInner = GetLine( m_nCurLine+1 ); if( pBufferInfoInner ) { DownCurrentLine(); PlaceCaretBegin( pBufferInfoInner ); } } if( GetKeyState( VK_SHIFT ) >= 0 ) { SetSelectStartPos(); } else { SetSelectEndPos(); } ResetCaretBlink(); bHandled = true; } break; case VK_UP: { UpCurrentLine(); if( GetKeyState( VK_SHIFT ) >= 0 ) { SetSelectStartPos(); } else { SetSelectEndPos(); } ResetCaretBlink(); bHandled = true; } break; case VK_DOWN: { DownCurrentLine(); if( GetKeyState( VK_SHIFT ) >= 0 ) { SetSelectStartPos(); } else { SetSelectEndPos(); } ResetCaretBlink(); bHandled = true; } break; case VK_ESCAPE: // 원래 LineEditBox, LineIMEEditBox 는 EVENT_EDITBOX 계열을 사용하지 않았으나, // 메일쓰기창에서 포커스가 가있는 상태에서 Esc로 창을 닫을 수 있어야해서, // 이렇게 EVENT_EDITBOX_ESCAPE를 사용하게 되었다. // EVENT_EDITBOX 계열의 다른 메세지도 전부 필요하게 된다면, 그때가서 추가하도록 하겠다. m_pParent->ProcessCommand( EVENT_EDITBOX_ESCAPE, true, this ); bHandled = true; break; default: bHandled = wParam != VK_ESCAPE; } } break; } return bHandled; } bool CEtUILineEditBox::HandleMouse( UINT uMsg, float fX, float fY, WPARAM wParam, LPARAM lParam ) { if( !IsEnable() || !IsShow() ) { return false; } switch( uMsg ) { case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: { if( !m_bFocus ) { m_pParent->RequestFocus( this ); } if( !IsInside( fX, fY ) ) { return false; } m_bMouseDrag = true; SetCapture( m_pParent->GetHWnd() ); int nLine = GetLineMouseIn( fX, fY ); if( nLine != -1 ) { SetCurrentLine( nLine ); SBufferInfo *pBufferInfo = GetCurrentLine(); if( pBufferInfo ) { int nCP, nTrail, nX1st; CEtFontMng& FontMng = CEtFontMng::GetInstance(); SUIElement* pElement = GetElement( 0 ); nX1st = FontMng.GetCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, 0 ); //pBufferInfo->CPtoX( 0, FALSE, &nX1st ); nCP = FontMng.GetCaretFromCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, ( int )( m_pParent->GetScreenWidth() * ( fX - pBufferInfo->TextCoord.fX ) + nX1st ), nTrail ); //if( SUCCEEDED( pBufferInfo->XtoCP( ( int )( m_pParent->GetScreenWidth() * ( fX - pBufferInfo->TextCoord.fX ) + nX1st ), &nCP, &nTrail ) ) ) if( 0 <= nCP ) { if( ( nTrail ) && ( nCP < pBufferInfo->GetTextSize() ) ) { PlaceCaret( pBufferInfo, nCP+1 ); } else { PlaceCaret( pBufferInfo, nCP ); } SetSelectStartPos(); ResetCaretBlink(); } } } return true; } case WM_LBUTTONUP: ReleaseCapture(); m_bMouseDrag = false; break; case WM_MOUSEMOVE: if( m_bMouseDrag ) { int nLine = GetLineMouseIn( fX, fY ); if( nLine != -1 ) { SetCurrentLine( nLine ); SBufferInfo *pBufferInfo = GetCurrentLine(); if( pBufferInfo ) { int nCP, nTrail, nX1st; CEtFontMng& FontMng = CEtFontMng::GetInstance(); SUIElement* pElement = GetElement( 0 ); nX1st = FontMng.GetCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, 0 ); //pBufferInfo->CPtoX( 0, FALSE, &nX1st ); nCP = FontMng.GetCaretFromCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, ( int )( m_pParent->GetScreenWidth() * ( fX - pBufferInfo->TextCoord.fX ) + nX1st ), nTrail ); //if( SUCCEEDED( pBufferInfo->XtoCP( ( int )( m_pParent->GetScreenWidth() * ( fX - pBufferInfo->TextCoord.fX ) + nX1st ), &nCP, &nTrail ) ) ) if( 0 <= nCP ) { if( ( nTrail ) && ( nCP < pBufferInfo->GetTextSize() ) ) { PlaceCaret( pBufferInfo, nCP+1 ); } else { PlaceCaret( pBufferInfo, nCP ); } SetSelectEndPos(); } } } } break; } return false; } bool CEtUILineEditBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) { if( !IsEnable() || !IsShow() ) { return false; } SBufferInfo *pBufferInfo(NULL); pBufferInfo = GetCurrentLine(); if( !pBufferInfo ) return false; switch( uMsg ) { case WM_KEYUP: case WM_KEYDOWN: break; //return true; case WM_CHAR: switch( ( WCHAR )wParam ) { case VK_BACK: { if( IsTextSelected() ) { DeleteSelectionText(); } else { if( pBufferInfo->nCaretPos > 0 ) { PlaceCaret( pBufferInfo, pBufferInfo->nCaretPos - 1 ); if( !CheckTagTextRemove( pBufferInfo, pBufferInfo->nCaretPos ) ) { RemoveOriginCharLine( pBufferInfo, pBufferInfo->nOriginCaretPos ); RemoveCharLine( pBufferInfo, pBufferInfo->nCaretPos ); } } else if( IsBeginLine(pBufferInfo) ) { } else { if( pBufferInfo->GetTextSize() > 0 ) { UpCurrentLine(); PlaceCaretEnd( GetCurrentLine() ); pBufferInfo = GetLine( m_nCurLine ); if( pBufferInfo && pBufferInfo->IsEndCaret() ) { SBufferInfo *pNextLine = GetLine( m_nCurLine+1 ); if( pNextLine ) { PasteTrailFromLine( pBufferInfo, pNextLine ); } } } else { if( !IsBeginLine(pBufferInfo) ) { DeleteLine( pBufferInfo ); UpCurrentLine(); PlaceCaretEnd( GetCurrentLine() ); } } } } SetSelectStartPos(); ResetCaretBlink(); } break; case 24: // Ctrl-X Cut case VK_CANCEL: // Ctrl-C Copy CopyToClipboard(); if( ( WCHAR )wParam == 24 ) { DeleteSelectionText(); } break; case 22: // Ctrl-V Paste PasteFromClipboard(); break; case 1: // Ctrl-A Select All if( !IsTextSelected() ) { m_nSelStartLine = 0; m_nSelStartPos = 0; m_nOriginSelStartPos = 0; int nSize = (int)m_listBuffer.size()-1; SetCurrentLine( nSize ); SBufferInfo *pLine = GetCurrentLine(); PlaceCaretEnd( GetCurrentLine() ); m_nSelEndLine = nSize; m_nSelEndPos = pLine->GetTextSize(); m_nOriginSelEndPos = pLine->GetOriginTextSize(); } break; case VK_RETURN: { if( pBufferInfo->IsEndCaret() ) { if( AddLine( pBufferInfo ) ) DownCurrentLine(); } else { SplitLineToAdd( pBufferInfo ); } SetSelectStartPos(); } break; // Junk characters we don't want in the string case 26: // Ctrl Z case 2: // Ctrl B case 14: // Ctrl N case 19: // Ctrl S case 4: // Ctrl D case 6: // Ctrl F case 7: // Ctrl G case 10: // Ctrl J case 11: // Ctrl K case 12: // Ctrl L case 17: // Ctrl Q case 23: // Ctrl W case 5: // Ctrl E case 18: // Ctrl R case 20: // Ctrl T case 25: // Ctrl Y case 21: // Ctrl U case 9: // Ctrl I case 15: // Ctrl O case 16: // Ctrl P case 27: // Ctrl [ case 29: // Ctrl ] case 28: // Ctrl \ break; default: if( IsTextSelected() ) { DeleteSelectionText(); } if( ( !m_bInsertMode ) && ( pBufferInfo->nCaretPos < pBufferInfo->GetTextSize() ) ) { (*pBufferInfo->pUniBuffer)[pBufferInfo->nCaretPos] = (WCHAR)wParam; PlaceCaret( pBufferInfo, pBufferInfo->nCaretPos + 1 ); } else { InsertCharLine( pBufferInfo, pBufferInfo->nCaretPos, (WCHAR)wParam ); } SetSelectStartPos(); ResetCaretBlink(); } return true; } return false; } void CEtUILineEditBox::UpdateRects() { SUICoord sSymbolCoord; m_pParent->CalcTextRect( L"X", GetElement(0), sSymbolCoord ); float fLineSpace(0.0f); if( m_Property.UIType == UI_CONTROL_LINE_IMEEDITBOX ) { fLineSpace = m_Property.LineIMEEditBoxProperty.fLineSpace; } else if( m_Property.UIType == UI_CONTROL_LINE_EDITBOX ) { fLineSpace = m_Property.LineEditBoxProperty.fLineSpace; } float fY(m_Property.UICoord.fY); std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { (*iter)->TextCoord = m_Property.UICoord; (*iter)->TextCoord.fY = fY; (*iter)->TextCoord.fHeight = sSymbolCoord.fHeight; fY += sSymbolCoord.fHeight + fLineSpace; } } void CEtUILineEditBox::Render( float fElapsedTime ) { //HRESULT hr; int nSelStartX(0), nCaretX(0), nXFirst(0); SUIElement *pElement(NULL); UpdateBlendRate(); //int nVecSize = (int)m_Template.m_vecElement.size(); //for( int i = 0; i < nVecSize; i++ ) //{ // pElement = GetElement(i); // pElement->TextureColor.Blend( UI_STATE_NORMAL, fElapsedTime, m_fBlendRate ); // m_pParent->DrawSprite( pElement->UVCoord, pElement->TextureColor.dwCurrentColor, m_RenderCoord[ i ] ); //} //m_pParent->DrawRect( m_Property.UICoord, EtInterface::debug::BLUE ); SBufferInfo *pBufferInfo(NULL); pBufferInfo = GetCurrentLine(); if( !pBufferInfo ) return; SUICoord SelectionCoord; CEtFontMng& FontMng = CEtFontMng::GetInstance(); pElement = GetElement( 0 ); if( m_nSelStartLine == m_nSelEndLine ) { //pBufferInfo->CPtoX( 0, FALSE, &nXFirst ); nXFirst = FontMng.GetCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, 0 ); //hr = pBufferInfo->CPtoX( pBufferInfo->nCaretPos, FALSE, &nCaretX ); nCaretX = FontMng.GetCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, pBufferInfo->nCaretPos ); if( IsTextSelected() ) { //hr = pBufferInfo->CPtoX( m_nSelStartPos, FALSE, &nSelStartX ); nSelStartX = FontMng.GetCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, m_nSelStartPos ); } else { nSelStartX = nCaretX; } if( pBufferInfo->nCaretPos != m_nSelStartPos ) { int nSelLeftX = nCaretX; int nSelRightX = nSelStartX; if( nSelLeftX > nSelRightX ) { std::swap( nSelLeftX, nSelRightX ); } SelectionCoord.SetCoord( ( ( float )nSelLeftX ) / m_pParent->GetScreenWidth(), pBufferInfo->TextCoord.fY, ( ( float )( nSelRightX - nSelLeftX ) ) / m_pParent->GetScreenWidth(), pBufferInfo->TextCoord.fHeight ); SelectionCoord.fX += pBufferInfo->TextCoord.fX - ( ( float )nXFirst ) / m_pParent->GetScreenWidth(); float fMinRight = min( pBufferInfo->TextCoord.Right(), SelectionCoord.Right() ); float fMinBottom = min( pBufferInfo->TextCoord.Bottom(), SelectionCoord.Bottom() ); SelectionCoord.fWidth = fMinRight - SelectionCoord.fX; SelectionCoord.fHeight = fMinBottom - SelectionCoord.fY; SelectionCoord.fX = max( pBufferInfo->TextCoord.fX, SelectionCoord.fX ); SelectionCoord.fY = max( pBufferInfo->TextCoord.fY, SelectionCoord.fY ); bool bEnableZ = GetEtDevice()->EnableZ( false ); m_pParent->DrawRect( SelectionCoord, m_Property.LineEditBoxProperty.dwSelBackColor ); GetEtDevice()->EnableZ( bEnableZ ); } } else { bool bSwap(false); if( m_nSelStartLine > m_nSelEndLine ) { std::swap( m_nSelStartLine, m_nSelEndLine ); std::swap( m_nSelStartPos, m_nSelEndPos ); bSwap = true; } int nSelStartLine = m_nSelStartLine; int nSelEndLine = m_nSelEndLine; int nSelStartPos = m_nSelStartPos; int nSelEndPos = m_nSelEndPos; for( int i=nSelStartLine; i<=nSelEndLine; ++i ) { SBufferInfo *pBufferInfoInner = GetLine(i); if( !pBufferInfoInner ) continue; if( i > nSelStartLine ) { nSelStartPos = 0; } if( i < nSelEndLine ) { nSelEndPos = pBufferInfoInner->GetTextSize(); } else { nSelEndPos = m_nSelEndPos; } int nSelLeftX(0); int nSelRightX(0); nSelLeftX = FontMng.GetCaretPos( pBufferInfoInner->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, nSelStartPos ); //pBufferInfoInner->CPtoX( nSelStartPos, FALSE, &nSelLeftX ); nSelRightX = FontMng.GetCaretPos( pBufferInfoInner->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, nSelEndPos ); //pBufferInfoInner->CPtoX( nSelEndPos, FALSE, &nSelRightX ); SelectionCoord.SetCoord( ( ( float )nSelLeftX ) / m_pParent->GetScreenWidth(), pBufferInfoInner->TextCoord.fY, ( ( float )( nSelRightX - nSelLeftX ) ) / m_pParent->GetScreenWidth(), pBufferInfoInner->TextCoord.fHeight ); SelectionCoord.fX += pBufferInfoInner->TextCoord.fX - ( ( float )nXFirst ) / m_pParent->GetScreenWidth(); float fMinRight = min( pBufferInfoInner->TextCoord.Right(), SelectionCoord.Right() ); float fMinBottom = min( pBufferInfoInner->TextCoord.Bottom(), SelectionCoord.Bottom() ); SelectionCoord.fWidth = fMinRight - SelectionCoord.fX; SelectionCoord.fHeight = fMinBottom - SelectionCoord.fY; SelectionCoord.fX = max( pBufferInfoInner->TextCoord.fX, SelectionCoord.fX ); SelectionCoord.fY = max( pBufferInfoInner->TextCoord.fY, SelectionCoord.fY ); bool bEnableZ = GetEtDevice()->EnableZ( false ); m_pParent->DrawRect( SelectionCoord, m_Property.LineEditBoxProperty.dwSelBackColor ); GetEtDevice()->EnableZ( bEnableZ ); } if( bSwap ) { std::swap( m_nSelStartLine, m_nSelEndLine ); std::swap( m_nSelStartPos, m_nSelEndPos ); } nCaretX = FontMng.GetCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, m_nSelEndPos ); //pBufferInfo->CPtoX( m_nSelEndPos, FALSE, &nCaretX ); } pElement = GetElement(0); std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { m_pParent->DrawDlgText( (*iter)->pUniBuffer->GetBuffer(), pElement, m_Property.LineEditBoxProperty.dwTextColor, (*iter)->TextCoord, -1, pElement->dwFontFormat, true ); //m_pParent->DrawRect( (*iter)->TextCoord, EtInterface::debug::YELLOW ); //if( (*iter)->nCaretPos != m_nSelStartPos ) //{ // int nFirstToRender, nNumChatToRender; // nFirstToRender = max( 0, min( m_nSelStartPos, (*iter)->nCaretPos ) ); // nNumChatToRender = max( m_nSelStartPos, (*iter)->nCaretPos ) - nFirstToRender; // m_pParent->DrawDlgText( (*iter)->pUniBuffer->GetBuffer() + nFirstToRender, pElement, // m_Property.LineEditBoxProperty.dwSelTextColor, SelectionCoord, // -1, pElement->dwFontFormat, true ); //} } LARGE_INTEGER liCurTime, liFrequency; float fElapsedBlinkTime; QueryPerformanceCounter( &liCurTime ); QueryPerformanceFrequency( &liFrequency ); fElapsedBlinkTime = ( ( float )( liCurTime.QuadPart - m_liLastBlinkTime.QuadPart ) ) / liFrequency.QuadPart; if( fElapsedBlinkTime >= m_fCaretBlinkTime ) { m_bCaretOn = !m_bCaretOn; m_liLastBlinkTime = liCurTime; } SUICoord CaretCoord; CaretCoord = pBufferInfo->TextCoord; CaretCoord.fX += ( ( float )( -nXFirst + nCaretX - 1 ) ) / m_pParent->GetScreenWidth(); CaretCoord.fWidth = 2.0f / m_pParent->GetScreenWidth(); if (IsFocus()) { CEtUIEditBox::s_CurrentCaretPos = CaretCoord; if( m_pParent ) { CEtUIEditBox::s_CurrentCaretPos.fX += m_pParent->GetXCoord(); CEtUIEditBox::s_CurrentCaretPos.fY += m_pParent->GetYCoord(); } } if( ( m_bFocus ) && ( m_bCaretOn ) && ( !CEtUIIME::s_bHideCaret ) ) { if( !m_bInsertMode ) { int nRightEdgeX; //pBufferInfo->CPtoX( pBufferInfo->nCaretPos, TRUE, &nRightEdgeX ); nRightEdgeX = FontMng.GetCaretPos( pBufferInfo->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, pBufferInfo->nCaretPos ); CaretCoord.fWidth = pBufferInfo->TextCoord.fX + ( ( float )( nRightEdgeX - nXFirst ) ) / m_pParent->GetScreenWidth() - CaretCoord.fX; } bool bEnableZ = GetEtDevice()->EnableZ( false ); m_pParent->DrawRect( CaretCoord, m_Property.LineEditBoxProperty.dwCaretColor ); GetEtDevice()->EnableZ( bEnableZ ); } } void CEtUILineEditBox::PlaceCaret( SBufferInfo *pBufferInfo, int nCP ) { if( !pBufferInfo ) return; if( nCP < 0 ) return; if( nCP > pBufferInfo->GetTextSize() ) return; //ASSERT( pBufferInfo ); //ASSERT( ( nCP >= 0 ) && ( nCP <= pBufferInfo->GetTextSize() ) ); pBufferInfo->nCaretPos = nCP; pBufferInfo->nOriginCaretPos = GetOriginTextCaretPos( pBufferInfo, nCP, true ); } int CEtUILineEditBox::GetOriginTextCaretPos( SBufferInfo* pBufferInfo, int nCaretPos, bool bRetWithCalcTagLast ) { if( nCaretPos == 0 || pBufferInfo == NULL || pBufferInfo->pOriginUniBuffer == NULL ) return 0; std::wstring text = pBufferInfo->pOriginUniBuffer->GetBuffer(); int caretPosFound = 0; int OriginTextCaretPos = 0; bool bInsideTag = false; WORD sep = EtInterface::GetNameLinkMgr().GetNameLinkSeperator(); while( OriginTextCaretPos < int(text.size()) ) { if( nCaretPos == caretPosFound ) { if( bRetWithCalcTagLast ) { if( bInsideTag ) { std::wstring parsee = text.substr( OriginTextCaretPos, std::wstring::npos ); std::wstring targetTag; targetTag = FormatW( L"%ce", sep ); std::wstring::size_type loc = parsee.find( targetTag.c_str() ); OriginTextCaretPos += (loc != std::wstring::npos) ? int(loc + 2) : int(parsee.length()); } } else { CEtUINameLinkMgr::eNameLinkTagType type = EtInterface::GetNameLinkMgr().IsTagType( text, OriginTextCaretPos ); if( type != CEtUINameLinkMgr::eNLTAG_NONE ) { std::wstring parsee = text.substr( OriginTextCaretPos, std::wstring::npos ); std::wstring targetTag; targetTag = FormatW( L"%ce", sep ); std::wstring::size_type loc = parsee.find( targetTag.c_str() ); OriginTextCaretPos += (loc != std::wstring::npos) ? int(loc + 2) : int(parsee.length()); } } break; } CEtUINameLinkMgr::eNameLinkTagType type = EtInterface::GetNameLinkMgr().IsTagType( text, OriginTextCaretPos ); if( type != CEtUINameLinkMgr::eNLTAG_NONE ) { if( type == CEtUINameLinkMgr::eNLTAG_START ) bInsideTag = true; else if( type == CEtUINameLinkMgr::eNLTAG_END ) bInsideTag = false; // todo by kalliste : parsee 의 태그 텍스트 길이가 일정 이하일 때 에러처리. 할 필요가 없으면 태그 타입에 따라 고정값 넘기는 함수 사용. int offset = 0; std::wstring parsee = text.substr( ++OriginTextCaretPos, std::wstring::npos ); EtInterface::GetNameLinkMgr().GetTagOffsetByParseText( parsee, offset ); OriginTextCaretPos += offset; } else { ++caretPosFound; ++OriginTextCaretPos; } } return OriginTextCaretPos; } int CEtUILineEditBox::GetTextCaretPos( SBufferInfo* pBufferInfo, int nOriginTextCaretPos ) { if( nOriginTextCaretPos <= 0 || pBufferInfo == NULL || pBufferInfo->pOriginUniBuffer == NULL ) return 0; std::wstring text = pBufferInfo->pOriginUniBuffer->GetBuffer(); std::wstring::size_type linkStartPos = 0; int caretPosFound = 0; int curFullCaretPos = 0; bool bInsideTag = false; while( curFullCaretPos < int(text.size()) && (curFullCaretPos < nOriginTextCaretPos) ) { CEtUINameLinkMgr::eNameLinkTagType type = EtInterface::GetNameLinkMgr().IsTagType( text, curFullCaretPos ); if( type != CEtUINameLinkMgr::eNLTAG_NONE ) { int offset = 0; std::wstring parsee = text.substr( curFullCaretPos + 1, std::wstring::npos ); EtInterface::GetNameLinkMgr().GetTagOffsetByParseText( parsee, offset ); curFullCaretPos += (offset + 1); } else { ++caretPosFound; ++curFullCaretPos; } } return caretPosFound; } void CEtUILineEditBox::PlaceCaretBegin( SBufferInfo *pBufferInfo ) { ASSERT( pBufferInfo ); PlaceCaret( pBufferInfo, 0 ); } void CEtUILineEditBox::PlaceCaretEnd( SBufferInfo *pBufferInfo ) { ASSERT( pBufferInfo ); PlaceCaret( pBufferInfo, pBufferInfo->GetTextSize() ); } void CEtUILineEditBox::DeleteSelectionText() { if (m_nSelStartLine == m_nSelEndLine && m_nSelStartPos == m_nSelEndPos) return; if( m_nSelStartLine > m_nSelEndLine ) { std::swap( m_nSelStartLine, m_nSelEndLine ); std::swap( m_nSelStartPos, m_nSelEndPos ); std::swap( m_nOriginSelStartPos, m_nOriginSelEndPos ); } else if( m_nSelStartLine == m_nSelEndLine ) { if( m_nSelStartPos > m_nSelEndPos ) { std::swap( m_nSelStartPos, m_nSelEndPos ); std::swap( m_nOriginSelStartPos, m_nOriginSelEndPos ); } } SetCurrentLine( m_nSelStartLine ); // Note : 삭제해야 할 모든 라인을 연결해 준다. for( int i=m_nSelStartLine; i<=m_nSelEndLine; i++ ) { if( i+1 <= m_nSelEndLine ) { SBufferInfo *pCurLine = GetLine(i); pCurLine->pNextLine = GetLine(i+1); } } // Note : 삭제해야할 문자의 개수를 카운트 한다. int nCount(0); for( int i=m_nSelStartLine; iGetTextSize() == 0 ) { // Note : 하나의 라인을 한문자로 간주한다. nCount += 1; } else { nCount += pLine->GetTextSize(); } } nCount -= m_nSelStartPos; nCount += m_nSelEndPos; // Note : 카운트 만큼 문자를 지운다. int nSelLine = m_nSelStartLine; int nSelPos = m_nSelStartPos; int nOriginSelPos = m_nOriginSelStartPos; for( int i=0; i= pBufferInfo->GetTextSize() ) { nSelLine++; nSelPos = 0; nOriginSelPos = 0; pBufferInfo->pNextLine = NULL; continue; } } } i++; } PlaceCaret( GetLine(m_nSelStartLine), m_nSelStartPos ); SetSelectStartPos(); } void CEtUILineEditBox::ResetCaretBlink() { m_bCaretOn = true; QueryPerformanceCounter( &m_liLastBlinkTime ); } void CEtUILineEditBox::CopyStringToClipboard( const wchar_t *wszText ) { if( !::OpenClipboard( NULL ) ) return; HGLOBAL hBlock = NULL; int nLength = (int)wcslen( wszText ); if( nLength > 0 ) { ::EmptyClipboard(); hBlock = ::GlobalAlloc( GMEM_MOVEABLE, sizeof( wchar_t ) * ( nLength + 1 ) ); if( hBlock ) { WCHAR *pwszText = ( WCHAR * )::GlobalLock( hBlock ); if( pwszText ) { memcpy( pwszText, wszText, nLength*sizeof(wchar_t) ); pwszText[nLength] = L'\0'; ::GlobalUnlock( hBlock ); } ::SetClipboardData( CF_UNICODETEXT, hBlock ); } } ::CloseClipboard(); if( hBlock ) { ::GlobalFree( hBlock ); } } void CEtUILineEditBox::CopyToClipboard() { if( IsTextSelected() ) { if( !OpenClipboard( NULL ) ) return; int nSelStartLine = m_nSelStartLine; int nSelEndLine = m_nSelEndLine; int nSelStartPos = m_nSelStartPos; int nSelEndPos = m_nSelEndPos; if( nSelStartLine > nSelEndLine ) { std::swap( nSelStartLine, nSelEndLine ); std::swap( nSelStartPos, nSelEndPos ); } else if( nSelStartLine == nSelEndLine ) { if( nSelStartPos > nSelEndPos ) { std::swap( nSelStartPos, nSelEndPos ); } } wchar_t wszTemp[2048]={0}; int nFirst, nLast; for( int i=nSelStartLine; i<=nSelEndLine; ++i ) { SBufferInfo *pBufferInfo = GetLine(i); if( !pBufferInfo ) continue; if( i > nSelStartLine ) { nFirst = 0; if( pBufferInfo->pPrevLine == NULL ) { wcscat_s( wszTemp, _countof(wszTemp), L"\r\n" ); } } else { nFirst = nSelStartPos; } if( i < nSelEndLine ) { nLast = pBufferInfo->GetTextSize(); } else { nLast = nSelEndPos; } wcsncat_s( wszTemp, _countof(wszTemp), pBufferInfo->pUniBuffer->GetBuffer()+nFirst, (nLast-nFirst) ); } // Note : 라인에디터에서 복사한 텍스트를 클립보드에 카피한다. // HGLOBAL hBlock = NULL; int nLength = (int)wcslen(wszTemp); if( nLength > 0 ) { EmptyClipboard(); hBlock = GlobalAlloc( GMEM_MOVEABLE, sizeof( wchar_t ) * ( nLength + 1 ) ); if( hBlock ) { WCHAR *pwszText = ( WCHAR * )GlobalLock( hBlock ); if( pwszText ) { memcpy( pwszText, wszTemp, nLength*sizeof(wchar_t) ); pwszText[nLength] = L'\0'; GlobalUnlock( hBlock ); } SetClipboardData( CF_UNICODETEXT, hBlock ); } } CloseClipboard(); if( hBlock ) { GlobalFree( hBlock ); } } } void CEtUILineEditBox::SetTextBuffer( const WCHAR* pwszText ) { if( pwszText == NULL ) return; int nLength = (int)wcslen(pwszText); for( int i=0; iIsEndCaret() ) { if( AddLine( pBufferInfo ) ) DownCurrentLine(); } else { SplitLineToAdd( pBufferInfo ); } SetSelectStartPos(); } else { InsertCharLine( pBufferInfo, pBufferInfo->nCaretPos, pwszText[i], true ); SetSelectStartPos(); } } } void CEtUILineEditBox::AddText( LPCWSTR wszText, bool bFocus ) { ASSERT( wszText != NULL ); std::wstring translated; int pureTextLength = EtInterface::GetNameLinkMgr().TranslateText( translated, wszText ); if( IsTextFull( pureTextLength ) ) return; SBufferInfo* pBufferInfo = GetCurrentLine(); if( pBufferInfo ) { int nTagFieldStart, nTagFieldEnd; if( IsInTagField( pBufferInfo, pBufferInfo->nCaretPos, nTagFieldStart, nTagFieldEnd ) ) { pBufferInfo->nCaretPos = GetTextCaretPos( pBufferInfo, nTagFieldEnd ); } std::wstring strBuffer = pBufferInfo->pOriginUniBuffer->GetBuffer(); int nBufferLength = static_cast( strBuffer.length() ); if( pBufferInfo->nOriginCaretPos == nBufferLength ) { strBuffer += wszText; } else { std::wstring strTemp = strBuffer; if( nBufferLength - pBufferInfo->nOriginCaretPos > 0 ) strBuffer.erase( pBufferInfo->nOriginCaretPos, nBufferLength - pBufferInfo->nOriginCaretPos ); if( pBufferInfo->nOriginCaretPos > 0 ) strTemp.erase( 0, pBufferInfo->nOriginCaretPos ); strBuffer += wszText; strBuffer += strTemp; } pBufferInfo->pOriginUniBuffer->SetText( strBuffer.c_str() ); pBufferInfo->nOriginCaretPos += static_cast( strBuffer.length() ); } SetTextBuffer( translated.c_str() ); } bool CEtUILineEditBox::CheckTagTextInsertPos( SBufferInfo* pBufferInfo, int nIndex ) { if( pBufferInfo == NULL ) return false; bool bInTagField = false; int nTagFieldStart, nTagFieldEnd; if( IsInTagField( pBufferInfo, nIndex, nTagFieldStart, nTagFieldEnd ) ) { pBufferInfo->nCaretPos = GetTextCaretPos( pBufferInfo, nTagFieldEnd ); pBufferInfo->nOriginCaretPos = GetOriginTextCaretPos( pBufferInfo, pBufferInfo->nCaretPos, false ); bInTagField = true; } return bInTagField; } bool CEtUILineEditBox::CheckTagTextRemove( SBufferInfo* pBufferInfo, int nCaretPos ) { if( pBufferInfo == NULL ) return false; bool bInTagField = false; int nTagFieldStart, nTagFieldEnd; if( IsInTagField( pBufferInfo, nCaretPos, nTagFieldStart, nTagFieldEnd ) ) { int nTextStart = GetTextCaretPos( pBufferInfo, nTagFieldStart ); int nTextEnd = GetTextCaretPos( pBufferInfo, nTagFieldEnd ); for( int i=nTextStart; inCaretPos = nTextStart; pBufferInfo->nOriginCaretPos = nTagFieldStart; bInTagField = true; } return bInTagField; } bool CEtUILineEditBox::IsInTagField( SBufferInfo* pBufferInfo, int nCaretPos, int& nTagFieldStart, int& nTagFieldEnd ) { if( pBufferInfo == NULL || pBufferInfo->pOriginUniBuffer == NULL ) return false; if( pBufferInfo->GetTextSize() == pBufferInfo->GetOriginTextSize() ) return false; bool bInTagField = false; std::wstring fullText = pBufferInfo->pOriginUniBuffer->GetBuffer(); int nOriginCaretPos = GetOriginTextCaretPos( pBufferInfo, nCaretPos, false ); std::wstring targetTag; std::wstring::size_type tagStart, tagEnd; tagStart = tagEnd = std::wstring::npos; EtInterface::GetNameLinkMgr().MakeTag( targetTag, CEtUINameLinkMgr::eNLTAG_START ); tagStart = fullText.rfind( targetTag, nOriginCaretPos ); if( tagStart != std::wstring::npos ) { EtInterface::GetNameLinkMgr().MakeTag( targetTag, CEtUINameLinkMgr::eNLTAG_END ); tagEnd = fullText.find( targetTag, tagStart ); if( int(tagStart) <= nOriginCaretPos && nOriginCaretPos < int(tagEnd) ) { nTagFieldStart = int(tagStart); nTagFieldEnd = int(tagEnd); bInTagField = true; } } return bInTagField; } void CEtUILineEditBox::PasteFromClipboard() { DeleteSelectionText(); if( !OpenClipboard( NULL ) ) return; HANDLE handle = GetClipboardData( CF_UNICODETEXT ); if( handle ) { WCHAR *pwszText = ( WCHAR * )GlobalLock( handle ); if( pwszText ) { AddText( pwszText, true ); GlobalUnlock( handle ); } } CloseClipboard(); } bool CEtUILineEditBox::IsMaxLine() { float fHeight(0.0f); std::list::iterator iter = m_listBuffer.begin(); if( iter != m_listBuffer.end() ) { if( m_Property.UIType == UI_CONTROL_LINE_IMEEDITBOX ) { fHeight = m_Property.LineIMEEditBoxProperty.fLineSpace; } else if( m_Property.UIType == UI_CONTROL_LINE_EDITBOX ) { fHeight = m_Property.LineEditBoxProperty.fLineSpace; } fHeight += (*iter)->TextCoord.fHeight; fHeight *= ((int)m_listBuffer.size()+1); } if( m_Property.UICoord.fHeight < fHeight ) return false; else return true; } int CEtUILineEditBox::GetLineMouseIn( float fX, float fY ) { std::list::iterator iter = m_listBuffer.begin(); for( int i=0; iter != m_listBuffer.end(); ++iter, i++ ) { if( (*iter)->IsInside( fX, fY ) == true ) return i; } return -1; } CEtUILineEditBox::SBufferInfo *CEtUILineEditBox::AddLine( SBufferInfo *pLine ) { if( !IsMaxLine() ) return NULL; SBufferInfo *pBufferInfo = new SBufferInfo( /*m_pFont*/ ); if( pLine == NULL ) { m_listBuffer.push_front( pBufferInfo ); } else { std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { if( (*iter) == pLine ) { iter = m_listBuffer.insert( ++iter, pBufferInfo ); break; } } if (iter == m_listBuffer.end()) SAFE_DELETE(pBufferInfo); } UpdateRects(); return pBufferInfo; } bool CEtUILineEditBox::AppendLine( SBufferInfo *pLine ) { if( !IsMaxLine() ) return false; if( !pLine ) return false; std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { if( (*iter) == pLine ) { SBufferInfo *pBufferInfo = new SBufferInfo( /*m_pFont*/ ); SBufferInfo *pNextLine = pLine->pNextLine; if( pNextLine ) { pBufferInfo->pNextLine = pNextLine; pNextLine->pPrevLine = pBufferInfo; } pLine->pNextLine = pBufferInfo; pBufferInfo->pPrevLine = pLine; m_listBuffer.insert( ++iter, pBufferInfo ); UpdateRects(); break; } } return true; } void CEtUILineEditBox::DeleteLine( SBufferInfo *pLine ) { if( !pLine ) return; std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { SBufferInfo* pInfo = *iter; if( pInfo == pLine ) { SBufferInfo *pPrevLine = pLine->pPrevLine; SBufferInfo *pNextLine = pLine->pNextLine; if( pPrevLine ) pPrevLine->pNextLine = pNextLine; if( pNextLine ) pNextLine->pPrevLine = pPrevLine; SAFE_DELETE(pInfo); m_listBuffer.erase( iter ); UpdateRects(); return; } } } void CEtUILineEditBox::UpCurrentLine() { AdjustCaretPosition( GetLine( m_nCurLine ), GetLine( m_nCurLine-1) ); m_nCurLine--; if( m_nCurLine < 0 ) { m_nCurLine = 0; } } void CEtUILineEditBox::DownCurrentLine() { AdjustCaretPosition( GetLine( m_nCurLine ), GetLine( m_nCurLine+1) ); m_nCurLine++; if( m_nCurLine >= (int)m_listBuffer.size() ) { m_nCurLine = (int)m_listBuffer.size()-1; } } void CEtUILineEditBox::AdjustCaretPosition( SBufferInfo *pCurLine, SBufferInfo *pNextLine ) { int nCurX(0), nNextX(0); CEtFontMng& FontMng = CEtFontMng::GetInstance(); SUIElement* pElement = GetElement( 0 ); if( pCurLine ) { nCurX = FontMng.GetCaretPos( pCurLine->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, pCurLine->nCaretPos ); //pCurLine->CPtoX( pCurLine->nCaretPos, FALSE, &nCurX ); } else { nCurX = INT_MAX; } if( pNextLine ) { nNextX = FontMng.GetCaretPos( pNextLine->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, pNextLine->GetTextSize() ); //pNextLine->CPtoX( pNextLine->GetTextSize(), FALSE, &nNextX ); if( nCurX <= nNextX ) { int nCaretPos, nTrail; nCaretPos = FontMng.GetCaretFromCaretPos( pNextLine->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, nCurX, nTrail ); //pNextLine->XtoCP( nCurX, &nCaretPos, &nTrail ); PlaceCaret( pNextLine, nCaretPos ); } else { PlaceCaretEnd( pNextLine ); } } } bool CEtUILineEditBox::IsBeginLine( SBufferInfo *pLine ) { if( !pLine ) return false; std::list::iterator iter = m_listBuffer.begin(); if( pLine == (*iter) ) return true; return false; } bool CEtUILineEditBox::IsEndLine( SBufferInfo *pLine ) { if( !pLine ) return false; std::list::reverse_iterator iter = m_listBuffer.rbegin(); if( pLine == (*iter) ) return true; return false; } bool CEtUILineEditBox::IsEmpty() { if( m_listBuffer.empty() ) return true; std::wstring strTemp; bool bEmpty(true); std::list::iterator iter = m_listBuffer.begin(); for( ; iter != m_listBuffer.end(); ++iter ) { int nBufferSize = (*iter)->pUniBuffer->GetBufferSize(); if( nBufferSize ) { strTemp = (*iter)->pUniBuffer->GetBuffer(); if( !strTemp.empty() ) { bEmpty = false; break; } } } return bEmpty; } void CEtUILineEditBox::InsertCharLine( SBufferInfo *pLine, int nIndex, WCHAR wChar, bool bSetText, bool bLineFeed ) { if( !pLine ) return; if (IsTextFull(1)) return; if( !bSetText ) { if( CheckTagTextInsertPos( pLine, nIndex ) ) nIndex = pLine->nCaretPos; } if( pLine->InsertChar( nIndex, wChar ) ) { if( !bSetText && !bLineFeed ) { pLine->InsertOriginChar( GetOriginTextCaretPos( pLine, nIndex, false ), wChar ); pLine->nOriginCaretPos++; } PlaceCaret( pLine, pLine->nCaretPos + 1 ); m_nSelEndPos = m_nSelStartPos = pLine->nCaretPos; m_nOriginSelEndPos = m_nOriginSelStartPos = pLine->nOriginCaretPos; } int nX; int nLastCP = pLine->GetTextSize(); CEtFontMng& FontMng = CEtFontMng::GetInstance(); SUIElement* pElement = GetElement( 0 ); nX = FontMng.GetCaretPos( pLine->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, nLastCP ); int nTextWidth = ( int )( pLine->TextCoord.fWidth * m_pParent->GetScreenWidth() ); if( nX > nTextWidth ) { if( IsEndLine(pLine) || (!pLine->pNextLine) ) { if( AppendLine( pLine ) == false ) { // Note : 더 이상 추가할 수 없다면 바로 전에 추가한 문자를 삭제하고 캐럿의 위치를 조정해준다. pLine->RemoveChar( nLastCP-1 ); pLine->RemoveOriginChar( GetOriginTextCaretPos( pLine, nLastCP - 1, false ) ); PlaceCaret( pLine, pLine->nCaretPos - 1 ); return; } } if( nLastCP == pLine->nCaretPos ) { PlaceCaret( pLine, pLine->nCaretPos - 1 ); if( GetCurrentLine() == pLine ) { DownCurrentLine(); GetLine( m_nCurLine )->nCaretPos = 0; } } int nTagFieldStart, nTagFieldEnd; if( IsInTagField( pLine, nLastCP - 1, nTagFieldStart, nTagFieldEnd ) ) { nLastCP = GetTextCaretPos( pLine, nTagFieldStart - 1 ) + 1; } if( nLastCP - 1 >=0 && nLastCP - 1 < pLine->pUniBuffer->GetBufferSize() ) { WCHAR wCharInner = (*(pLine->pUniBuffer))[nLastCP - 1]; pLine->RemoveChar( nLastCP - 1 ); pLine->RemoveOriginChar( GetOriginTextCaretPos( pLine, nLastCP - 1, false ) ); InsertCharLine( pLine->pNextLine, 0, wCharInner, false, false ); } } } bool CEtUILineEditBox::RemoveCharLine( SBufferInfo *pLine, int nIndex ) { if( !pLine ) return false; bool bRet = pLine->RemoveChar( nIndex ); if (bRet == false) { return false; } if( pLine->pNextLine ) { PasteTrailFromLine( pLine, pLine->pNextLine ); } else { if( (pLine->GetTextSize() == 0) && ( GetCurrentLine() != pLine ) ) { DeleteLine( pLine ); } } return true; } bool CEtUILineEditBox::RemoveOriginCharLine( SBufferInfo* pBufferInfo, int nIndex ) { if( !pBufferInfo ) return false; bool bRet = pBufferInfo->RemoveOriginChar( nIndex ); return bRet; } CEtUILineEditBox::SBufferInfo *CEtUILineEditBox::GetLine( int nLineIndex ) { if( nLineIndex < 0 ) return NULL; std::list::iterator iter = m_listBuffer.begin(); for( int i=0; iter != m_listBuffer.end(); ++iter, ++i ) { if( i >= nLineIndex ) { return (*iter); } } return NULL; } void CEtUILineEditBox::SetCurrentLine( int nLineIndex ) { if( nLineIndex < 0 || nLineIndex >= (int)m_listBuffer.size() ) { _ASSERT(0); return; } m_nCurLine = nLineIndex; } CEtUILineEditBox::SBufferInfo *CEtUILineEditBox::GetCurrentLine() { if( m_nCurLine < 0 ) return NULL; return GetLine( m_nCurLine ); } void CEtUILineEditBox::PasteTrailFromLine( SBufferInfo *pDestLine, SBufferInfo *pSrcLine ) { if (pDestLine == NULL || pSrcLine == NULL) { _ASSERT(0); return; } CEtFontMng& FontMng = CEtFontMng::GetInstance(); SUIElement* pElement = GetElement( 0 ); pDestLine->pNextLine = pSrcLine; pSrcLine->pPrevLine = pDestLine; if( pDestLine->IsEndCaret() && (pSrcLine->GetTextSize() == 0) ) { pDestLine->pNextLine = pSrcLine->pNextLine; DeleteLine( pSrcLine ); return; } int i(0), nX(0), nTextWidth(0); // Note : 삭제된 공간에 들어갈 수 있을때까지 문자를 입력한다. 글자마다 차지하는 공간이 다르기 때문... while(1) { if( i >= pSrcLine->GetTextSize() ) { break; } WCHAR wChar = (*(pSrcLine->pUniBuffer))[i++]; int nTagFieldStart, nTagFieldEnd; bool bInTagField = IsInTagField( pDestLine, pDestLine->GetTextSize(), nTagFieldStart, nTagFieldEnd ); pDestLine->InsertChar( pDestLine->GetTextSize(), wChar ); if( !bInTagField ) pDestLine->InsertOriginChar( pDestLine->GetOriginTextSize(), wChar ); int nLastCP = pDestLine->GetTextSize(); //pDestLine->CPtoX( nLastCP, FALSE, &nX ); nX = FontMng.GetCaretPos( pDestLine->pUniBuffer->GetBuffer(), pElement->nFontIndex, pElement->nFontHeight, nLastCP ); nTextWidth = ( int )( pDestLine->TextCoord.fWidth * m_pParent->GetScreenWidth() ); if( nX > nTextWidth ) { // Note : 마지막에 넘어선 문자는 제거한다. pDestLine->RemoveChar( pDestLine->GetTextSize()-1 ); if( !bInTagField ) pDestLine->RemoveOriginChar( pDestLine->GetOriginTextSize()-1 ); i--; break; } } // Note : 앞 라인에 추가된 개수만큼 삭제를 시켜준다. for( int j=0; jnCaretPos; m_nOriginSelEndPos = m_nOriginSelStartPos = pBufferInfo->nOriginCaretPos; m_nSelEndLine = m_nSelStartLine = m_nCurLine; } } void CEtUILineEditBox::SetSelectEndPos() { SBufferInfo *pBufferInfo = GetCurrentLine(); if( pBufferInfo ) { m_nSelEndPos = pBufferInfo->nCaretPos; m_nOriginSelEndPos = pBufferInfo->nOriginCaretPos; m_nSelEndLine = m_nCurLine; } } void CEtUILineEditBox::SplitLineToAdd( SBufferInfo *pLine ) { if( pLine == NULL ) return; int nTagFieldStart, nTagFieldEnd; if( IsInTagField( pLine, pLine->nCaretPos, nTagFieldStart, nTagFieldEnd ) ) return; std::wstring strTemp( pLine->pUniBuffer->GetBuffer() ); std::wstring strOriginTemp( pLine->pOriginUniBuffer->GetBuffer() ); pLine->pUniBuffer->Clear(); pLine->pUniBuffer->SetText( strTemp.substr( 0, pLine->nCaretPos ).c_str() ); pLine->pOriginUniBuffer->Clear(); pLine->pOriginUniBuffer->SetText( strOriginTemp.substr( 0, pLine->nOriginCaretPos ).c_str() ); SBufferInfo *pAddLine = AddLine( pLine ); if( pAddLine ) { pAddLine->pUniBuffer->SetText( strTemp.substr( pLine->nCaretPos ).c_str() ); pAddLine->pOriginUniBuffer->SetText( strOriginTemp.substr( pLine->nOriginCaretPos ).c_str() ); if( pLine->pNextLine ) { PasteTrailFromLine( pAddLine, pLine->pNextLine ); pLine->pNextLine = NULL; } DownCurrentLine(); PlaceCaretBegin( pAddLine ); } } void CEtUILineEditBox::SetMaxEditLength(DWORD dwMaxLength) { ASSERT( dwMaxLength > 0 ); m_nMaxTextLength = dwMaxLength; } int CEtUILineEditBox::GetTextLength() const { int wholeTextLength = 0; std::list::const_iterator iter = m_listBuffer.begin(); for(; iter != m_listBuffer.end(); ++iter) wholeTextLength += (*iter)->pUniBuffer->GetTextSize(); return wholeTextLength; } bool CEtUILineEditBox::IsTextFull(int textAddedLength) const { int wholeTextLength = GetTextLength(); if (wholeTextLength + textAddedLength < m_nMaxTextLength) return false; return true; }