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 :
21 : #include <vcl/wrkwin.hxx>
22 : #include <vcl/dialog.hxx>
23 : #include <vcl/msgbox.hxx>
24 : #include <vcl/svapp.hxx>
25 :
26 : #include <impedit.hxx>
27 : #include <editeng/editview.hxx>
28 : #include <editeng/editeng.hxx>
29 : #include <edtspell.hxx>
30 : #include <editeng/flditem.hxx>
31 : #include <editeng/fontitem.hxx>
32 : #include <svl/intitem.hxx>
33 : #include <svl/eitem.hxx>
34 : #include <editeng/unolingu.hxx>
35 : #include <linguistic/lngprops.hxx>
36 : #include <com/sun/star/beans/XPropertySet.hpp>
37 :
38 : using namespace com::sun::star::uno;
39 : using namespace com::sun::star::beans;
40 : using namespace com::sun::star::linguistic2;
41 :
42 :
43 9 : EditSpellWrapper::EditSpellWrapper( Window* _pWin,
44 : Reference< XSpellChecker1 > &xChecker,
45 : sal_Bool bIsStart, sal_Bool bIsAllRight, EditView* pView ) :
46 9 : SvxSpellWrapper( _pWin, xChecker, bIsStart, bIsAllRight )
47 : {
48 : SAL_WARN_IF( !pView, "editeng", "One view has to be abandoned!" );
49 : // Keep IgnoreList, delete ReplaceList...
50 9 : if (SvxGetChangeAllList().is())
51 9 : SvxGetChangeAllList()->clear();
52 9 : pEditView = pView;
53 9 : }
54 :
55 9 : void EditSpellWrapper::SpellStart( SvxSpellArea eArea )
56 : {
57 9 : EditEngine* pEE = pEditView->GetEditEngine();
58 9 : ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
59 9 : SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
60 :
61 9 : if ( eArea == SVX_SPELL_BODY_START )
62 : {
63 : // Is called when
64 : // a) Spell-Forward has arrived at the end and should restart at the top
65 : // IsEndDone() returns also sal_True, when backward-spelling is started at the end!
66 0 : if ( IsEndDone() )
67 : {
68 0 : pSpellInfo->bSpellToEnd = sal_False;
69 0 : pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
70 : pEditView->GetImpEditView()->SetEditSelection(
71 0 : pEE->GetEditDoc().GetStartPaM() );
72 : }
73 : else
74 : {
75 0 : pSpellInfo->bSpellToEnd = sal_True;
76 0 : pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
77 0 : pEE->GetEditDoc().GetStartPaM() );
78 : }
79 : }
80 9 : else if ( eArea == SVX_SPELL_BODY_END )
81 : {
82 : // Is called when
83 : // a) Spell-Forward is launched
84 : // IsStartDone() return also sal_True, when forward-spelling is started at the beginning!
85 9 : if ( !IsStartDone() )
86 : {
87 0 : pSpellInfo->bSpellToEnd = sal_True;
88 0 : pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
89 0 : pEE->GetEditDoc().GetEndPaM() );
90 : }
91 : else
92 : {
93 9 : pSpellInfo->bSpellToEnd = sal_False;
94 9 : pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
95 : pEditView->GetImpEditView()->SetEditSelection(
96 9 : pEE->GetEditDoc().GetEndPaM() );
97 : }
98 : }
99 : else if ( eArea == SVX_SPELL_BODY )
100 : {
101 : ; // Is handled by the App through SpellNextDocument
102 : }
103 : else
104 : {
105 : OSL_FAIL( "SpellStart: Unknown Area!" );
106 : }
107 9 : }
108 :
109 9 : sal_Bool EditSpellWrapper::SpellContinue()
110 : {
111 9 : SetLast( pEditView->GetImpEditEngine()->ImpSpell( pEditView ) );
112 9 : return GetLast().is();
113 : }
114 :
115 9 : void EditSpellWrapper::SpellEnd()
116 : {
117 : // Base class will show language errors...
118 9 : SvxSpellWrapper::SpellEnd();
119 9 : }
120 :
121 9 : sal_Bool EditSpellWrapper::HasOtherCnt()
122 : {
123 9 : return sal_False;
124 : }
125 :
126 9 : sal_Bool EditSpellWrapper::SpellMore()
127 : {
128 9 : EditEngine* pEE = pEditView->GetEditEngine();
129 9 : ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
130 9 : SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
131 9 : sal_Bool bMore = sal_False;
132 9 : if ( pSpellInfo->bMultipleDoc )
133 : {
134 0 : bMore = pEE->SpellNextDocument();
135 0 : if ( bMore )
136 : {
137 : // The text has been entered into the engine, when backwords then
138 : // it must be behind the selection.
139 : pEditView->GetImpEditView()->SetEditSelection(
140 0 : pEE->GetEditDoc().GetStartPaM() );
141 : }
142 : }
143 9 : return bMore;
144 : }
145 :
146 0 : void EditSpellWrapper::ScrollArea()
147 : {
148 : // No further action needed ...
149 : // Except for, that the area is to be scrolled in the center, and not stand
150 : // still anywhere.
151 0 : }
152 :
153 0 : void EditSpellWrapper::ReplaceAll( const String &rNewText,
154 : sal_Int16 )
155 : {
156 : // Is called when the word is in ReplaceList of the spell checker
157 0 : pEditView->InsertText( rNewText );
158 0 : CheckSpellTo();
159 0 : }
160 :
161 0 : void EditSpellWrapper::ChangeWord( const String& rNewWord,
162 : const sal_uInt16 )
163 : {
164 : // Will be called when Word Button Change
165 : // or internally by me ChangeAll
166 :
167 : // If there is a dot Punkt after the word, this dot will be stripped away.
168 : // If '"' => PreStripped.
169 0 : String aNewWord( rNewWord );
170 0 : pEditView->InsertText( aNewWord );
171 0 : CheckSpellTo();
172 0 : }
173 :
174 0 : void EditSpellWrapper::ChangeThesWord( const String& rNewWord )
175 : {
176 0 : pEditView->InsertText( rNewWord );
177 0 : CheckSpellTo();
178 0 : }
179 :
180 0 : void EditSpellWrapper::AutoCorrect( const String&, const String& )
181 : {
182 0 : }
183 :
184 0 : void EditSpellWrapper::CheckSpellTo()
185 : {
186 0 : ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
187 0 : SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
188 0 : EditPaM aPaM( pEditView->GetImpEditView()->GetEditSelection().Max() );
189 0 : EPaM aEPaM = pImpEE->CreateEPaM( aPaM );
190 0 : if ( aEPaM.nPara == pSpellInfo->aSpellTo.nPara )
191 : {
192 : // Check if SpellToEnd still has a valid Index, if replace has been
193 : // performed in the paragraph.
194 0 : if ( pSpellInfo->aSpellTo.nIndex > aPaM.GetNode()->Len() )
195 0 : pSpellInfo->aSpellTo.nIndex = aPaM.GetNode()->Len();
196 : }
197 0 : }
198 :
199 : //////////////////////////////////////////////////////////////////////
200 :
201 : #define NOT_INVALID 0xFFFF
202 :
203 302141 : WrongList::WrongList() : nInvalidStart(0), nInvalidEnd(0xFFFF) {}
204 :
205 120707 : WrongList::WrongList(const WrongList& r) :
206 : maRanges(r.maRanges),
207 : nInvalidStart(r.nInvalidStart),
208 120707 : nInvalidEnd(r.nInvalidEnd) {}
209 :
210 422802 : WrongList::~WrongList() {}
211 :
212 93195 : bool WrongList::IsInvalid() const
213 : {
214 93195 : return nInvalidStart != NOT_INVALID;
215 : }
216 :
217 3167 : void WrongList::SetValid()
218 : {
219 3167 : nInvalidStart = NOT_INVALID;
220 3167 : nInvalidEnd = 0;
221 3167 : }
222 :
223 2041 : void WrongList::MarkInvalid( sal_uInt16 nS, sal_uInt16 nE )
224 : {
225 2041 : if ( ( nInvalidStart == NOT_INVALID ) || ( nInvalidStart > nS ) )
226 411 : nInvalidStart = nS;
227 2041 : if ( nInvalidEnd < nE )
228 953 : nInvalidEnd = nE;
229 2041 : }
230 :
231 90255 : void WrongList::TextInserted( sal_uInt16 nPos, sal_uInt16 nNew, sal_Bool bPosIsSep )
232 : {
233 90255 : if ( !IsInvalid() )
234 : {
235 0 : nInvalidStart = nPos;
236 0 : nInvalidEnd = nPos+nNew;
237 : }
238 : else
239 : {
240 90255 : if ( nInvalidStart > nPos )
241 0 : nInvalidStart = nPos;
242 90255 : if ( nInvalidEnd >= nPos )
243 90255 : nInvalidEnd = nInvalidEnd + nNew;
244 : else
245 0 : nInvalidEnd = nPos+nNew;
246 : }
247 :
248 90255 : for (size_t i = 0, n = maRanges.size(); i < n; ++i)
249 : {
250 0 : WrongRange& rWrong = maRanges[i];
251 0 : bool bRefIsValid = true;
252 0 : if (rWrong.nEnd >= nPos)
253 : {
254 : // Move all Wrongs after the insert position...
255 0 : if (rWrong.nStart > nPos)
256 : {
257 0 : rWrong.nStart += nNew;
258 0 : rWrong.nEnd += nNew;
259 : }
260 : // 1: Starts before and goes until nPos...
261 0 : else if (rWrong.nEnd == nPos)
262 : {
263 : // Should be halted at a blank!
264 0 : if ( !bPosIsSep )
265 0 : rWrong.nEnd += nNew;
266 : }
267 : // 2: Starts before and goes until after nPos...
268 0 : else if ((rWrong.nStart < nPos) && (rWrong.nEnd > nPos))
269 : {
270 0 : rWrong.nEnd += nNew;
271 : // When a separator remove and re-examine the Wrong
272 0 : if ( bPosIsSep )
273 : {
274 : // Split Wrong...
275 0 : WrongRange aNewWrong(rWrong.nStart, nPos);
276 0 : rWrong.nStart = nPos + 1;
277 0 : maRanges.insert(maRanges.begin() + i, aNewWrong);
278 : // Reference no longer valid after Insert, the other
279 : // was inserted in front of this position
280 0 : bRefIsValid = false;
281 0 : ++i; // Not this again...
282 0 : }
283 : }
284 : // 3: Attribute starts at position ..
285 0 : else if (rWrong.nStart == nPos)
286 : {
287 0 : rWrong.nEnd += nNew;
288 0 : if ( bPosIsSep )
289 0 : ++(rWrong.nStart);
290 : }
291 : }
292 : SAL_WARN_IF(bRefIsValid && rWrong.nStart >= rWrong.nEnd, "editeng",
293 : "TextInserted, WrongRange: Start >= End?!");
294 : (void)bRefIsValid;
295 : }
296 :
297 : SAL_WARN_IF(DbgIsBuggy(), "editeng", "InsertWrong: WrongList broken!");
298 90255 : }
299 :
300 47 : void WrongList::TextDeleted( sal_uInt16 nPos, sal_uInt16 nDeleted )
301 : {
302 47 : sal_uInt16 nEndChanges = nPos+nDeleted;
303 47 : if ( !IsInvalid() )
304 : {
305 0 : sal_uInt16 nNewInvalidStart = nPos ? nPos - 1 : 0;
306 0 : nInvalidStart = nNewInvalidStart;
307 0 : nInvalidEnd = nNewInvalidStart + 1;
308 : }
309 : else
310 : {
311 47 : if ( nInvalidStart > nPos )
312 0 : nInvalidStart = nPos;
313 47 : if ( nInvalidEnd > nPos )
314 : {
315 0 : if ( nInvalidEnd > nEndChanges )
316 0 : nInvalidEnd = nInvalidEnd - nDeleted;
317 : else
318 0 : nInvalidEnd = nPos+1;
319 : }
320 : }
321 :
322 94 : for (WrongList::iterator i = begin(); i != end(); )
323 : {
324 0 : sal_Bool bDelWrong = sal_False;
325 0 : if (i->nEnd >= nPos)
326 : {
327 : // Move all Wrongs after the insert position...
328 0 : if (i->nStart >= nEndChanges)
329 : {
330 0 : i->nStart -= nDeleted;
331 0 : i->nEnd -= nDeleted;
332 : }
333 : // 1. Delete Internal Wrongs ...
334 0 : else if (i->nStart >= nPos && i->nEnd <= nEndChanges)
335 : {
336 0 : bDelWrong = sal_True;
337 : }
338 : // 2. Wrong begins before, ends inside or behind it ...
339 0 : else if (i->nStart <= nPos && i->nEnd > nPos)
340 : {
341 0 : if (i->nEnd <= nEndChanges) // ends inside
342 0 : i->nEnd = nPos;
343 : else
344 0 : i->nEnd -= nDeleted; // ends after
345 : }
346 : // 3. Wrong begins inside, ending after ...
347 0 : else if (i->nStart >= nPos && i->nEnd > nEndChanges)
348 : {
349 0 : i->nStart = nEndChanges - nDeleted;
350 0 : i->nEnd -= nDeleted;
351 : }
352 : }
353 : SAL_WARN_IF(i->nStart >= i->nEnd, "editeng",
354 : "TextDeleted, WrongRange: Start >= End?!");
355 0 : if ( bDelWrong )
356 : {
357 0 : i = maRanges.erase(i);
358 : }
359 : else
360 : {
361 0 : ++i;
362 : }
363 : }
364 :
365 : SAL_WARN_IF(DbgIsBuggy(), "editeng", "TextDeleted: WrongList broken!");
366 47 : }
367 :
368 70 : sal_Bool WrongList::NextWrong( sal_uInt16& rnStart, sal_uInt16& rnEnd ) const
369 : {
370 : /*
371 : rnStart get the start position, is possibly adjusted wrt. Wrong start
372 : rnEnd does not have to be initialized.
373 : */
374 72 : for (WrongList::const_iterator i = begin(); i != end(); ++i)
375 : {
376 70 : if ( i->nEnd > rnStart )
377 : {
378 68 : rnStart = i->nStart;
379 68 : rnEnd = i->nEnd;
380 68 : return sal_True;
381 : }
382 : }
383 2 : return sal_False;
384 : }
385 :
386 160 : sal_Bool WrongList::HasWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
387 : {
388 161 : for (WrongList::const_iterator i = begin(); i != end(); ++i)
389 : {
390 1 : if (i->nStart == nStart && i->nEnd == nEnd)
391 0 : return sal_True;
392 1 : else if ( i->nStart >= nStart )
393 0 : break;
394 : }
395 160 : return sal_False;
396 : }
397 :
398 3556 : sal_Bool WrongList::HasAnyWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
399 : {
400 3560 : for (WrongList::const_iterator i = begin(); i != end(); ++i)
401 : {
402 4 : if (i->nEnd >= nStart && i->nStart < nEnd)
403 0 : return sal_True;
404 4 : else if (i->nStart >= nEnd)
405 0 : break;
406 : }
407 3556 : return sal_False;
408 : }
409 :
410 0 : void WrongList::ClearWrongs( sal_uInt16 nStart, sal_uInt16 nEnd,
411 : const ContentNode* pNode )
412 : {
413 0 : for (WrongList::iterator i = begin(); i != end(); )
414 : {
415 0 : if (i->nEnd > nStart && i->nStart < nEnd)
416 : {
417 0 : if (i->nEnd > nEnd) // Runs out
418 : {
419 0 : i->nStart = nEnd;
420 : // Blanks?
421 0 : while (i->nStart < pNode->Len() &&
422 0 : (pNode->GetChar(i->nStart) == ' ' ||
423 0 : pNode->IsFeature(i->nStart)))
424 : {
425 0 : ++(i->nStart);
426 : }
427 0 : ++i;
428 : }
429 : else
430 : {
431 0 : i = maRanges.erase(i);
432 : // no increment here
433 : }
434 : }
435 : else
436 : {
437 0 : ++i;
438 : }
439 : }
440 :
441 : SAL_WARN_IF(DbgIsBuggy(), "editeng", "ClearWrongs: WrongList broken!");
442 0 : }
443 :
444 160 : void WrongList::InsertWrong( sal_uInt16 nStart, sal_uInt16 nEnd,
445 : sal_Bool bClearRange )
446 : {
447 160 : WrongList::iterator nPos = end();
448 161 : for (WrongList::iterator i = begin(); i != end(); ++i)
449 : {
450 1 : if (i->nStart >= nStart )
451 : {
452 0 : nPos = i;
453 0 : if ( bClearRange )
454 : {
455 : // It can really only happen that the Wrong starts exactly here
456 : // and runs along, but not that there are several ranges ...
457 : // Exactly in the range is no one allowed to be, otherwise this
458 : // Method can not be called!
459 : SAL_WARN_IF((i->nStart != nStart || i->nEnd <= nEnd) && i->nStart <= nEnd, "editeng", "InsertWrong: RangeMismatch!");
460 0 : if (i->nStart == nStart && i->nEnd > nEnd)
461 0 : i->nStart = nEnd + 1;
462 : }
463 0 : break;
464 : }
465 : }
466 :
467 160 : if (nPos != maRanges.end())
468 0 : maRanges.insert(nPos, WrongRange(nStart, nEnd));
469 : else
470 160 : maRanges.push_back(WrongRange(nStart, nEnd));
471 :
472 : SAL_WARN_IF(DbgIsBuggy(), "editeng", "InsertWrong: WrongList broken!");
473 160 : }
474 :
475 0 : void WrongList::MarkWrongsInvalid()
476 : {
477 0 : if (!maRanges.empty())
478 0 : MarkInvalid(maRanges.front().nStart, maRanges.back().nEnd );
479 0 : }
480 :
481 120707 : WrongList* WrongList::Clone() const
482 : {
483 120707 : return new WrongList(*this);
484 : }
485 :
486 : // #i102062#
487 0 : bool WrongList::operator==(const WrongList& rCompare) const
488 : {
489 : // cleck direct members
490 0 : if(GetInvalidStart() != rCompare.GetInvalidStart()
491 0 : || GetInvalidEnd() != rCompare.GetInvalidEnd()
492 0 : || maRanges.size() != rCompare.maRanges.size())
493 0 : return false;
494 :
495 0 : WrongList::const_iterator rCA = maRanges.begin();
496 0 : WrongList::const_iterator rCB = rCompare.maRanges.begin();
497 :
498 0 : for (; rCA != maRanges.end(); ++rCA, ++rCB)
499 : {
500 0 : if(rCA->nStart != rCB->nStart || rCA->nEnd != rCB->nEnd)
501 0 : return false;
502 : }
503 :
504 0 : return true;
505 : }
506 :
507 8832 : bool WrongList::empty() const
508 : {
509 8832 : return maRanges.empty();
510 : }
511 :
512 0 : void WrongList::push_back(const WrongRange& rRange)
513 : {
514 0 : maRanges.push_back(rRange);
515 0 : }
516 :
517 0 : WrongRange& WrongList::back()
518 : {
519 0 : return maRanges.back();
520 : }
521 :
522 0 : const WrongRange& WrongList::back() const
523 : {
524 0 : return maRanges.back();
525 : }
526 :
527 618 : WrongList::iterator WrongList::begin()
528 : {
529 618 : return maRanges.begin();
530 : }
531 :
532 779 : WrongList::iterator WrongList::end()
533 : {
534 779 : return maRanges.end();
535 : }
536 :
537 3786 : WrongList::const_iterator WrongList::begin() const
538 : {
539 3786 : return maRanges.begin();
540 : }
541 :
542 3793 : WrongList::const_iterator WrongList::end() const
543 : {
544 3793 : return maRanges.end();
545 : }
546 :
547 0 : sal_Bool WrongList::DbgIsBuggy() const
548 : {
549 : // Check if the ranges overlap.
550 0 : sal_Bool bError = sal_False;
551 0 : for (WrongList::const_iterator i = begin(); !bError && (i != end()); ++i)
552 : {
553 0 : for (WrongList::const_iterator j = i + 1; !bError && (j != end()); ++j)
554 : {
555 : // 1) Start before, End after the second Start
556 0 : if (i->nStart <= j->nStart && i->nEnd >= j->nStart)
557 0 : bError = sal_True;
558 : // 2) Start after the second Start, but still before the second End
559 0 : else if (i->nStart >= j->nStart && i->nStart <= j->nEnd)
560 0 : bError = sal_True;
561 : }
562 : }
563 0 : return bError;
564 : }
565 :
566 : //////////////////////////////////////////////////////////////////////
567 :
568 0 : EdtAutoCorrDoc::EdtAutoCorrDoc(
569 : EditEngine* pE, ContentNode* pN, sal_uInt16 nCrsr, sal_Unicode cIns) :
570 : mpEditEngine(pE),
571 : pCurNode(pN),
572 : nCursor(nCrsr),
573 0 : bAllowUndoAction(cIns != 0),
574 0 : bUndoAction(false) {}
575 :
576 0 : EdtAutoCorrDoc::~EdtAutoCorrDoc()
577 : {
578 0 : if ( bUndoAction )
579 0 : mpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
580 0 : }
581 :
582 0 : sal_Bool EdtAutoCorrDoc::Delete( sal_uInt16 nStt, sal_uInt16 nEnd )
583 : {
584 0 : EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
585 0 : mpEditEngine->DeleteSelection(aSel);
586 : SAL_WARN_IF(nCursor < nEnd, "editeng",
587 : "Cursor in the heart of the action?!");
588 0 : nCursor -= ( nEnd-nStt );
589 0 : bAllowUndoAction = sal_False;
590 0 : return sal_True;
591 : }
592 :
593 0 : sal_Bool EdtAutoCorrDoc::Insert( sal_uInt16 nPos, const String& rTxt )
594 : {
595 0 : EditSelection aSel = EditPaM( pCurNode, nPos );
596 0 : mpEditEngine->InsertText(aSel, rTxt);
597 : SAL_WARN_IF(nCursor < nPos, "editeng",
598 : "Cursor in the heart of the action?!");
599 0 : nCursor = nCursor + rTxt.Len();
600 :
601 0 : if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
602 0 : ImplStartUndoAction();
603 0 : bAllowUndoAction = sal_False;
604 :
605 0 : return sal_True;
606 : }
607 :
608 0 : sal_Bool EdtAutoCorrDoc::Replace( sal_uInt16 nPos, const String& rTxt )
609 : {
610 0 : return ReplaceRange( nPos, rTxt.Len(), rTxt );
611 : }
612 :
613 0 : sal_Bool EdtAutoCorrDoc::ReplaceRange( xub_StrLen nPos, xub_StrLen nSourceLength, const String& rTxt )
614 : {
615 : // Actually a Replace introduce => corresponds to UNDO
616 0 : sal_uInt16 nEnd = nPos+nSourceLength;
617 0 : if ( nEnd > pCurNode->Len() )
618 0 : nEnd = pCurNode->Len();
619 :
620 : // #i5925# First insert new text behind to be deleted text, for keeping attributes.
621 0 : mpEditEngine->InsertText(EditSelection(EditPaM(pCurNode, nEnd)), rTxt);
622 : mpEditEngine->DeleteSelection(
623 0 : EditSelection(EditPaM(pCurNode, nPos), EditPaM(pCurNode, nEnd)));
624 :
625 0 : if ( nPos == nCursor )
626 0 : nCursor = nCursor + rTxt.Len();
627 :
628 0 : if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
629 0 : ImplStartUndoAction();
630 :
631 0 : bAllowUndoAction = sal_False;
632 :
633 0 : return sal_True;
634 : }
635 :
636 0 : sal_Bool EdtAutoCorrDoc::SetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
637 : sal_uInt16 nSlotId, SfxPoolItem& rItem )
638 : {
639 0 : SfxItemPool* pPool = &mpEditEngine->GetEditDoc().GetItemPool();
640 0 : while ( pPool->GetSecondaryPool() &&
641 0 : !pPool->GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EditEngineItemPool")) )
642 : {
643 0 : pPool = pPool->GetSecondaryPool();
644 :
645 : }
646 0 : sal_uInt16 nWhich = pPool->GetWhich( nSlotId );
647 0 : if ( nWhich )
648 : {
649 0 : rItem.SetWhich( nWhich );
650 :
651 0 : SfxItemSet aSet = mpEditEngine->GetEmptyItemSet();
652 0 : aSet.Put( rItem );
653 :
654 0 : EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
655 0 : aSel.Max().SetIndex( nEnd ); // ???
656 0 : mpEditEngine->SetAttribs( aSel, aSet, ATTRSPECIAL_EDGE );
657 0 : bAllowUndoAction = false;
658 : }
659 0 : return sal_True;
660 : }
661 :
662 0 : sal_Bool EdtAutoCorrDoc::SetINetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
663 : const String& rURL )
664 : {
665 : // Turn the Text into a command field ...
666 0 : EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
667 0 : String aText = mpEditEngine->GetSelected(aSel);
668 0 : aSel = mpEditEngine->DeleteSelection(aSel);
669 : SAL_WARN_IF(nCursor < nEnd, "editeng",
670 : "Cursor in the heart of the action?!");
671 0 : nCursor -= ( nEnd-nStt );
672 : SvxFieldItem aField( SvxURLField( rURL, aText, SVXURLFORMAT_REPR ),
673 0 : EE_FEATURE_FIELD );
674 0 : mpEditEngine->InsertField(aSel, aField);
675 0 : nCursor++;
676 0 : mpEditEngine->UpdateFieldsOnly();
677 0 : bAllowUndoAction = false;
678 0 : return sal_True;
679 : }
680 :
681 0 : const String* EdtAutoCorrDoc::GetPrevPara( sal_Bool )
682 : {
683 : // Return previous paragraph, so that it can be determined,
684 : // whether the current word is at the beginning of a sentence.
685 :
686 0 : bAllowUndoAction = sal_False; // Not anymore ...
687 :
688 0 : EditDoc& rNodes = mpEditEngine->GetEditDoc();
689 0 : sal_Int32 nPos = rNodes.GetPos( pCurNode );
690 :
691 : // Special case: Bullet => Paragraph start => simply return NULL...
692 : const SfxBoolItem& rBulletState = (const SfxBoolItem&)
693 0 : mpEditEngine->GetParaAttrib( nPos, EE_PARA_BULLETSTATE );
694 0 : sal_Bool bBullet = rBulletState.GetValue() ? sal_True : sal_False;
695 0 : if ( !bBullet && (mpEditEngine->GetControlWord() & EE_CNTRL_OUTLINER) )
696 : {
697 : // The Outliner has still a Bullet at Level 0.
698 : const SfxInt16Item& rLevel = (const SfxInt16Item&)
699 0 : mpEditEngine->GetParaAttrib( nPos, EE_PARA_OUTLLEVEL );
700 0 : if ( rLevel.GetValue() == 0 )
701 0 : bBullet = sal_True;
702 : }
703 0 : if ( bBullet )
704 0 : return NULL;
705 :
706 0 : for ( sal_Int32 n = nPos; n; )
707 : {
708 0 : n--;
709 0 : ContentNode* pNode = rNodes[n];
710 0 : if ( pNode->Len() )
711 0 : return &pNode->GetString();
712 : }
713 0 : return NULL;
714 :
715 : }
716 :
717 0 : sal_Bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_uInt16& rSttPos,
718 : sal_uInt16 nEndPos, SvxAutoCorrect& rACorrect,
719 : const String** ppPara )
720 : {
721 : // Paragraph-start or a blank found, search for the word
722 : // shortcut in Auto
723 0 : bAllowUndoAction = sal_False; // Not anymore ...
724 :
725 0 : String aShort( pCurNode->Copy( rSttPos, nEndPos - rSttPos ) );
726 0 : sal_Bool bRet = sal_False;
727 :
728 0 : if( !aShort.Len() )
729 0 : return bRet;
730 :
731 0 : LanguageType eLang = mpEditEngine->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) );
732 0 : const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList(pCurNode->GetString(), rSttPos, nEndPos, *this, eLang);
733 0 : if( pFnd && pFnd->IsTextOnly() )
734 : {
735 : // then replace
736 : EditSelection aSel( EditPaM( pCurNode, rSttPos ),
737 0 : EditPaM( pCurNode, nEndPos ) );
738 0 : aSel = mpEditEngine->DeleteSelection(aSel);
739 : SAL_WARN_IF(nCursor < nEndPos, "editeng",
740 : "Cursor in the heart of the action?!");
741 0 : nCursor -= ( nEndPos-rSttPos );
742 0 : mpEditEngine->InsertText(aSel, pFnd->GetLong());
743 0 : nCursor = nCursor + pFnd->GetLong().Len();
744 0 : if( ppPara )
745 0 : *ppPara = &pCurNode->GetString();
746 0 : bRet = sal_True;
747 : }
748 :
749 0 : return bRet;
750 : }
751 :
752 0 : LanguageType EdtAutoCorrDoc::GetLanguage( sal_uInt16 nPos, sal_Bool ) const
753 : {
754 0 : return mpEditEngine->GetLanguage( EditPaM( pCurNode, nPos+1 ) );
755 : }
756 :
757 0 : void EdtAutoCorrDoc::ImplStartUndoAction()
758 : {
759 0 : sal_Int32 nPara = mpEditEngine->GetEditDoc().GetPos( pCurNode );
760 0 : ESelection aSel( nPara, nCursor, nPara, nCursor );
761 0 : mpEditEngine->UndoActionStart( EDITUNDO_INSERT, aSel );
762 0 : bUndoAction = sal_True;
763 0 : bAllowUndoAction = sal_False;
764 267 : }
765 :
766 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|