diff options
Diffstat (limited to 'svtools/source/edit/textdoc.cxx')
-rw-r--r-- | svtools/source/edit/textdoc.cxx | 636 |
1 files changed, 0 insertions, 636 deletions
diff --git a/svtools/source/edit/textdoc.cxx b/svtools/source/edit/textdoc.cxx deleted file mode 100644 index a8062ecefbf3..000000000000 --- a/svtools/source/edit/textdoc.cxx +++ /dev/null @@ -1,636 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include <textdoc.hxx> - -#include <stdlib.h> - - - -// Vergleichmethode wird von QuickSort gerufen... - -static bool CompareStart( const TextCharAttrib* pFirst, const TextCharAttrib* pSecond ) -{ - return pFirst->GetStart() < pSecond->GetStart(); -} - -// ------------------------------------------------------------------------- -// (+) class TextCharAttrib -// ------------------------------------------------------------------------- -TextCharAttrib::TextCharAttrib( const TextAttrib& rAttr, sal_uInt16 nStart, sal_uInt16 nEnd ) -{ - mpAttr = rAttr.Clone(); - mnStart = nStart, - mnEnd = nEnd; -} - -TextCharAttrib::TextCharAttrib( const TextCharAttrib& rTextCharAttrib ) -{ - mpAttr = rTextCharAttrib.GetAttr().Clone(); - mnStart = rTextCharAttrib.mnStart; - mnEnd = rTextCharAttrib.mnEnd; -} - -TextCharAttrib::~TextCharAttrib() -{ - delete mpAttr; -} - -// ------------------------------------------------------------------------- -// (+) class TextCharAttribList -// ------------------------------------------------------------------------- - -TextCharAttribList::TextCharAttribList() -{ - mbHasEmptyAttribs = sal_False; -} - -TextCharAttribList::~TextCharAttribList() -{ - // PTRARR_DEL -} - -void TextCharAttribList::Clear( sal_Bool bDestroyAttribs ) -{ - if ( bDestroyAttribs ) - for(iterator it = begin(); it != end(); ++it) - delete *it; - TextCharAttribs::clear(); -} - - -void TextCharAttribList::InsertAttrib( TextCharAttrib* pAttrib ) -{ - if ( pAttrib->IsEmpty() ) - mbHasEmptyAttribs = sal_True; - - const sal_uInt16 nCount = size(); - const sal_uInt16 nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt. - sal_Bool bInserted = sal_False; - for ( sal_uInt16 x = 0; x < nCount; x++ ) - { - TextCharAttrib* pCurAttrib = GetAttrib( x ); - if ( pCurAttrib->GetStart() > nStart ) - { - insert( begin() + x, pAttrib ); - bInserted = sal_True; - break; - } - } - if ( !bInserted ) - push_back( pAttrib ); -} - -void TextCharAttribList::ResortAttribs() -{ - if ( !empty() ) - std::sort( begin(), end(), CompareStart ); -} - -TextCharAttrib* TextCharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) -{ - // Rueckwaerts, falls eins dort endet, das naechste startet. - // => Das startende gilt... - - for ( sal_uInt16 nAttr = size(); nAttr; ) - { - TextCharAttrib* pAttr = GetAttrib( --nAttr ); - - if ( pAttr->GetEnd() < nPos ) - return 0; - - if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) ) - return pAttr; - } - return NULL; -} - -TextCharAttrib* TextCharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos, sal_uInt16 nMaxPos ) const -{ - DBG_ASSERT( nWhich, "FindNextAttrib: Which?" ); - const sal_uInt16 nAttribs = size(); - for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) - { - TextCharAttrib* pAttr = GetAttrib( nAttr ); - if ( ( pAttr->GetStart() >= nFromPos ) && - ( pAttr->GetEnd() <= nMaxPos ) && - ( pAttr->Which() == nWhich ) ) - return pAttr; - } - return NULL; -} - -sal_Bool TextCharAttribList::HasAttrib( sal_uInt16 nWhich ) const -{ - for ( sal_uInt16 nAttr = size(); nAttr; ) - { - const TextCharAttrib* pAttr = GetAttrib( --nAttr ); - if ( pAttr->Which() == nWhich ) - return sal_True; - } - return sal_False; -} - -sal_Bool TextCharAttribList::HasBoundingAttrib( sal_uInt16 nBound ) -{ - // Rueckwaerts, falls eins dort endet, das naechste startet. - // => Das startende gilt... - for ( sal_uInt16 nAttr = size(); nAttr; ) - { - TextCharAttrib* pAttr = GetAttrib( --nAttr ); - - if ( pAttr->GetEnd() < nBound ) - return sal_False; - - if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) ) - return sal_True; - } - return sal_False; -} - -TextCharAttrib* TextCharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) -{ - if ( !mbHasEmptyAttribs ) - return 0; - - const sal_uInt16 nAttribs = size(); - for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) - { - TextCharAttrib* pAttr = GetAttrib( nAttr ); - if ( pAttr->GetStart() > nPos ) - return 0; - - if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) ) - return pAttr; - } - return 0; -} - -void TextCharAttribList::DeleteEmptyAttribs() -{ - for ( sal_uInt16 nAttr = 0; nAttr < size(); nAttr++ ) - { - TextCharAttrib* pAttr = GetAttrib( nAttr ); - if ( pAttr->IsEmpty() ) - { - erase( begin() + nAttr ); - delete pAttr; - nAttr--; - } - } - mbHasEmptyAttribs = sal_False; -} - -// ------------------------------------------------------------------------- -// (+) class TextNode -// ------------------------------------------------------------------------- - -TextNode::TextNode( const String& rText ) : - maText( rText ) -{ -} - -void TextNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew ) -{ - if ( !nNew ) - return; - - sal_Bool bResort = sal_False; - sal_uInt16 nAttribs = maCharAttribs.Count(); - for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) - { - TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); - if ( pAttrib->GetEnd() >= nIndex ) - { - // Alle Attribute hinter der Einfuegeposition verschieben... - if ( pAttrib->GetStart() > nIndex ) - { - pAttrib->MoveForward( nNew ); - } - // 0: Leeres Attribut expandieren, wenn an Einfuegestelle - else if ( pAttrib->IsEmpty() ) - { - // Index nicht pruefen, leeres durfte nur dort liegen. - // Wenn spaeter doch Ueberpruefung: - // Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch! - // Start <= nIndex, End >= nIndex => Start=End=nIndex! -// if ( pAttrib->GetStart() == nIndex ) - pAttrib->Expand( nNew ); - } - // 1: Attribut startet davor, geht bis Index... - else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen - { - // Nur expandieren, wenn kein Feature, - // und wenn nicht in ExcludeListe! - // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren - if ( !maCharAttribs.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) - { - pAttrib->Expand( nNew ); - } - else - bResort = sal_True; - } - // 2: Attribut startet davor, geht hinter Index... - else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - pAttrib->Expand( nNew ); - } - // 3: Attribut startet auf Index... - else if ( pAttrib->GetStart() == nIndex ) - { - if ( nIndex == 0 ) - { - pAttrib->Expand( nNew ); -// bResort = sal_True; // es gibt ja keine Features mehr... - } - else - pAttrib->MoveForward( nNew ); - } - } - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len() ), "Expand: Attrib groesser als Absatz!" ); - DBG_ASSERT( !pAttrib->IsEmpty(), "Leeres Attribut nach ExpandAttribs?" ); - } - - if ( bResort ) - maCharAttribs.ResortAttribs(); -} - -void TextNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted ) -{ - if ( !nDeleted ) - return; - - sal_Bool bResort = sal_False; - sal_uInt16 nEndChanges = nIndex+nDeleted; - - for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ ) - { - TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); - sal_Bool bDelAttr = sal_False; - if ( pAttrib->GetEnd() >= nIndex ) - { - // Alles Attribute hinter der Einfuegeposition verschieben... - if ( pAttrib->GetStart() >= nEndChanges ) - { - pAttrib->MoveBackward( nDeleted ); - } - // 1. Innenliegende Attribute loeschen... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) - { - // Spezialfall: Attrubt deckt genau den Bereich ab - // => als leeres Attribut behalten. - if ( ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) - pAttrib->GetEnd() = nIndex; // leer - else - bDelAttr = sal_True; - } - // 2. Attribut beginnt davor, endet drinnen oder dahinter... - else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen - pAttrib->GetEnd() = nIndex; - else - pAttrib->Collaps( nDeleted ); // endet dahinter - } - // 3. Attribut beginnt drinnen, endet dahinter... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) - { - // Features duerfen nicht expandieren! - pAttrib->GetStart() = nEndChanges; - pAttrib->MoveBackward( nDeleted ); - } - } - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" ); - if ( bDelAttr /* || pAttrib->IsEmpty() */ ) - { - bResort = sal_True; - maCharAttribs.RemoveAttrib( nAttr ); - delete pAttrib; - nAttr--; - } - else if ( pAttrib->IsEmpty() ) - maCharAttribs.HasEmptyAttribs() = sal_True; - } - - if ( bResort ) - maCharAttribs.ResortAttribs(); -} - -void TextNode::InsertText( sal_uInt16 nPos, const String& rText ) -{ - maText.Insert( rText, nPos ); - ExpandAttribs( nPos, rText.Len() ); -} - -void TextNode::InsertText( sal_uInt16 nPos, sal_Unicode c ) -{ - maText.Insert( c, nPos ); - ExpandAttribs( nPos, 1 ); -} - -void TextNode::RemoveText( sal_uInt16 nPos, sal_uInt16 nChars ) -{ - maText.Erase( nPos, nChars ); - CollapsAttribs( nPos, nChars ); -} - -TextNode* TextNode::Split( sal_uInt16 nPos, sal_Bool bKeepEndingAttribs ) -{ - String aNewText; - if ( nPos < maText.Len() ) - { - aNewText = maText.Copy( nPos ); - maText.Erase( nPos ); - } - TextNode* pNew = new TextNode( aNewText ); - - for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ ) - { - TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); - if ( pAttrib->GetEnd() < nPos ) - { - // bleiben unveraendert.... - ; - } - else if ( pAttrib->GetEnd() == nPos ) - { - // muessen als leeres Attribut kopiert werden. - // !FindAttrib nur sinnvoll, wenn Rueckwaerts durch Liste! - if ( bKeepEndingAttribs && !pNew->maCharAttribs.FindAttrib( pAttrib->Which(), 0 ) ) - { - TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); - pNewAttrib->GetStart() = 0; - pNewAttrib->GetEnd() = 0; - pNew->maCharAttribs.InsertAttrib( pNewAttrib ); - } - } - else if ( pAttrib->IsInside( nPos ) || ( !nPos && !pAttrib->GetStart() ) ) - { - // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben! - // muessen kopiert und geaendert werden - TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); - pNewAttrib->GetStart() = 0; - pNewAttrib->GetEnd() = pAttrib->GetEnd()-nPos; - pNew->maCharAttribs.InsertAttrib( pNewAttrib ); - // stutzen: - pAttrib->GetEnd() = nPos; - } - else - { - DBG_ASSERT( pAttrib->GetStart() >= nPos, "Start < nPos!" ); - DBG_ASSERT( pAttrib->GetEnd() >= nPos, "End < nPos!" ); - // alle dahinter verschieben in den neuen Node (this) - maCharAttribs.RemoveAttrib( nAttr ); - pNew->maCharAttribs.InsertAttrib( pAttrib ); - pAttrib->GetStart() = pAttrib->GetStart() - nPos; - pAttrib->GetEnd() = pAttrib->GetEnd() - nPos; - nAttr--; - } - } - return pNew; -} - -void TextNode::Append( const TextNode& rNode ) -{ - sal_uInt16 nOldLen = maText.Len(); - - maText += rNode.GetText(); - - const sal_uInt16 nAttribs = rNode.GetCharAttribs().Count(); - for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) - { - TextCharAttrib* pAttrib = rNode.GetCharAttribs().GetAttrib( nAttr ); - sal_Bool bMelted = sal_False; - if ( pAttrib->GetStart() == 0 ) - { - // Evtl koennen Attribute zusammengefasst werden: - sal_uInt16 nTmpAttribs = maCharAttribs.Count(); - for ( sal_uInt16 nTmpAttr = 0; nTmpAttr < nTmpAttribs; nTmpAttr++ ) - { - TextCharAttrib* pTmpAttrib = maCharAttribs.GetAttrib( nTmpAttr ); - - if ( pTmpAttrib->GetEnd() == nOldLen ) - { - if ( ( pTmpAttrib->Which() == pAttrib->Which() ) && - ( pTmpAttrib->GetAttr() == pAttrib->GetAttr() ) ) - { - pTmpAttrib->GetEnd() = - pTmpAttrib->GetEnd() + pAttrib->GetLen(); - bMelted = sal_True; - break; // es kann nur eins von der Sorte an der Stelle geben - } - } - } - } - - if ( !bMelted ) - { - TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); - pNewAttrib->GetStart() = pNewAttrib->GetStart() + nOldLen; - pNewAttrib->GetEnd() = pNewAttrib->GetEnd() + nOldLen; - maCharAttribs.InsertAttrib( pNewAttrib ); - } - } -} - -// ------------------------------------------------------------------------- -// (+) class TextDoc -// ------------------------------------------------------------------------- - -TextDoc::TextDoc() -{ - mnLeftMargin = 0; -}; - -TextDoc::~TextDoc() -{ - DestroyTextNodes(); -} - -void TextDoc::Clear() -{ - DestroyTextNodes(); -} - -void TextDoc::DestroyTextNodes() -{ - for ( sal_uLong nNode = 0; nNode < maTextNodes.Count(); nNode++ ) - delete maTextNodes.GetObject( nNode ); - maTextNodes.clear(); -} - -String TextDoc::GetText( const sal_Unicode* pSep ) const -{ - sal_uLong nLen = GetTextLen( pSep ); - sal_uLong nNodes = maTextNodes.Count(); - - if ( nLen > STRING_MAXLEN ) - { - OSL_FAIL( "Text zu gross fuer String" ); - return String(); - } - - String aASCIIText; - sal_uLong nLastNode = nNodes-1; - for ( sal_uLong nNode = 0; nNode < nNodes; nNode++ ) - { - TextNode* pNode = maTextNodes.GetObject( nNode ); - String aTmp( pNode->GetText() ); - aASCIIText += aTmp; - if ( pSep && ( nNode != nLastNode ) ) - aASCIIText += pSep; - } - - return aASCIIText; -} - -XubString TextDoc::GetText( sal_uLong nPara ) const -{ - XubString aText; - TextNode* pNode = ( nPara < maTextNodes.Count() ) ? maTextNodes.GetObject( nPara ) : 0; - if ( pNode ) - aText = pNode->GetText(); - - return aText; -} - - -sal_uLong TextDoc::GetTextLen( const xub_Unicode* pSep, const TextSelection* pSel ) const -{ - sal_uLong nLen = 0; - sal_uLong nNodes = maTextNodes.Count(); - if ( nNodes ) - { - sal_uLong nStartNode = 0; - sal_uLong nEndNode = nNodes-1; - if ( pSel ) - { - nStartNode = pSel->GetStart().GetPara(); - nEndNode = pSel->GetEnd().GetPara(); - } - - for ( sal_uLong nNode = nStartNode; nNode <= nEndNode; nNode++ ) - { - TextNode* pNode = maTextNodes.GetObject( nNode ); - - sal_uInt16 nS = 0; - sal_uLong nE = pNode->GetText().Len(); - if ( pSel && ( nNode == pSel->GetStart().GetPara() ) ) - nS = pSel->GetStart().GetIndex(); - if ( pSel && ( nNode == pSel->GetEnd().GetPara() ) ) - nE = pSel->GetEnd().GetIndex(); - - nLen += ( nE - nS ); - } - - if ( pSep ) - nLen += (nEndNode-nStartNode) * rtl_ustr_getLength(pSep); - } - - return nLen; -} - -TextPaM TextDoc::InsertText( const TextPaM& rPaM, xub_Unicode c ) -{ - DBG_ASSERT( c != 0x0A, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); - DBG_ASSERT( c != 0x0D, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); - - TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); - pNode->InsertText( rPaM.GetIndex(), c ); - - TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+1 ); - return aPaM; -} - -TextPaM TextDoc::InsertText( const TextPaM& rPaM, const XubString& rStr ) -{ - DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); - DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); - - TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); - pNode->InsertText( rPaM.GetIndex(), rStr ); - - TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+rStr.Len() ); - return aPaM; -} - -TextPaM TextDoc::InsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs ) -{ - TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); - TextNode* pNew = pNode->Split( rPaM.GetIndex(), bKeepEndingAttribs ); - - maTextNodes.Insert( pNew, rPaM.GetPara()+1 ); - - TextPaM aPaM( rPaM.GetPara()+1, 0 ); - return aPaM; -} - -TextPaM TextDoc::ConnectParagraphs( TextNode* pLeft, TextNode* pRight ) -{ - sal_uInt16 nPrevLen = pLeft->GetText().Len(); - pLeft->Append( *pRight ); - - // der rechte verschwindet. - sal_uLong nRight = maTextNodes.GetPos( pRight ); - maTextNodes.Remove( nRight ); - delete pRight; - - sal_uLong nLeft = maTextNodes.GetPos( pLeft ); - TextPaM aPaM( nLeft, nPrevLen ); - return aPaM; -} - -TextPaM TextDoc::RemoveChars( const TextPaM& rPaM, sal_uInt16 nChars ) -{ - TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); - pNode->RemoveText( rPaM.GetIndex(), nChars ); - - return rPaM; -} - -sal_Bool TextDoc::IsValidPaM( const TextPaM& rPaM ) -{ - if ( rPaM.GetPara() >= maTextNodes.Count() ) - { - OSL_FAIL( "PaM: Para out of range" ); - return sal_False; - } - TextNode * pNode = maTextNodes.GetObject( rPaM.GetPara() ); - if ( rPaM.GetIndex() > pNode->GetText().Len() ) - { - OSL_FAIL( "PaM: Index out of range" ); - return sal_False; - } - return sal_True; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |