1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: textdata.cxx,v $
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
;
72 \f// -------------------------------------------------------------------------
73 // (+) class TETextPortionList
74 // -------------------------------------------------------------------------
75 TETextPortionList::TETextPortionList()
79 TETextPortionList::~TETextPortionList()
84 void TETextPortionList::Reset()
86 for ( USHORT nPortion
= 0; nPortion
< Count(); nPortion
++ )
87 delete GetObject( nPortion
);
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
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();
117 DBG_ERROR( "FindPortion: Nicht gefunden!" );
118 return ( Count() - 1 );
122 USHORT TETextPortionList::GetPortionStartIndex( USHORT nPortion )
125 for ( USHORT nP = 0; nP < nPortion; nP++ )
127 TETextPortion* pPortion = GetObject( nP );
128 nPos += pPortion->GetLen();
135 \f// -------------------------------------------------------------------------
136 // (+) class TEParaPortion
137 // -------------------------------------------------------------------------
138 TEParaPortion::TEParaPortion( TextNode
* pN
)
141 mnInvalidPosStart
= mnInvalidDiff
= 0;
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
;
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
;
173 DBG_ASSERT( ( nDiff
>= 0 ) || ( (nStart
+nDiff
) >= 0 ), "MarkInvalid: Diff out of Range" );
174 mnInvalidPosStart
= Min( mnInvalidPosStart
, (USHORT
) ( (nDiff
< 0) ? nStart
+nDiff
: nDiff
) );
180 maWritingDirectionInfos
.Remove( 0, maWritingDirectionInfos
.Count() );
185 void TEParaPortion::MarkSelectionInvalid( USHORT nStart
, USHORT
/*nEnd*/ )
187 if ( mbInvalid
== FALSE
)
189 mnInvalidPosStart
= nStart
;
190 // nInvalidPosEnd = nEnd;
194 mnInvalidPosStart
= Min( mnInvalidPosStart
, nStart
);
195 // nInvalidPosEnd = pNode->Len();
198 maWritingDirectionInfos
.Remove( 0, maWritingDirectionInfos
.Count() );
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
) )
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
;
260 \f// -------------------------------------------------------------------------
261 // (+) class TEParaPortions
262 // -------------------------------------------------------------------------
263 TEParaPortions::TEParaPortions()
267 TEParaPortions::~TEParaPortions()
272 void TEParaPortions::Reset()
274 TEParaPortions::iterator
aIter( begin() );
275 while ( aIter
!= end() )
280 \f// -------------------------------------------------------------------------
281 // (+) class IdleFormatter
282 // -------------------------------------------------------------------------
283 IdleFormatter::IdleFormatter()
289 IdleFormatter::~IdleFormatter()
294 void IdleFormatter::DoIdleFormat( TextView
* pV
, USHORT nMaxRestarts
)
301 if ( mnRestarts
> nMaxRestarts
)
304 ((Link
&)GetTimeoutHdl()).Call( this );
312 void IdleFormatter::ForceTimeout()
318 ((Link
&)GetTimeoutHdl()).Call( this );
322 TYPEINIT1( TextHint
, SfxSimpleHint
);
324 TextHint::TextHint( ULONG Id
) : SfxSimpleHint( Id
)
329 TextHint::TextHint( ULONG Id
, ULONG nValue
) : SfxSimpleHint( Id
)
334 TEIMEInfos::TEIMEInfos( const TextPaM
& rPos
, const String
& rOldTextAfterStartPos
)
335 : aOldTextAfterStartPos( rOldTextAfterStartPos
)
341 bWasCursorOverwrite
= FALSE
;
344 TEIMEInfos::~TEIMEInfos()
349 void TEIMEInfos::CopyAttribs( const USHORT
* pA
, USHORT nL
)
353 pAttribs
= new USHORT
[ nL
];
354 memcpy( pAttribs
, pA
, nL
*sizeof(USHORT
) );
357 void TEIMEInfos::DestroyAttribs()