12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430 |
- #include "stdafx.h"
- #include "afxconv.h"
- #include "Markup.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- #ifdef _MBCS
- #pragma message( "Note: MBCS build (not UTF-8)" )
- #endif
- #ifndef _tclen
- #define _tclen(p) 1
- #define _tccpy(p1,p2) *(p1)=*(p2)
- #endif
- void CMarkup::operator=( const CMarkup& markup )
- {
- m_iPosParent = markup.m_iPosParent;
- m_iPos = markup.m_iPos;
- m_iPosChild = markup.m_iPosChild;
- m_iPosFree = markup.m_iPosFree;
- m_nNodeType = markup.m_nNodeType;
- m_aPos.RemoveAll();
- m_aPos.Append( markup.m_aPos );
- m_csDoc = markup.m_csDoc;
- MARKUP_SETDEBUGSTATE;
- }
- bool CMarkup::SetDoc( LPCTSTR szDoc )
- {
-
- m_iPosFree = 1;
- ResetPos();
- m_mapSavedPos.RemoveAll();
-
- if ( szDoc )
- m_csDoc = szDoc;
- else
- m_csDoc.Empty();
-
-
-
- int nStartSize = m_csDoc.GetLength() / 64 + 8;
- if ( m_aPos.GetSize() < nStartSize )
- m_aPos.SetSize( nStartSize );
-
- bool bWellFormed = false;
- if ( m_csDoc.GetLength() )
- {
- m_aPos[0].Clear();
- int iPos = x_ParseElem( 0 );
- if ( iPos > 0 )
- {
- m_aPos[0].iElemChild = iPos;
- bWellFormed = true;
- }
- }
-
- if ( ! bWellFormed )
- {
- m_aPos[0].Clear();
- m_iPosFree = 1;
- }
- ResetPos();
- return bWellFormed;
- };
- bool CMarkup::IsWellFormed()
- {
- if ( m_aPos.GetSize() && m_aPos[0].iElemChild )
- return true;
- return false;
- }
- bool CMarkup::Load( LPCTSTR szFileName )
- {
- CString csDoc;
- CFile file;
- if ( ! file.Open(szFileName,CFile::modeRead) )
- return false;
- int nLength = file.GetLength();
- #if defined(_UNICODE)
-
- unsigned char* pBuffer = new unsigned char[nLength + 1];
- nLength = file.Read( pBuffer, nLength );
- pBuffer[nLength] = '\0';
-
- int nWideLength = MultiByteToWideChar(CP_UTF8,0,(const char*)pBuffer,nLength,NULL,0);
- nLength = MultiByteToWideChar(CP_UTF8,0,(const char*)pBuffer,nLength,
- csDoc.GetBuffer(nWideLength),nWideLength);
- ASSERT( nLength == nWideLength );
- delete [] pBuffer;
- #else
- nLength = file.Read( csDoc.GetBuffer(nLength), nLength );
- #endif
- csDoc.ReleaseBuffer(nLength);
- file.Close();
- return SetDoc( csDoc );
- }
- bool CMarkup::Save( LPCTSTR szFileName )
- {
- int nLength = m_csDoc.GetLength();
- CFile file;
- if ( ! file.Open(szFileName,CFile::modeWrite|CFile::modeCreate) )
- return false;
- #if defined( _UNICODE )
- int nUTF8Len = WideCharToMultiByte(CP_UTF8,0,m_csDoc,nLength,NULL,0,NULL,NULL);
- char* pBuffer = new char[nUTF8Len+1];
- nLength = WideCharToMultiByte(CP_UTF8,0,m_csDoc,nLength,pBuffer,nUTF8Len+1,NULL,NULL);
- file.Write( pBuffer, nLength );
- delete pBuffer;
- #else
- file.Write( (LPCTSTR)m_csDoc, nLength );
- #endif
- file.Close();
- return true;
- }
- bool CMarkup::FindElem( LPCTSTR szName )
- {
-
-
- if ( m_aPos.GetSize() )
- {
- int iPos = x_FindElem( m_iPosParent, m_iPos, szName );
- if ( iPos )
- {
-
- x_SetPos( m_aPos[iPos].iElemParent, iPos, 0 );
- return true;
- }
- }
- return false;
- }
- bool CMarkup::FindChildElem( LPCTSTR szName )
- {
-
-
-
-
- if ( ! m_iPos )
- FindElem();
- int iPosChild = x_FindElem( m_iPos, m_iPosChild, szName );
- if ( iPosChild )
- {
-
- int iPos = m_aPos[iPosChild].iElemParent;
- x_SetPos( m_aPos[iPos].iElemParent, iPos, iPosChild );
- return true;
- }
- return false;
- }
- CString CMarkup::GetTagName() const
- {
-
- CString csTagName;
- if ( m_iPos )
- csTagName = x_GetTagName( m_iPos );
- return csTagName;
- }
- bool CMarkup::IntoElem()
- {
-
-
-
-
-
-
-
- if ( m_iPos && m_nNodeType == MNT_ELEMENT )
- {
- x_SetPos( m_iPos, m_iPosChild, 0 );
- return true;
- }
- return false;
- }
- bool CMarkup::OutOfElem()
- {
-
- if ( m_iPosParent )
- {
- x_SetPos( m_aPos[m_iPosParent].iElemParent, m_iPosParent, m_iPos );
- return true;
- }
- return false;
- }
- CString CMarkup::GetAttrName( int n ) const
- {
-
- if ( ! m_iPos || m_nNodeType != MNT_ELEMENT )
- return _T("");
- TokenPos token( m_csDoc );
- token.nNext = m_aPos[m_iPos].nStartL + 1;
- for ( int nAttr=0; nAttr<=n; ++nAttr )
- if ( ! x_FindAttr(token) )
- return _T("");
-
- return x_GetToken( token );
- }
- bool CMarkup::SavePos( LPCTSTR szPosName )
- {
-
- if ( szPosName )
- {
- SavedPos savedpos;
- savedpos.iPosParent = m_iPosParent;
- savedpos.iPos = m_iPos;
- savedpos.iPosChild = m_iPosChild;
- m_mapSavedPos.SetAt( szPosName, savedpos );
- return true;
- }
- return false;
- }
- bool CMarkup::RestorePos( LPCTSTR szPosName )
- {
-
- SavedPos savedpos;
- if ( szPosName && m_mapSavedPos.Lookup( szPosName, savedpos ) )
- {
- x_SetPos( savedpos.iPosParent, savedpos.iPos, savedpos.iPosChild );
- return true;
- }
- return false;
- }
- bool CMarkup::GetOffsets( int& nStart, int& nEnd ) const
- {
-
-
- if ( m_iPos )
- {
- nStart = m_aPos[m_iPos].nStartL;
- nEnd = m_aPos[m_iPos].nEndR;
- return true;
- }
- return false;
- }
- CString CMarkup::GetChildSubDoc() const
- {
- if ( m_iPosChild )
- {
- int nL = m_aPos[m_iPosChild].nStartL;
- int nR = m_aPos[m_iPosChild].nEndR + 1;
- TokenPos token( m_csDoc );
- token.nNext = nR;
- if ( ! x_FindToken(token) || m_csDoc[token.nL] == _T('<') )
- nR = token.nL;
- return m_csDoc.Mid( nL, nR - nL );
- }
- return _T("");
- }
- bool CMarkup::RemoveElem()
- {
-
- if ( m_iPos && m_nNodeType == MNT_ELEMENT )
- {
- int iPos = x_RemoveElem( m_iPos );
- x_SetPos( m_iPosParent, iPos, 0 );
- return true;
- }
- return false;
- }
- bool CMarkup::RemoveChildElem()
- {
-
- if ( m_iPosChild )
- {
- int iPosChild = x_RemoveElem( m_iPosChild );
- x_SetPos( m_iPosParent, m_iPos, iPosChild );
- return true;
- }
- return false;
- }
- int CMarkup::x_GetFreePos()
- {
-
-
-
- if ( m_iPosFree == m_aPos.GetSize() )
- m_aPos.SetSize( m_iPosFree + m_iPosFree / 2 );
- ++m_iPosFree;
- return m_iPosFree - 1;
- }
- int CMarkup::x_ReleasePos()
- {
-
-
-
-
- --m_iPosFree;
- return 0;
- }
- int CMarkup::x_ParseError( LPCTSTR szError, LPCTSTR szName )
- {
- if ( szName )
- m_csError.Format( szError, szName );
- else
- m_csError = szError;
- x_ReleasePos();
- return -1;
- }
- int CMarkup::x_ParseElem( int iPosParent )
- {
-
-
-
-
-
- int iPos = x_GetFreePos();
- m_aPos[iPos].nStartL = m_aPos[iPosParent].nEndL;
- m_aPos[iPos].iElemParent = iPosParent;
- m_aPos[iPos].iElemChild = 0;
- m_aPos[iPos].iElemNext = 0;
-
-
-
-
-
- TokenPos token( m_csDoc );
- token.nNext = m_aPos[iPosParent].nEndL;
- CString csName;
- while ( csName.IsEmpty() )
- {
-
- m_aPos[iPos].nStartL = token.nNext;
- if ( ! x_FindChar( token.szDoc, m_aPos[iPos].nStartL, _T('<') ) )
- return x_ParseError( _T("Element tag not found") );
-
- m_aPos[iPosParent].nEndL = m_aPos[iPos].nStartL;
-
- token.nNext = m_aPos[iPos].nStartL + 1;
- if ( x_FindToken( token ) )
- {
- if ( token.bIsString )
- return x_ParseError( _T("Tag starts with quote") );
- _TCHAR cFirstChar = m_csDoc[token.nL];
- if ( cFirstChar == _T('?') || cFirstChar == _T('!') )
- {
- token.nNext = m_aPos[iPos].nStartL;
- if ( ! x_ParseNode(token) )
- return x_ParseError( _T("Invalid node") );
- }
- else if ( cFirstChar != _T('/') )
- {
- csName = x_GetToken( token );
-
- if ( ! x_FindChar(token.szDoc, token.nNext, _T('>')) )
- return x_ParseError( _T("End of tag not found") );
- }
- else
- return x_ReleasePos();
- }
- else
- return x_ParseError( _T("Abrupt end within tag") );
- }
- m_aPos[iPos].nStartR = token.nNext;
-
- if ( m_csDoc[m_aPos[iPos].nStartR-1] == _T('/') )
- {
-
-
- m_aPos[iPos].nEndL = m_aPos[iPos].nStartR-1;
- m_aPos[iPos].nEndR = m_aPos[iPos].nStartR;
- }
- else
- {
-
-
-
- int iInner, iInnerPrev = 0;
- m_aPos[iPos].nEndL = m_aPos[iPos].nStartR + 1;
- while ( (iInner = x_ParseElem( iPos )) > 0 )
- {
-
- if ( iInnerPrev )
- m_aPos[iInnerPrev].iElemNext = iInner;
- else
- m_aPos[iPos].iElemChild = iInner;
- iInnerPrev = iInner;
-
- m_aPos[iPos].nEndL = m_aPos[iInner].nEndR + 1;
- }
- if ( iInner == -1 )
- return -1;
-
- if ( ! x_FindChar( token.szDoc, m_aPos[iPos].nEndL, _T('<') ) )
- return x_ParseError( _T("End tag of %s element not found"), csName );
-
- token.nNext = m_aPos[iPos].nEndL + 1;
- int nTokenCount = 0;
- while ( x_FindToken( token ) )
- {
- ++nTokenCount;
- if ( ! token.bIsString )
- {
-
- if ( nTokenCount == 1 && m_csDoc[token.nL] != _T('/') )
- return x_ParseError( _T("Expecting end tag of element %s"), csName );
- else if ( nTokenCount == 2 && ! token.Match(csName) )
- return x_ParseError( _T("End tag does not correspond to %s"), csName );
-
- else if ( m_csDoc[token.nL] == _T('>') )
- break;
- }
- }
-
- if ( ! token.szDoc[token.nL] || nTokenCount < 2 )
- return x_ParseError( _T("End tag not completed for element %s"), csName );
- m_aPos[iPos].nEndR = token.nL;
- }
-
- return iPos;
- }
- bool CMarkup::x_FindChar( LPCTSTR szDoc, int& nChar, _TCHAR c )
- {
-
- LPCTSTR pChar = &szDoc[nChar];
- while ( *pChar && *pChar != c )
- pChar += _tclen( pChar );
- nChar = pChar - szDoc;
- if ( ! *pChar )
- return false;
-
- return true;
- }
- bool CMarkup::x_FindToken( CMarkup::TokenPos& token )
- {
-
-
-
- LPCTSTR szDoc = token.szDoc;
- int nChar = token.nNext;
- token.bIsString = false;
-
- while ( szDoc[nChar] && _tcschr(_T(" \t\n\r"),szDoc[nChar]) )
- ++nChar;
- if ( ! szDoc[nChar] )
- {
-
- token.nL = nChar;
- token.nR = nChar;
- token.nNext = nChar;
- return false;
- }
-
- _TCHAR cFirstChar = szDoc[nChar];
- if ( cFirstChar == _T('\"') || cFirstChar == _T('\'') )
- {
- token.bIsString = true;
-
- ++nChar;
- token.nL = nChar;
-
- x_FindChar( token.szDoc, nChar, cFirstChar );
-
- token.nR = nChar - 1;
-
- if ( szDoc[nChar] )
- ++nChar;
- }
- else
- {
-
- token.nL = nChar;
- while ( szDoc[nChar] && ! _tcschr(_T(" \t\n\r<>=\\/?!"),szDoc[nChar]) )
- nChar += _tclen(&szDoc[nChar]);
-
- if ( nChar == token.nL )
- ++nChar;
- token.nR = nChar - 1;
- }
-
- token.nNext = nChar;
- return true;
- }
- CString CMarkup::x_GetToken( const CMarkup::TokenPos& token ) const
- {
-
-
- if ( token.nL > token.nR )
- return _T("");
- return m_csDoc.Mid( token.nL,
- token.nR - token.nL + ((token.nR<m_csDoc.GetLength())? 1:0) );
- }
- int CMarkup::x_FindElem( int iPosParent, int iPos, LPCTSTR szPath )
- {
-
-
-
- if ( iPos )
- iPos = m_aPos[iPos].iElemNext;
- else
- iPos = m_aPos[iPosParent].iElemChild;
-
- if ( szPath == NULL || !szPath[0] )
- return iPos;
-
- TokenPos token( m_csDoc );
- while ( iPos )
- {
-
- token.nNext = m_aPos[iPos].nStartL + 1;
- x_FindToken( token );
- if ( token.Match(szPath) )
- return iPos;
- iPos = m_aPos[iPos].iElemNext;
- }
- return 0;
- }
- int CMarkup::x_ParseNode( CMarkup::TokenPos& token )
- {
-
-
-
-
- int nTypeFound = 0;
- LPCTSTR szDoc = token.szDoc;
- token.nL = token.nNext;
- if ( szDoc[token.nL] == '<' )
- {
-
-
-
-
-
-
-
- if ( ! szDoc[token.nL+1] || ! szDoc[token.nL+2] )
- return 0;
- _TCHAR cFirstChar = szDoc[token.nL+1];
- LPCTSTR szEndOfNode = NULL;
- if ( cFirstChar == _T('?') )
- {
- nTypeFound = MNT_PROCESSING_INSTRUCTION;
- szEndOfNode = _T("?>");
- }
- else if ( cFirstChar == _T('!') )
- {
- _TCHAR cSecondChar = szDoc[token.nL+2];
- if ( cSecondChar == _T('[') )
- {
- nTypeFound = MNT_CDATA_SECTION;
- szEndOfNode = _T("]]>");
- }
- else if ( cSecondChar == _T('-') )
- {
- nTypeFound = MNT_COMMENT;
- szEndOfNode = _T("-->");
- }
- else
- {
-
- nTypeFound = 0;
- int nBrackets = 0;
- while ( x_FindToken(token) )
- {
- if ( ! token.bIsString )
- {
- _TCHAR cChar = szDoc[token.nL];
- if ( cChar == _T('[') )
- ++nBrackets;
- else if ( cChar == _T(']') )
- --nBrackets;
- else if ( nBrackets == 0 && cChar == _T('>') )
- {
- nTypeFound = MNT_DOCUMENT_TYPE;
- break;
- }
- }
- }
- if ( ! nTypeFound )
- return 0;
- }
- }
- else if ( cFirstChar == _T('/') )
- {
-
- return 0;
- }
- else
- {
- nTypeFound = MNT_ELEMENT;
- }
-
- if ( szEndOfNode )
- {
- LPCTSTR pEnd = _tcsstr( &szDoc[token.nNext], szEndOfNode );
- if ( ! pEnd )
- return 0;
- token.nNext = (pEnd - szDoc) + _tcslen(szEndOfNode);
- }
- }
- else if ( szDoc[token.nL] )
- {
-
- nTypeFound = MNT_WHITESPACE;
- if ( x_FindToken(token) )
- {
- if ( szDoc[token.nL] == _T('<') )
- token.nNext = token.nL;
- else
- {
- nTypeFound = MNT_TEXT;
- x_FindChar( token.szDoc, token.nNext, _T('<') );
- }
- }
- }
- return nTypeFound;
- }
- CString CMarkup::x_GetTagName( int iPos ) const
- {
-
- TokenPos token( m_csDoc );
- token.nNext = m_aPos[iPos].nStartL + 1;
- if ( ! iPos || ! x_FindToken( token ) )
- return _T("");
-
- return x_GetToken( token );
- }
- bool CMarkup::x_FindAttr( CMarkup::TokenPos& token, LPCTSTR szAttr ) const
- {
-
-
- int nAttr = 0;
- for ( int nCount = 0; x_FindToken(token); ++nCount )
- {
- if ( ! token.bIsString )
- {
-
- if ( m_csDoc[token.nL] == _T('>') || m_csDoc[token.nL] == _T('/') )
- break;
-
- if ( m_csDoc[token.nL] == _T('=') )
- continue;
-
- if ( ! nAttr && nCount )
- {
-
- if ( ! szAttr || ! szAttr[0] )
- return true;
-
- if ( token.Match(szAttr) )
- nAttr = nCount;
- }
- }
- else if ( nAttr && nCount == nAttr + 2 )
- {
- return true;
- }
- }
-
- return false;
- }
- CString CMarkup::x_GetAttr( int iPos, LPCTSTR szAttr ) const
- {
-
- if ( ! iPos || m_nNodeType != MNT_ELEMENT )
- return _T("");
- TokenPos token( m_csDoc );
- token.nNext = m_aPos[iPos].nStartL + 1;
- if ( szAttr && x_FindAttr( token, szAttr ) )
- return x_TextFromDoc( token.nL, token.nR - ((token.nR<m_csDoc.GetLength())?0:1) );
- return _T("");
- }
- bool CMarkup::x_SetAttr( int iPos, LPCTSTR szAttr, int nValue )
- {
-
- _TCHAR szVal[25];
- _stprintf( szVal, _T("%d"), nValue );
- return x_SetAttr( iPos, szAttr, szVal );
- }
- bool CMarkup::x_SetAttr( int iPos, LPCTSTR szAttr, LPCTSTR szValue )
- {
-
- if ( ! iPos || m_nNodeType != MNT_ELEMENT )
- return false;
- TokenPos token( m_csDoc );
- token.nNext = m_aPos[iPos].nStartL + 1;
- int nInsertAt, nReplace = 0;
- CString csInsert;
- if ( x_FindAttr( token, szAttr ) )
- {
-
-
- csInsert = x_TextToDoc( szValue, true );
- nInsertAt = token.nL;
- nReplace = token.nR-token.nL+1;
- }
- else
- {
-
- CString csFormat;
- csFormat = _T(" ");
- csFormat += szAttr;
- csFormat += _T("=\"");
- csFormat += x_TextToDoc( szValue, true );
- csFormat += _T("\"");
- csInsert = csFormat;
-
- nInsertAt = m_aPos[iPos].nStartR - (m_aPos[iPos].IsEmptyElement()?1:0);
- }
- x_DocChange( nInsertAt, nReplace, csInsert );
- int nAdjust = csInsert.GetLength() - nReplace;
- m_aPos[iPos].nStartR += nAdjust;
- m_aPos[iPos].AdjustEnd( nAdjust );
- x_Adjust( iPos, nAdjust );
- MARKUP_SETDEBUGSTATE;
- return true;
- }
- bool CMarkup::x_CreateNode( CString& csNode, int nNodeType, LPCTSTR szText )
- {
-
-
-
- switch ( nNodeType )
- {
- case MNT_CDATA_SECTION:
- if ( _tcsstr(szText,_T("]]>")) != NULL )
- return false;
- csNode = "<![CDATA[";
- csNode += szText;
- csNode += "]]>";
- break;
- }
- return true;
- }
- bool CMarkup::x_SetData( int iPos, LPCTSTR szData, int nCDATA )
- {
-
-
- CString csInsert;
-
- if ( ! iPos || m_aPos[iPos].iElemChild )
- return false;
-
-
- if ( nCDATA != 0 )
- if ( ! x_CreateNode(csInsert, MNT_CDATA_SECTION, szData) )
- nCDATA = 0;
- if ( nCDATA == 0 )
- csInsert = x_TextToDoc( szData );
-
- int nInsertAt, nReplace;
- if ( m_aPos[iPos].IsEmptyElement() )
- {
- nInsertAt = m_aPos[iPos].nEndL;
- nReplace = 1;
-
- CString csTagName = x_GetTagName( iPos );
- m_aPos[iPos].nStartR -= 1;
- m_aPos[iPos].nEndL -= (1 + csTagName.GetLength());
- CString csFormat;
- csFormat = _T(">");
- csFormat += csInsert;
- csFormat += _T("</");
- csFormat += csTagName;
- csInsert = csFormat;
- }
- else
- {
- nInsertAt = m_aPos[iPos].nStartR+1;
- nReplace = m_aPos[iPos].nEndL - m_aPos[iPos].nStartR - 1;
- }
- x_DocChange( nInsertAt, nReplace, csInsert );
- int nAdjust = csInsert.GetLength() - nReplace;
- x_Adjust( iPos, nAdjust );
- m_aPos[iPos].AdjustEnd( nAdjust );
- MARKUP_SETDEBUGSTATE;
- return true;
- }
- CString CMarkup::x_GetData( int iPos ) const
- {
-
-
- if ( ! m_aPos[iPos].iElemChild && ! m_aPos[iPos].IsEmptyElement() )
- {
-
- TokenPos token( m_csDoc );
- token.nNext = m_aPos[iPos].nStartR+1;
- if ( x_FindToken( token ) && m_csDoc[token.nL] == _T('<')
- && token.nL + 11 < m_aPos[iPos].nEndL
- && _tcsncmp( &token.szDoc[token.nL+1], _T("![CDATA["), 8 ) == 0 )
- {
- int nEndCDATA = m_csDoc.Find( _T("]]>"), token.nNext );
- if ( nEndCDATA != -1 && nEndCDATA < m_aPos[iPos].nEndL )
- {
- return m_csDoc.Mid( token.nL+9, nEndCDATA-token.nL-9 );
- }
- }
- return x_TextFromDoc( m_aPos[iPos].nStartR+1, m_aPos[iPos].nEndL-1 );
- }
- return _T("");
- }
- CString CMarkup::x_TextToDoc( LPCTSTR szText, bool bAttr ) const
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
- static _TCHAR* szaReplace[] = { _T("<"),_T("&"),_T(">"),_T("'"),_T(""") };
- const _TCHAR* pFind = bAttr?_T("<&>\'\""):_T("<&>");
- CString csText;
- const _TCHAR* pSource = szText;
- int nDestSize = _tcslen(pSource);
- nDestSize += nDestSize / 10 + 7;
- _TCHAR* pDest = csText.GetBuffer(nDestSize);
- int nLen = 0;
- _TCHAR cSource = *pSource;
- _TCHAR* pFound;
- while ( cSource )
- {
- if ( nLen > nDestSize - 6 )
- {
- csText.ReleaseBuffer(nLen);
- nDestSize *= 2;
- pDest = csText.GetBuffer(nDestSize);
- }
- if ( (pFound=_tcschr(pFind,cSource)) != NULL )
- {
- pFound = szaReplace[pFound-pFind];
- _tcscpy(&pDest[nLen],pFound);
- nLen += _tcslen(pFound);
- }
- else
- {
- _tccpy( &pDest[nLen], pSource );
- ++nLen;
- }
- pSource += _tclen( pSource );
- cSource = *pSource;
- }
- csText.ReleaseBuffer(nLen);
- return csText;
- }
- CString CMarkup::x_TextFromDoc( int nLeft, int nRight ) const
- {
-
-
-
-
-
-
- static _TCHAR* szaCode[] = { _T("lt;"),_T("amp;"),_T("gt;"),_T("apos;"),_T("quot;") };
- static int anCodeLen[] = { 3,4,3,5,5 };
- static _TCHAR* szSymbol = _T("<&>\'\"");
- CString csText;
- const _TCHAR* pSource = m_csDoc;
- int nDestSize = nRight - nLeft + 1;
- _TCHAR* pDest = csText.GetBuffer(nDestSize);
- int nLen = 0;
- int nCharLen;
- int nChar = nLeft;
- while ( nChar <= nRight )
- {
- if ( pSource[nChar] == _T('&') )
- {
-
- for ( int nMatch = 0; nMatch < 5; ++nMatch )
- {
- if ( nChar <= nRight - anCodeLen[nMatch]
- && _tcsncmp(szaCode[nMatch],&pSource[nChar+1],anCodeLen[nMatch]) == 0 )
- {
- pDest[nLen++] = szSymbol[nMatch];
- nChar += anCodeLen[nMatch] + 1;
- break;
- }
- }
-
-
- if ( nMatch == 5 )
- {
- pDest[nLen++] = _T('&');
- ++nChar;
- }
- }
- else
- {
- nCharLen = _tclen(&pSource[nChar]);
- _tccpy( &pDest[nLen], &pSource[nChar] );
- nLen += nCharLen;
- nChar += nCharLen;
- }
- }
- csText.ReleaseBuffer(nLen);
- return csText;
- }
- void CMarkup::x_DocChange( int nLeft, int nReplace, const CString& csInsert )
- {
-
-
-
- int nDocLength = m_csDoc.GetLength();
- int nInsLength = csInsert.GetLength();
-
- nLeft = max( 0, min( nLeft, nDocLength ) );
- nReplace = max( 0, min( nReplace, nDocLength-nLeft ) );
-
- int nNewLength = nInsLength + nDocLength - nReplace;
- int nBufferLen = nNewLength;
- _TCHAR* pDoc = m_csDoc.GetBuffer( nBufferLen );
-
- if ( nLeft+nReplace < nDocLength )
- memmove( &pDoc[nLeft+nInsLength], &pDoc[nLeft+nReplace], (nDocLength-nLeft-nReplace)*sizeof(_TCHAR) );
-
- memcpy( &pDoc[nLeft], csInsert, nInsLength*sizeof(_TCHAR) );
-
- m_csDoc.ReleaseBuffer( nNewLength );
- }
- void CMarkup::x_Adjust( int iPos, int nShift, bool bAfterPos )
- {
-
-
-
-
-
-
-
- int iPosTop = m_aPos[iPos].iElemParent;
- bool bPosFirst = bAfterPos;
- while ( iPos )
- {
-
- bool bPosTop = false;
- if ( iPos == iPosTop )
- {
-
- iPosTop = m_aPos[iPos].iElemParent;
- bPosTop = true;
- }
-
- if ( ! bPosTop && ! bPosFirst && m_aPos[iPos].iElemChild )
- {
-
- iPos = m_aPos[iPos].iElemChild;
- }
- else if ( m_aPos[iPos].iElemNext )
- {
- iPos = m_aPos[iPos].iElemNext;
- }
- else
- {
-
-
- while ( (iPos=m_aPos[iPos].iElemParent) != 0 && iPos != iPosTop )
- if ( m_aPos[iPos].iElemNext )
- {
- iPos = m_aPos[iPos].iElemNext;
- break;
- }
- }
- bPosFirst = false;
-
- if ( iPos != iPosTop )
- m_aPos[iPos].AdjustStart( nShift );
- m_aPos[iPos].AdjustEnd( nShift );
- }
- }
- void CMarkup::x_LocateNew( int iPosParent, int& iPosRel, int& nOffset, int nLength, int nFlags )
- {
-
-
- bool bInsert = (nFlags&1)?true:false;
- bool bHonorWhitespace = (nFlags&2)?true:false;
- int nStartL;
- if ( nLength )
- {
-
- if ( bInsert )
- nStartL = nOffset;
- else
- nStartL = nOffset + nLength;
- }
- else if ( iPosRel )
- {
-
- if ( bInsert )
- nStartL = m_aPos[iPosRel].nStartL;
- else
- nStartL = m_aPos[iPosRel].nEndR + 1;
- }
- else if ( m_aPos[iPosParent].IsEmptyElement() )
- {
-
- nStartL = m_aPos[iPosParent].nStartR;
- }
- else
- {
- if ( bInsert )
- nStartL = m_aPos[iPosParent].nStartR + 1;
- else
- nStartL = m_aPos[iPosParent].nEndL;
- }
-
- if ( ! bHonorWhitespace && ! m_aPos[iPosParent].IsEmptyElement() )
- {
- TokenPos token( m_csDoc );
- token.nNext = nStartL;
- if ( ! x_FindToken(token) || m_csDoc[token.nL] == _T('<') )
- nStartL = token.nL;
- }
-
- int iPosBefore = 0;
- if ( iPosRel )
- {
- if ( bInsert )
- {
-
- int iPosPrev = m_aPos[iPosParent].iElemChild;
- if ( iPosPrev != iPosRel )
- {
-
- while ( m_aPos[iPosPrev].iElemNext != iPosRel )
- iPosPrev = m_aPos[iPosPrev].iElemNext;
- iPosBefore = iPosPrev;
- }
- }
- else
- {
- iPosBefore = iPosRel;
- }
- }
- else if ( m_aPos[iPosParent].iElemChild )
- {
- if ( ! bInsert )
- {
-
- int iPosLast = m_aPos[iPosParent].iElemChild;
- int iPosNext = iPosLast;
- while ( iPosNext )
- {
- iPosLast = iPosNext;
- iPosNext = m_aPos[iPosNext].iElemNext;
- }
- iPosBefore = iPosLast;
- }
- }
- nOffset = nStartL;
- iPosRel = iPosBefore;
- }
- bool CMarkup::x_AddElem( LPCTSTR szName, LPCTSTR szValue, bool bInsert, bool bAddChild )
- {
- if ( bAddChild )
- {
-
- if ( ! m_iPos )
- return false;
- }
- else if ( m_iPosParent == 0 )
- {
-
- if ( IsWellFormed() )
- return false;
-
- m_aPos[0].nEndL = m_csDoc.GetLength();
- }
-
- int iPosParent, iPosBefore, nOffset = 0, nLength = 0;
- if ( bAddChild )
- {
- iPosParent = m_iPos;
- iPosBefore = m_iPosChild;
- }
- else
- {
- iPosParent = m_iPosParent;
- iPosBefore = m_iPos;
- }
- int nFlags = bInsert?1:0;
- x_LocateNew( iPosParent, iPosBefore, nOffset, nLength, nFlags );
- bool bEmptyParent = m_aPos[iPosParent].IsEmptyElement();
- if ( bEmptyParent )
- nOffset += 2;
-
-
-
-
- int iPos = x_GetFreePos();
- m_aPos[iPos].nStartL = nOffset;
-
- m_aPos[iPos].iElemParent = iPosParent;
- m_aPos[iPos].iElemChild = 0;
- m_aPos[iPos].iElemNext = 0;
- if ( iPosBefore )
- {
-
- m_aPos[iPos].iElemNext = m_aPos[iPosBefore].iElemNext;
- m_aPos[iPosBefore].iElemNext = iPos;
- }
- else
- {
-
- m_aPos[iPos].iElemNext = m_aPos[iPosParent].iElemChild;
- m_aPos[iPosParent].iElemChild = iPos;
- }
-
- CString csInsert;
- int nLenName = _tcslen(szName);
- int nLenValue = szValue? _tcslen(szValue) : 0;
- if ( ! nLenValue )
- {
-
- csInsert = _T("<");
- csInsert += szName;
- csInsert += _T("/>\r\n");
- m_aPos[iPos].nStartR = m_aPos[iPos].nStartL + nLenName + 2;
- m_aPos[iPos].nEndL = m_aPos[iPos].nStartR - 1;
- m_aPos[iPos].nEndR = m_aPos[iPos].nEndL + 1;
- }
- else
- {
-
- CString csValue = x_TextToDoc( szValue );
- nLenValue = csValue.GetLength();
- csInsert = _T("<");
- csInsert += szName;
- csInsert += _T(">");
- csInsert += csValue;
- csInsert += _T("</");
- csInsert += szName;
- csInsert += _T(">\r\n");
- m_aPos[iPos].nStartR = m_aPos[iPos].nStartL + nLenName + 1;
- m_aPos[iPos].nEndL = m_aPos[iPos].nStartR + nLenValue + 1;
- m_aPos[iPos].nEndR = m_aPos[iPos].nEndL + nLenName + 2;
- }
-
- int nReplace = 0, nLeft = m_aPos[iPos].nStartL;
- if ( bEmptyParent )
- {
- CString csParentTagName = x_GetTagName(iPosParent);
- CString csFormat;
- csFormat = _T(">\r\n");
- csFormat += csInsert;
- csFormat += _T("</");
- csFormat += csParentTagName;
- csInsert = csFormat;
- nLeft -= 3;
- nReplace = 1;
-
-
-
-
- m_aPos[iPosParent].nStartR -= 1;
-
-
-
-
- m_aPos[iPosParent].nEndL -= (csParentTagName.GetLength() + 1);
- }
- x_DocChange( nLeft, nReplace, csInsert );
- x_Adjust( iPos, csInsert.GetLength() - nReplace );
- if ( bAddChild )
- x_SetPos( m_iPosParent, iPosParent, iPos );
- else
- x_SetPos( iPosParent, iPos, 0 );
- return true;
- }
- bool CMarkup::x_AddSubDoc( LPCTSTR szSubDoc, bool bInsert, bool bAddChild )
- {
-
-
- int nOffset = 0, iPosParent, iPosBefore;
- if ( bAddChild )
- {
-
- if ( ! m_iPos )
- return false;
- iPosParent = m_iPos;
- iPosBefore = m_iPosChild;
- }
- else
- {
- iPosParent = m_iPosParent;
- iPosBefore = m_iPos;
- }
- int nFlags = bInsert?1:0;
- x_LocateNew( iPosParent, iPosBefore, nOffset, 0, nFlags );
- bool bEmptyParent = m_aPos[iPosParent].IsEmptyElement();
- if ( bEmptyParent )
- nOffset += 2;
-
- int nParentEndLBeforeAdd = m_aPos[iPosParent].nEndL;
- int iPosFreeBeforeAdd = m_iPosFree;
-
- TokenPos token( szSubDoc );
- int nNodeType = x_ParseNode( token );
- while ( nNodeType && nNodeType != MNT_ELEMENT )
- {
- token.szDoc = &szSubDoc[token.nNext];
- token.nNext = 0;
- nNodeType = x_ParseNode( token );
- }
- CString csInsert = token.szDoc;
-
- m_aPos[iPosParent].nEndL = nOffset;
- int nReplace = 0, nLeft = nOffset;
- CString csParentTagName;
- if ( bEmptyParent )
- {
- csParentTagName = x_GetTagName(iPosParent);
- CString csFormat;
- csFormat = _T(">\r\n");
- csFormat += csInsert;
- csFormat += _T("</");
- csFormat += csParentTagName;
- csInsert = csFormat;
- m_aPos[iPosParent].nEndL = m_aPos[iPosParent].nStartR + 2;
- nLeft = m_aPos[iPosParent].nStartR - 1;
- nReplace = 1;
- }
- x_DocChange( nLeft, nReplace, csInsert );
-
- int iPos = x_ParseElem(iPosParent);
- m_aPos[iPosParent].nEndL = nParentEndLBeforeAdd;
- if ( iPos <= 0 )
- {
-
- CString csRevert = bEmptyParent?_T("/"):_T("");
- x_DocChange( nLeft, csInsert.GetLength(), csRevert );
- m_iPosFree = iPosFreeBeforeAdd;
- return false;
- }
- else
- {
-
- m_aPos[iPos].iElemParent = iPosParent;
- if ( iPosBefore )
- {
- m_aPos[iPos].iElemNext = m_aPos[iPosBefore].iElemNext;
- m_aPos[iPosBefore].iElemNext = iPos;
- }
- else
- {
- m_aPos[iPos].iElemNext = m_aPos[iPosParent].iElemChild;
- m_aPos[iPosParent].iElemChild = iPos;
- }
-
- if ( bEmptyParent )
- {
- m_aPos[iPosParent].nStartR -= 1;
- m_aPos[iPosParent].nEndL -= (csParentTagName.GetLength() + 1);
- }
-
- x_Adjust( iPos, csInsert.GetLength() - nReplace, true );
- }
-
- if ( bAddChild )
- x_SetPos( m_iPosParent, iPosParent, iPos );
- else
- x_SetPos( m_iPosParent, iPos, 0 );
- return true;
- }
- int CMarkup::x_RemoveElem( int iPos )
- {
-
-
-
- int iPosParent = m_aPos[iPos].iElemParent;
-
-
- int iPosLook = m_aPos[iPosParent].iElemChild;
- int iPosPrev = 0;
- while ( iPosLook != iPos )
- {
- iPosPrev = iPosLook;
- iPosLook = m_aPos[iPosLook].iElemNext;
- }
- if ( iPosPrev )
- m_aPos[iPosPrev].iElemNext = m_aPos[iPos].iElemNext;
- else
- m_aPos[iPosParent].iElemChild = m_aPos[iPos].iElemNext;
-
-
-
- int nAfterEnd = m_aPos[iPos].nEndR + 1;
- TokenPos token( m_csDoc );
- token.nNext = nAfterEnd;
- if ( ! x_FindToken(token) || token.szDoc[token.nL] == _T('<') )
- nAfterEnd = token.nL;
- int nLen = nAfterEnd - m_aPos[iPos].nStartL;
- x_DocChange( m_aPos[iPos].nStartL, nLen, CString() );
- x_Adjust( iPos, - nLen, true );
- return iPosPrev;
- }
|