Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "textundo.hxx"
21 : #include "textund2.hxx"
22 : #include "textundo.hrc"
23 :
24 : #include <vcl/texteng.hxx>
25 : #include <vcl/textview.hxx>
26 : #include <vcl/textdata.hxx>
27 : #include <textdoc.hxx>
28 : #include <textdat2.hxx>
29 : #include <svdata.hxx> // ImplGetResMgr()
30 : #include <tools/resid.hxx>
31 :
32 0 : TYPEINIT1( TextUndo, SfxUndoAction );
33 0 : TYPEINIT1( TextUndoDelPara, TextUndo );
34 0 : TYPEINIT1( TextUndoConnectParas, TextUndo );
35 0 : TYPEINIT1( TextUndoSplitPara, TextUndo );
36 0 : TYPEINIT1( TextUndoInsertChars, TextUndo );
37 0 : TYPEINIT1( TextUndoRemoveChars, TextUndo );
38 :
39 :
40 : namespace
41 : {
42 :
43 : // Shorten() -- inserts ellipsis (...) in the middle of a long text
44 0 : void Shorten (rtl::OUString& rString)
45 : {
46 0 : unsigned nLen = rString.getLength();
47 0 : if (nLen > 48)
48 : {
49 : // If possible, we don't break a word, hence first we look for a space.
50 : // Space before the ellipsis:
51 0 : int iFirst = rString.lastIndexOf(' ', 32);
52 0 : if (iFirst == -1 || unsigned(iFirst) < 16)
53 0 : iFirst = 24; // not possible
54 : // Space after the ellipsis:
55 0 : int iLast = rString.indexOf(' ', nLen - 16);
56 0 : if (iLast == -1 || unsigned(iLast) > nLen - 4)
57 0 : iLast = nLen - 8; // not possible
58 : // finally:
59 : rString =
60 : rString.copy(0, iFirst + 1) +
61 0 : "..." +
62 0 : rString.copy(iLast);
63 : }
64 0 : }
65 :
66 : } // namespace
67 :
68 : //
69 : // TextUndoManager
70 : // ===============
71 : //
72 :
73 0 : TextUndoManager::TextUndoManager( TextEngine* p )
74 : {
75 0 : mpTextEngine = p;
76 0 : }
77 :
78 0 : TextUndoManager::~TextUndoManager()
79 : {
80 0 : }
81 :
82 0 : sal_Bool TextUndoManager::Undo()
83 : {
84 0 : if ( GetUndoActionCount() == 0 )
85 0 : return sal_False;
86 :
87 0 : UndoRedoStart();
88 :
89 0 : mpTextEngine->SetIsInUndo( sal_True );
90 0 : sal_Bool bDone = SfxUndoManager::Undo();
91 0 : mpTextEngine->SetIsInUndo( sal_False );
92 :
93 0 : UndoRedoEnd();
94 :
95 0 : return bDone;
96 : }
97 :
98 0 : sal_Bool TextUndoManager::Redo()
99 : {
100 0 : if ( GetRedoActionCount() == 0 )
101 0 : return sal_False;
102 :
103 :
104 0 : UndoRedoStart();
105 :
106 0 : mpTextEngine->SetIsInUndo( sal_True );
107 0 : sal_Bool bDone = SfxUndoManager::Redo();
108 0 : mpTextEngine->SetIsInUndo( sal_False );
109 :
110 0 : UndoRedoEnd();
111 :
112 0 : return bDone;
113 : }
114 :
115 0 : void TextUndoManager::UndoRedoStart()
116 : {
117 : DBG_ASSERT( GetView(), "Undo/Redo: Active View?" );
118 :
119 : // if ( GetView() )
120 : // GetView()->HideSelection();
121 0 : }
122 :
123 0 : void TextUndoManager::UndoRedoEnd()
124 : {
125 0 : if ( GetView() )
126 : {
127 0 : TextSelection aNewSel( GetView()->GetSelection() );
128 0 : aNewSel.GetStart() = aNewSel.GetEnd();
129 0 : GetView()->ImpSetSelection( aNewSel );
130 : }
131 :
132 0 : mpTextEngine->UpdateSelections();
133 :
134 0 : mpTextEngine->FormatAndUpdate( GetView() );
135 0 : }
136 :
137 :
138 : //
139 : // TextUndo
140 : // ========
141 : //
142 :
143 0 : TextUndo::TextUndo( TextEngine* p )
144 : {
145 0 : mpTextEngine = p;
146 0 : }
147 :
148 0 : TextUndo::~TextUndo()
149 : {
150 0 : }
151 :
152 0 : rtl::OUString TextUndo::GetComment() const
153 : {
154 0 : return rtl::OUString();
155 : }
156 :
157 0 : void TextUndo::SetSelection( const TextSelection& rSel )
158 : {
159 0 : if ( GetView() )
160 0 : GetView()->ImpSetSelection( rSel );
161 0 : }
162 :
163 :
164 : //
165 : // TextUndoDelPara
166 : // ===============
167 : //
168 :
169 0 : TextUndoDelPara::TextUndoDelPara( TextEngine* pTextEngine, TextNode* pNode, sal_uLong nPara )
170 0 : : TextUndo( pTextEngine )
171 : {
172 0 : mpNode = pNode;
173 0 : mnPara = nPara;
174 0 : mbDelObject = sal_True;
175 0 : }
176 :
177 0 : TextUndoDelPara::~TextUndoDelPara()
178 : {
179 0 : if ( mbDelObject )
180 0 : delete mpNode;
181 0 : }
182 :
183 0 : void TextUndoDelPara::Undo()
184 : {
185 0 : GetTextEngine()->InsertContent( mpNode, mnPara );
186 0 : mbDelObject = sal_False; // gehoert wieder der Engine
187 :
188 0 : if ( GetView() )
189 : {
190 0 : TextSelection aSel( TextPaM( mnPara, 0 ), TextPaM( mnPara, mpNode->GetText().Len() ) );
191 0 : SetSelection( aSel );
192 : }
193 0 : }
194 :
195 0 : void TextUndoDelPara::Redo()
196 : {
197 : // pNode stimmt nicht mehr, falls zwischendurch Undos, in denen
198 : // Absaetze verschmolzen sind.
199 0 : mpNode = GetDoc()->GetNodes().GetObject( mnPara );
200 :
201 0 : delete GetTEParaPortions()->GetObject( mnPara );
202 0 : GetTEParaPortions()->Remove( mnPara );
203 :
204 : // Node nicht loeschen, haengt im Undo!
205 0 : GetDoc()->GetNodes().Remove( mnPara );
206 0 : GetTextEngine()->ImpParagraphRemoved( mnPara );
207 :
208 0 : mbDelObject = sal_True; // gehoert wieder dem Undo
209 :
210 0 : sal_uLong nParas = GetDoc()->GetNodes().Count();
211 0 : sal_uLong n = mnPara < nParas ? mnPara : (nParas-1);
212 0 : TextNode* pN = GetDoc()->GetNodes().GetObject( n );
213 0 : TextPaM aPaM( n, pN->GetText().Len() );
214 0 : SetSelection( aPaM );
215 0 : }
216 :
217 0 : rtl::OUString TextUndoDelPara::GetComment () const
218 : {
219 0 : return ResId(STR_TEXTUNDO_DELPARA, *ImplGetResMgr());
220 : }
221 :
222 :
223 : //
224 : // TextUndoConnectParas
225 : // ====================
226 : //
227 :
228 0 : TextUndoConnectParas::TextUndoConnectParas( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nPos )
229 0 : : TextUndo( pTextEngine )
230 : {
231 0 : mnPara = nPara;
232 0 : mnSepPos = nPos;
233 0 : }
234 :
235 0 : TextUndoConnectParas::~TextUndoConnectParas()
236 : {
237 0 : }
238 :
239 0 : void TextUndoConnectParas::Undo()
240 : {
241 0 : TextPaM aPaM = GetTextEngine()->SplitContent( mnPara, mnSepPos );
242 0 : SetSelection( aPaM );
243 0 : }
244 :
245 0 : void TextUndoConnectParas::Redo()
246 : {
247 0 : TextPaM aPaM = GetTextEngine()->ConnectContents( mnPara );
248 0 : SetSelection( aPaM );
249 0 : }
250 :
251 0 : rtl::OUString TextUndoConnectParas::GetComment () const
252 : {
253 0 : return ResId(STR_TEXTUNDO_CONNECTPARAS, *ImplGetResMgr());
254 : }
255 :
256 :
257 : //
258 : // TextUndoSplitPara
259 : // =================
260 : //
261 :
262 0 : TextUndoSplitPara::TextUndoSplitPara( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nPos )
263 0 : : TextUndo( pTextEngine )
264 : {
265 0 : mnPara = nPara;
266 0 : mnSepPos = nPos;
267 0 : }
268 :
269 0 : TextUndoSplitPara::~TextUndoSplitPara()
270 : {
271 0 : }
272 :
273 0 : void TextUndoSplitPara::Undo()
274 : {
275 0 : TextPaM aPaM = GetTextEngine()->ConnectContents( mnPara );
276 0 : SetSelection( aPaM );
277 0 : }
278 :
279 0 : void TextUndoSplitPara::Redo()
280 : {
281 0 : TextPaM aPaM = GetTextEngine()->SplitContent( mnPara, mnSepPos );
282 0 : SetSelection( aPaM );
283 0 : }
284 :
285 0 : rtl::OUString TextUndoSplitPara::GetComment () const
286 : {
287 0 : return ResId(STR_TEXTUNDO_SPLITPARA, *ImplGetResMgr());
288 : }
289 :
290 :
291 : //
292 : // TextUndoInsertChars
293 : // ===================
294 : //
295 :
296 0 : TextUndoInsertChars::TextUndoInsertChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr )
297 : : TextUndo( pTextEngine ),
298 0 : maTextPaM( rTextPaM ), maText( rStr )
299 : {
300 0 : }
301 :
302 0 : void TextUndoInsertChars::Undo()
303 : {
304 0 : TextSelection aSel( maTextPaM, maTextPaM );
305 0 : aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len();
306 0 : TextPaM aPaM = GetTextEngine()->ImpDeleteText( aSel );
307 0 : SetSelection( aPaM );
308 0 : }
309 :
310 0 : void TextUndoInsertChars::Redo()
311 : {
312 0 : TextSelection aSel( maTextPaM, maTextPaM );
313 0 : GetTextEngine()->ImpInsertText( aSel, maText );
314 0 : TextPaM aNewPaM( maTextPaM );
315 0 : aNewPaM.GetIndex() = aNewPaM.GetIndex() + maText.Len();
316 0 : SetSelection( TextSelection( aSel.GetStart(), aNewPaM ) );
317 0 : }
318 :
319 0 : sal_Bool TextUndoInsertChars::Merge( SfxUndoAction* pNextAction )
320 : {
321 0 : if ( !pNextAction->ISA( TextUndoInsertChars ) )
322 0 : return sal_False;
323 :
324 0 : TextUndoInsertChars* pNext = (TextUndoInsertChars*)pNextAction;
325 :
326 0 : if ( maTextPaM.GetPara() != pNext->maTextPaM.GetPara() )
327 0 : return sal_False;
328 :
329 0 : if ( ( maTextPaM.GetIndex() + maText.Len() ) == pNext->maTextPaM.GetIndex() )
330 : {
331 0 : maText += pNext->maText;
332 0 : return sal_True;
333 : }
334 0 : return sal_False;
335 : }
336 :
337 0 : rtl::OUString TextUndoInsertChars::GetComment () const
338 : {
339 : // multiple lines?
340 0 : rtl::OUString sText(maText);
341 0 : Shorten(sText);
342 0 : return rtl::OUString(ResId(STR_TEXTUNDO_INSERTCHARS, *ImplGetResMgr())).replaceAll("$1", sText);
343 : }
344 :
345 :
346 :
347 : //
348 : // TextUndoRemoveChars
349 : // ===================
350 : //
351 :
352 0 : TextUndoRemoveChars::TextUndoRemoveChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr )
353 : : TextUndo( pTextEngine ),
354 0 : maTextPaM( rTextPaM ), maText( rStr )
355 : {
356 0 : }
357 :
358 0 : void TextUndoRemoveChars::Undo()
359 : {
360 0 : TextSelection aSel( maTextPaM, maTextPaM );
361 0 : GetTextEngine()->ImpInsertText( aSel, maText );
362 0 : aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len();
363 0 : SetSelection( aSel );
364 0 : }
365 :
366 0 : void TextUndoRemoveChars::Redo()
367 : {
368 0 : TextSelection aSel( maTextPaM, maTextPaM );
369 0 : aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len();
370 0 : TextPaM aPaM = GetTextEngine()->ImpDeleteText( aSel );
371 0 : SetSelection( aPaM );
372 0 : }
373 :
374 0 : rtl::OUString TextUndoRemoveChars::GetComment () const
375 : {
376 : // multiple lines?
377 0 : rtl::OUString sText(maText);
378 0 : Shorten(sText);
379 0 : return rtl::OUString(ResId(STR_TEXTUNDO_REMOVECHARS, *ImplGetResMgr())).replaceAll("$1", sText);
380 : }
381 :
382 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|