bool CMarkup::x_SetAttrib( int iPos, LPCTSTR szAttrib, LPCTSTR szValue ) { // Set attribute in iPos element TokenPos token( m_csDoc ); int nInsertAt; if ( iPos && m_nNodeType == MNT_ELEMENT ) { token.nNext = m_aPos[iPos].nStartL + 1; nInsertAt = m_aPos[iPos].nStartR - (m_aPos[iPos].IsEmptyElement()?1:0); } else return false; // Create insertion text depending on whether attribute already exists int nReplace = 0; CString csInsert; if ( x_FindAttrib( token, szAttrib ) ) { // Replace value only // Decision: for empty value leaving attrib="" instead of removing attrib csInsert = x_TextToDoc( szValue, true ); nInsertAt = token.nL; nReplace = token.nR-token.nL+1; } else { // Insert string name value pair CString csFormat; csFormat = _T(" "); csFormat += szAttrib; csFormat += _T("=\""); csFormat += x_TextToDoc( szValue, true ); csFormat += _T("\""); csInsert = csFormat; } 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 CMarkupSTL::x_SetAttrib( int iPos, const char * szAttrib, const char * szValue ) { // Set attribute in iPos element if ( ! iPos || m_nNodeType != MNT_ELEMENT ) return false; TokenPos token( m_csDoc ); token.nNext = m_aPos[iPos].nStartL + 1; int nInsertAt, nReplace = 0; CStdString csInsert; if ( x_FindAttrib( token, szAttrib ) ) { // Decision: for empty value leaving attrib="" instead of removing attrib // Replace value only csInsert = x_TextToDoc( szValue, true ); nInsertAt = token.nL; nReplace = token.nR-token.nL+1; } else { // Insert string name value pair CStdString csFormat; csFormat = _T(" "); csFormat += szAttrib; csFormat += _T("=\""); csFormat += x_TextToDoc( szValue, true ); csFormat += _T("\""); csInsert = csFormat; // take into account whether it is an empty element 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 CMarkupSTL::x_SetData( int iPos, const char * szData, int nCDATA ) { // Set data at specified position // if nCDATA==1, set content of element to a CDATA Section CStdString csInsert; // Set data in iPos element if ( ! iPos || m_aPos[iPos].iElemChild ) return false; // Build csInsert from szData based on nCDATA // If CDATA section not valid, use parsed text (PCDATA) instead if ( nCDATA != 0 ) if ( ! x_CreateNode(csInsert, MNT_CDATA_SECTION, szData) ) nCDATA = 0; if ( nCDATA == 0 ) csInsert = x_TextToDoc( szData ); // Decide where to insert int nInsertAt, nReplace; if ( m_aPos[iPos].IsEmptyElement() ) { nInsertAt = m_aPos[iPos].nEndL; nReplace = 1; // Pre-adjust since <NAME/> becomes <NAME>data</NAME> CStdString csTagName = x_GetTagName( iPos ); m_aPos[iPos].nStartR -= 1; m_aPos[iPos].nEndL -= (1 + csTagName.GetLength()); CStdString 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; }
bool CMarkupSTL::x_AddElem( const char * szName, const char * szValue, bool bInsert, bool bAddChild ) { if ( bAddChild ) { // Adding a child element under main position if ( ! m_iPos ) return false; } else if ( m_iPosParent == 0 ) { // Adding root element if ( IsWellFormed() ) return false; // Locate after any version and DTD m_aPos[0].nEndL = m_csDoc.GetLength(); } // Locate where to add element relative to current node 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; // include CRLF // Create element and modify positions of affected elements // If no szValue is specified, an empty element is created // i.e. either <NAME>value</NAME> or <NAME/> // int iPos = x_GetFreePos(); m_aPos[iPos].nStartL = nOffset; // Set links m_aPos[iPos].iElemParent = iPosParent; m_aPos[iPos].iElemChild = 0; m_aPos[iPos].iElemNext = 0; if ( iPosBefore ) { // Link in after iPosBefore m_aPos[iPos].iElemNext = m_aPos[iPosBefore].iElemNext; m_aPos[iPosBefore].iElemNext = iPos; } else { // First child m_aPos[iPos].iElemNext = m_aPos[iPosParent].iElemChild; m_aPos[iPosParent].iElemChild = iPos; } // Create string for insert CStdString csInsert; int nLenName = _tcslen(szName); int nLenValue = szValue? _tcslen(szValue) : 0; if ( ! nLenValue ) { // <NAME/> empty element 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 { // <NAME>value</NAME> CStdString 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; } // Insert int nReplace = 0, nLeft = m_aPos[iPos].nStartL; if ( bEmptyParent ) { CStdString csParentTagName = x_GetTagName(iPosParent); CStdString csFormat; csFormat = _T(">\r\n"); csFormat += csInsert; csFormat += _T("</"); csFormat += csParentTagName; csInsert = csFormat; nLeft -= 3; nReplace = 1; // x_Adjust is going to update all affected indexes by one amount // This will satisfy all except the empty parent // Here we pre-adjust for the empty parent // The empty tag slash is removed m_aPos[iPosParent].nStartR -= 1; // For the newly created end tag, see the following example: // <A/> (len 4) becomes <A><B/></A> (len 11) // In x_Adjust everything will be adjusted 11 - 4 = 7 // But the nEndL of element A should only be adjusted 5 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; }