merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / edit / textdata.cxx
blobbda67af69a753b14057f6ab038907e400319429e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: textdata.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <svtools/textdata.hxx>
35 #include <textdat2.hxx>
37 #include <tools/debug.hxx>
39 SV_IMPL_PTRARR( TextLines, TextLinePtr );
40 SV_IMPL_VARARR( TEWritingDirectionInfos, TEWritingDirectionInfo );
43 \f// -------------------------------------------------------------------------
44 // (+) class TextSelection
45 // -------------------------------------------------------------------------
47 TextSelection::TextSelection()
51 TextSelection::TextSelection( const TextPaM& rPaM ) :
52 maStartPaM( rPaM ), maEndPaM( rPaM )
56 TextSelection::TextSelection( const TextPaM& rStart, const TextPaM& rEnd ) :
57 maStartPaM( rStart ), maEndPaM( rEnd )
61 void TextSelection::Justify()
63 if ( maEndPaM < maStartPaM )
65 TextPaM aTemp( maStartPaM );
66 maStartPaM = maEndPaM;
67 maEndPaM = aTemp;
72 \f// -------------------------------------------------------------------------
73 // (+) class TETextPortionList
74 // -------------------------------------------------------------------------
75 TETextPortionList::TETextPortionList()
79 TETextPortionList::~TETextPortionList()
81 Reset();
84 void TETextPortionList::Reset()
86 for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ )
87 delete GetObject( nPortion );
88 Remove( 0, Count() );
91 void TETextPortionList::DeleteFromPortion( USHORT nDelFrom )
93 DBG_ASSERT( ( nDelFrom < Count() ) || ( (nDelFrom == 0) && (Count() == 0) ), "DeleteFromPortion: Out of range" );
94 for ( USHORT nP = nDelFrom; nP < Count(); nP++ )
95 delete GetObject( nP );
96 Remove( nDelFrom, Count()-nDelFrom );
99 USHORT TETextPortionList::FindPortion( USHORT nCharPos, USHORT& nPortionStart, BOOL bPreferStartingPortion )
101 // Bei nCharPos an Portion-Grenze wird die linke Portion gefunden
102 USHORT nTmpPos = 0;
103 for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ )
105 TETextPortion* pPortion = GetObject( nPortion );
106 nTmpPos = nTmpPos + pPortion->GetLen();
107 if ( nTmpPos >= nCharPos )
109 // take this one if we don't prefer the starting portion, or if it's the last one
110 if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( nPortion == Count() - 1 ) )
112 nPortionStart = nTmpPos - pPortion->GetLen();
113 return nPortion;
117 DBG_ERROR( "FindPortion: Nicht gefunden!" );
118 return ( Count() - 1 );
122 USHORT TETextPortionList::GetPortionStartIndex( USHORT nPortion )
124 USHORT nPos = 0;
125 for ( USHORT nP = 0; nP < nPortion; nP++ )
127 TETextPortion* pPortion = GetObject( nP );
128 nPos += pPortion->GetLen();
130 return nPos;
135 \f// -------------------------------------------------------------------------
136 // (+) class TEParaPortion
137 // -------------------------------------------------------------------------
138 TEParaPortion::TEParaPortion( TextNode* pN )
140 mpNode = pN;
141 mnInvalidPosStart = mnInvalidDiff = 0;
142 mbInvalid = TRUE;
143 mbSimple = FALSE;
146 TEParaPortion::~TEParaPortion()
150 void TEParaPortion::MarkInvalid( USHORT nStart, short nDiff )
152 if ( mbInvalid == FALSE )
154 mnInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff );
155 mnInvalidDiff = nDiff;
157 else
159 // Einfaches hintereinander tippen
160 if ( ( nDiff > 0 ) && ( mnInvalidDiff > 0 ) &&
161 ( ( mnInvalidPosStart+mnInvalidDiff ) == nStart ) )
163 mnInvalidDiff = mnInvalidDiff + nDiff;
165 // Einfaches hintereinander loeschen
166 else if ( ( nDiff < 0 ) && ( mnInvalidDiff < 0 ) && ( mnInvalidPosStart == nStart ) )
168 mnInvalidPosStart = mnInvalidPosStart + nDiff;
169 mnInvalidDiff = mnInvalidDiff + nDiff;
171 else
173 DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" );
174 mnInvalidPosStart = Min( mnInvalidPosStart, (USHORT) ( (nDiff < 0) ? nStart+nDiff : nDiff ) );
175 mnInvalidDiff = 0;
176 mbSimple = FALSE;
180 maWritingDirectionInfos.Remove( 0, maWritingDirectionInfos.Count() );
182 mbInvalid = TRUE;
185 void TEParaPortion::MarkSelectionInvalid( USHORT nStart, USHORT /*nEnd*/ )
187 if ( mbInvalid == FALSE )
189 mnInvalidPosStart = nStart;
190 // nInvalidPosEnd = nEnd;
192 else
194 mnInvalidPosStart = Min( mnInvalidPosStart, nStart );
195 // nInvalidPosEnd = pNode->Len();
198 maWritingDirectionInfos.Remove( 0, maWritingDirectionInfos.Count() );
200 mnInvalidDiff = 0;
201 mbInvalid = TRUE;
202 mbSimple = FALSE;
205 USHORT TEParaPortion::GetLineNumber( USHORT nChar, BOOL bInclEnd )
207 for ( USHORT nLine = 0; nLine < maLines.Count(); nLine++ )
209 TextLine* pLine = maLines.GetObject( nLine );
210 if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) ||
211 ( pLine->GetEnd() > nChar ) )
213 return nLine;
217 // Dann sollte es am Ende der letzten Zeile sein!
218 DBG_ASSERT( nChar == maLines[ maLines.Count() - 1 ]->GetEnd(), "Index voll daneben!" );
219 DBG_ASSERT( !bInclEnd, "Zeile nicht gefunden: FindLine" );
220 return ( maLines.Count() - 1 );
224 void TEParaPortion::CorrectValuesBehindLastFormattedLine( USHORT nLastFormattedLine )
226 USHORT nLines = maLines.Count();
227 DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Leere Portion?" );
228 if ( nLastFormattedLine < ( nLines - 1 ) )
230 const TextLine* pLastFormatted = maLines[ nLastFormattedLine ];
231 const TextLine* pUnformatted = maLines[ nLastFormattedLine+1 ];
232 short nPortionDiff = pUnformatted->GetStartPortion() - pLastFormatted->GetEndPortion();
233 short nTextDiff = pUnformatted->GetStart() - pLastFormatted->GetEnd();
234 nTextDiff++; // LastFormatted->GetEnd() war incl. => 1 zuviel abgezogen!
236 // Die erste unformatierte muss genau eine Portion hinter der letzten der
237 // formatierten beginnen:
238 // Wenn in der geaenderten Zeile eine Portion gesplittet wurde,
239 // kann nLastEnd > nNextStart sein!
240 short nPDiff = sal::static_int_cast< short >(-( nPortionDiff-1 ));
241 short nTDiff = sal::static_int_cast< short >(-( nTextDiff-1 ));
242 if ( nPDiff || nTDiff )
244 for ( USHORT nL = nLastFormattedLine+1; nL < nLines; nL++ )
246 TextLine* pLine = maLines[ nL ];
248 pLine->GetStartPortion() = pLine->GetStartPortion() + nPDiff;
249 pLine->GetEndPortion() = pLine->GetEndPortion() + nPDiff;
251 pLine->GetStart() = pLine->GetStart() + nTDiff;
252 pLine->GetEnd() = pLine->GetEnd() + nTDiff;
254 pLine->SetValid();
260 \f// -------------------------------------------------------------------------
261 // (+) class TEParaPortions
262 // -------------------------------------------------------------------------
263 TEParaPortions::TEParaPortions()
267 TEParaPortions::~TEParaPortions()
269 Reset();
272 void TEParaPortions::Reset()
274 TEParaPortions::iterator aIter( begin() );
275 while ( aIter != end() )
276 delete *aIter++;
277 clear();
280 \f// -------------------------------------------------------------------------
281 // (+) class IdleFormatter
282 // -------------------------------------------------------------------------
283 IdleFormatter::IdleFormatter()
285 mpView = 0;
286 mnRestarts = 0;
289 IdleFormatter::~IdleFormatter()
291 mpView = 0;
294 void IdleFormatter::DoIdleFormat( TextView* pV, USHORT nMaxRestarts )
296 mpView = pV;
298 if ( IsActive() )
299 mnRestarts++;
301 if ( mnRestarts > nMaxRestarts )
303 mnRestarts = 0;
304 ((Link&)GetTimeoutHdl()).Call( this );
306 else
308 Start();
312 void IdleFormatter::ForceTimeout()
314 if ( IsActive() )
316 Stop();
317 mnRestarts = 0;
318 ((Link&)GetTimeoutHdl()).Call( this );
322 TYPEINIT1( TextHint, SfxSimpleHint );
324 TextHint::TextHint( ULONG Id ) : SfxSimpleHint( Id )
326 mnValue = 0;
329 TextHint::TextHint( ULONG Id, ULONG nValue ) : SfxSimpleHint( Id )
331 mnValue = nValue;
334 TEIMEInfos::TEIMEInfos( const TextPaM& rPos, const String& rOldTextAfterStartPos )
335 : aOldTextAfterStartPos( rOldTextAfterStartPos )
337 aPos = rPos;
338 nLen = 0;
339 bCursor = TRUE;
340 pAttribs = NULL;
341 bWasCursorOverwrite = FALSE;
344 TEIMEInfos::~TEIMEInfos()
346 delete[] pAttribs;
349 void TEIMEInfos::CopyAttribs( const USHORT* pA, USHORT nL )
351 nLen = nL;
352 delete pAttribs;
353 pAttribs = new USHORT[ nL ];
354 memcpy( pAttribs, pA, nL*sizeof(USHORT) );
357 void TEIMEInfos::DestroyAttribs()
359 delete pAttribs;
360 pAttribs = NULL;
361 nLen = 0;