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: acmplwrd.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_sw.hxx"
35 #include <hintids.hxx>
37 #include <unotools/transliterationwrapper.hxx>
38 #include <acmplwrd.hxx>
40 #include <ndindex.hxx>
44 #include <pagedesc.hxx>
45 #include <poolfmt.hxx>
47 #include <svx/svxacorr.hxx>
49 #include <svx/acorrcfg.hxx>
50 #include <sfx2/docfile.hxx>
54 /* -----------------------------05.08.2002 12:43------------------------------
56 ---------------------------------------------------------------------------*/
57 class SwAutoCompleteClient
: public SwClient
59 SwAutoCompleteWord
* pAutoCompleteWord
;
62 static ULONG nSwAutoCompleteClientCount
;
65 SwAutoCompleteClient(SwAutoCompleteWord
& rToTell
, SwDoc
& rSwDoc
);
66 SwAutoCompleteClient(const SwAutoCompleteClient
& rClient
);
67 ~SwAutoCompleteClient();
69 SwAutoCompleteClient
& operator=(const SwAutoCompleteClient
& rClient
);
71 virtual void Modify( SfxPoolItem
*pOld
, SfxPoolItem
*pNew
);
72 const SwDoc
& GetDoc(){return *pDoc
;}
74 static ULONG
GetElementCount() {return nSwAutoCompleteClientCount
;}
77 /* -----------------------------05.08.2002 12:48------------------------------
79 ---------------------------------------------------------------------------*/
80 typedef std::vector
<SwAutoCompleteClient
> SwAutoCompleteClientVector
;
82 class SwAutoCompleteWord_Impl
84 SwAutoCompleteClientVector aClientVector
;
85 SwAutoCompleteWord
& rAutoCompleteWord
;
87 SwAutoCompleteWord_Impl(SwAutoCompleteWord
& rParent
) :
88 rAutoCompleteWord(rParent
){}
89 void AddDocument(SwDoc
& rDoc
);
90 void RemoveDocument(const SwDoc
& rDoc
);
93 /* -----------------------------05.08.2002 14:11------------------------------
95 ---------------------------------------------------------------------------*/
96 typedef const SwDoc
* SwDocPtr
;
97 typedef std::vector
<SwDocPtr
> SwDocPtrVector
;
98 class SwAutoCompleteString
: public String
101 static ULONG nSwAutoCompleteStringCount
;
103 SwDocPtrVector aSourceDocs
;
105 SwAutoCompleteString(const String
& rStr
, xub_StrLen nPos
, xub_StrLen nLen
);
107 ~SwAutoCompleteString();
108 void AddDocument(const SwDoc
& rDoc
);
109 //returns true if last document reference has been removed
110 sal_Bool
RemoveDocument(const SwDoc
& rDoc
);
112 static ULONG
GetElementCount() {return nSwAutoCompleteStringCount
;}
116 ULONG
SwAutoCompleteClient::nSwAutoCompleteClientCount
= 0;
117 ULONG
SwAutoCompleteString::nSwAutoCompleteStringCount
= 0;
119 /* -----------------------------06.08.2002 08:57------------------------------
121 ---------------------------------------------------------------------------*/
122 SwAutoCompleteClient::SwAutoCompleteClient(SwAutoCompleteWord
& rToTell
, SwDoc
& rSwDoc
) :
123 pAutoCompleteWord(&rToTell
),
126 pDoc
->GetPageDescFromPool(RES_POOLPAGE_STANDARD
)->Add(this);
128 ++nSwAutoCompleteClientCount
;
131 /* -----------------------------05.08.2002 14:07------------------------------
133 ---------------------------------------------------------------------------*/
134 SwAutoCompleteClient::SwAutoCompleteClient(const SwAutoCompleteClient
& rClient
) :
136 pAutoCompleteWord(rClient
.pAutoCompleteWord
),
139 pDoc
->GetPageDescFromPool(RES_POOLPAGE_STANDARD
)->Add(this);
141 ++nSwAutoCompleteClientCount
;
144 /* -----------------------------05.08.2002 14:10------------------------------
146 ---------------------------------------------------------------------------*/
147 SwAutoCompleteClient::~SwAutoCompleteClient()
150 --nSwAutoCompleteClientCount
;
153 /* -----------------06.03.2003 15:30-----------------
155 --------------------------------------------------*/
156 SwAutoCompleteClient
& SwAutoCompleteClient::operator=(const SwAutoCompleteClient
& rClient
)
158 pAutoCompleteWord
= rClient
.pAutoCompleteWord
;
160 if(rClient
.GetRegisteredIn())
161 rClient
.pRegisteredIn
->Add(this);
162 else if(GetRegisteredIn())
163 pRegisteredIn
->Remove(this);
166 /* -----------------------------05.08.2002 12:49------------------------------
168 ---------------------------------------------------------------------------*/
169 void SwAutoCompleteClient::Modify(SfxPoolItem
*pOld
, SfxPoolItem
*)
171 switch( pOld
? pOld
->Which() : 0 )
173 case RES_REMOVE_UNO_OBJECT
:
174 case RES_OBJECTDYING
:
175 if( (void*)GetRegisteredIn() == ((SwPtrMsgPoolItem
*)pOld
)->pObject
)
176 ((SwModify
*)GetRegisteredIn())->Remove(this);
177 pAutoCompleteWord
->DocumentDying(*pDoc
);
182 /* -----------------------------05.08.2002 13:03------------------------------
184 ---------------------------------------------------------------------------*/
185 void SwAutoCompleteWord_Impl::AddDocument(SwDoc
& rDoc
)
187 SwAutoCompleteClientVector::iterator aIt
;
188 for(aIt
= aClientVector
.begin(); aIt
!= aClientVector
.end(); aIt
++)
190 if(&aIt
->GetDoc() == &rDoc
)
193 aClientVector
.push_back(SwAutoCompleteClient(rAutoCompleteWord
, rDoc
));
195 /* -----------------------------05.08.2002 14:33------------------------------
197 ---------------------------------------------------------------------------*/
198 void SwAutoCompleteWord_Impl::RemoveDocument(const SwDoc
& rDoc
)
200 SwAutoCompleteClientVector::iterator aIt
;
201 for(aIt
= aClientVector
.begin(); aIt
!= aClientVector
.end(); aIt
++)
203 if(&aIt
->GetDoc() == &rDoc
)
205 aClientVector
.erase(aIt
);
210 /* -----------------------------06.08.2002 08:54------------------------------
212 ---------------------------------------------------------------------------*/
213 SwAutoCompleteString::SwAutoCompleteString(const String
& rStr
, xub_StrLen nPos
, xub_StrLen nLen
) :
214 String( rStr
, nPos
, nLen
)
217 ++nSwAutoCompleteStringCount
;
220 /* -----------------------------05.08.2002 14:22------------------------------
222 ---------------------------------------------------------------------------*/
223 SwAutoCompleteString::~SwAutoCompleteString()
226 --nSwAutoCompleteStringCount
;
229 /* -----------------------------05.08.2002 14:17------------------------------
231 ---------------------------------------------------------------------------*/
232 void SwAutoCompleteString::AddDocument(const SwDoc
& rDoc
)
234 SwDocPtrVector::iterator aIt
;
235 for(aIt
= aSourceDocs
.begin(); aIt
!= aSourceDocs
.end(); aIt
++)
240 SwDocPtr pNew
= &rDoc
;
241 aSourceDocs
.push_back(pNew
);
243 /* -----------------------------05.08.2002 14:36------------------------------
245 ---------------------------------------------------------------------------*/
246 sal_Bool
SwAutoCompleteString::RemoveDocument(const SwDoc
& rDoc
)
248 SwDocPtrVector::iterator aIt
;
249 for(aIt
= aSourceDocs
.begin(); aIt
!= aSourceDocs
.end(); aIt
++)
253 aSourceDocs
.erase(aIt
);
254 return !aSourceDocs
.size();
259 /* ---------------------------------------------------------------------------
261 ---------------------------------------------------------------------------*/
262 SwAutoCompleteWord::SwAutoCompleteWord( USHORT nWords
, USHORT nMWrdLen
)
263 : aWordLst( 0, 255 ), aLRULst( 0, 255 ),
264 pImpl(new SwAutoCompleteWord_Impl(*this)),
266 nMinWrdLen( nMWrdLen
),
267 bLockWordLst( FALSE
)
271 SwAutoCompleteWord::~SwAutoCompleteWord()
273 for(USHORT nPos
= aWordLst
.Count(); nPos
; nPos
--)
275 SwAutoCompleteString
* pCurrent
= (SwAutoCompleteString
*)aWordLst
[ nPos
- 1 ];
276 aWordLst
.Remove( nPos
- 1 );
281 ULONG nStrings
= SwAutoCompleteString::GetElementCount();
282 ULONG nClients
= SwAutoCompleteClient::GetElementCount();
283 DBG_ASSERT(!nStrings
&& !nClients
, "AutoComplete: clients or string count mismatch");
287 BOOL
SwAutoCompleteWord::InsertWord( const String
& rWord
, SwDoc
& rDoc
)
289 SwDocShell
* pDocShell
= rDoc
.GetDocShell();
290 SfxMedium
* pMedium
= pDocShell
? pDocShell
->GetMedium() : 0;
291 // strings from help module should not be added
294 const INetURLObject
& rURL
= pMedium
->GetURLObject();
295 if ( rURL
.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP
)
299 String
aNewWord(rWord
);
300 aNewWord
.EraseAllChars( CH_TXTATR_INWORD
);
301 aNewWord
.EraseAllChars( CH_TXTATR_BREAKWORD
);
303 pImpl
->AddDocument(rDoc
);
305 xub_StrLen nWrdLen
= aNewWord
.Len();
306 while( nWrdLen
&& '.' == aNewWord
.GetChar( nWrdLen
-1 ))
309 if( !bLockWordLst
&& nWrdLen
>= nMinWrdLen
)
311 SwAutoCompleteString
* pAutoString
;
312 StringPtr pNew
= pAutoString
= new SwAutoCompleteString( aNewWord
, 0, nWrdLen
);
313 pAutoString
->AddDocument(rDoc
);
315 if( aWordLst
.Insert( pNew
, nInsPos
) )
318 if( aLRULst
.Count() < nMaxCount
)
319 aLRULst
.Insert( pNew
, 0 );
322 // der letzte muss entfernt werden
323 // damit der neue vorne Platz hat
324 String
* pDel
= (String
*)aLRULst
[ nMaxCount
- 1 ];
326 void** ppData
= (void**)aLRULst
.GetData();
327 memmove( ppData
+1, ppData
, (nMaxCount
- 1) * sizeof( void* ));
330 aWordLst
.Remove( pDel
);
331 delete (SwAutoCompleteString
*)pDel
;
336 delete (SwAutoCompleteString
*)pNew
;
337 // dann aber auf jedenfall nach "oben" moven
338 pNew
= aWordLst
[ nInsPos
];
340 //add the document to the already inserted string
341 SwAutoCompleteString
* pCurrent
= (SwAutoCompleteString
*)pNew
;
342 pCurrent
->AddDocument(rDoc
);
344 nInsPos
= aLRULst
.GetPos( (void*)pNew
);
345 ASSERT( USHRT_MAX
!= nInsPos
, "String nicht gefunden" );
348 void** ppData
= (void**)aLRULst
.GetData();
349 memmove( ppData
+1, ppData
, nInsPos
* sizeof( void* ) );
357 void SwAutoCompleteWord::SetMaxCount( USHORT nNewMax
)
359 if( nNewMax
< nMaxCount
&& aLRULst
.Count() > nNewMax
)
361 // dann die unten ueberhaengenden entfernen
362 USHORT nLRUIndex
= nNewMax
-1;
363 while( nNewMax
< aWordLst
.Count() && nLRUIndex
< aLRULst
.Count())
365 USHORT nPos
= aWordLst
.GetPos( (String
*)aLRULst
[ nLRUIndex
++ ] );
366 ASSERT( USHRT_MAX
!= nPos
, "String nicht gefunden" );
367 void * pDel
= aWordLst
[nPos
];
368 aWordLst
.Remove(nPos
);
369 delete (SwAutoCompleteString
*)pDel
;
371 aLRULst
.Remove( nNewMax
-1, aLRULst
.Count() - nNewMax
);
376 void SwAutoCompleteWord::SetMinWordLen( USHORT n
)
378 // will man wirklich alle Worte, die kleiner als die neue Min Laenge
380 // JP 02.02.99 - erstmal nicht.
382 // JP 11.03.99 - mal testhalber eingebaut
385 for( USHORT nPos
= 0; nPos
< aWordLst
.Count(); ++nPos
)
386 if( aWordLst
[ nPos
]->Len() < n
)
388 void* pDel
= aWordLst
[ nPos
];
389 aWordLst
.Remove(nPos
);
391 USHORT nDelPos
= aLRULst
.GetPos( pDel
);
392 ASSERT( USHRT_MAX
!= nDelPos
, "String nicht gefunden" );
393 aLRULst
.Remove( nDelPos
);
395 delete (SwAutoCompleteString
*)pDel
;
402 BOOL
SwAutoCompleteWord::GetRange( const String
& rWord
, USHORT
& rStt
,
405 const StringPtr pStr
= (StringPtr
)&rWord
;
406 aWordLst
.Seek_Entry( pStr
, &rStt
);
409 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
410 while( rEnd
< aWordLst
.Count() && rSCmp
.isMatch( rWord
, *aWordLst
[ rEnd
]))
416 void SwAutoCompleteWord::CheckChangedList( const SvStringsISortDtor
& rNewLst
)
418 USHORT nMyLen
= aWordLst
.Count(), nNewLen
= rNewLst
.Count();
419 USHORT nMyPos
= 0, nNewPos
= 0;
421 for( ; nMyPos
< nMyLen
&& nNewPos
< nNewLen
; ++nMyPos
, ++nNewPos
)
423 const StringPtr pStr
= rNewLst
[ nNewPos
];
424 while( aWordLst
[ nMyPos
] != pStr
)
426 void* pDel
= aWordLst
[ nMyPos
];
427 aWordLst
.Remove(nMyPos
);
429 USHORT nPos
= aLRULst
.GetPos( pDel
);
430 ASSERT( USHRT_MAX
!= nPos
, "String nicht gefunden" );
431 aLRULst
.Remove( nPos
);
432 delete (SwAutoCompleteString
*)pDel
;
433 if( nMyPos
>= --nMyLen
)
437 //remove the elements at the end of the array
438 if( nMyPos
< nMyLen
)
440 //clear LRU array first then delete the string object
441 for( ; nNewPos
< nMyLen
; ++nNewPos
)
443 void* pDel
= aWordLst
[ nNewPos
];
444 USHORT nPos
= aLRULst
.GetPos( pDel
);
445 ASSERT( USHRT_MAX
!= nPos
, "String nicht gefunden" );
446 aLRULst
.Remove( nPos
);
447 delete (SwAutoCompleteString
*)pDel
;
450 aWordLst
.Remove( nMyPos
, nMyLen
- nMyPos
);
453 /* -----------------------------05.08.2002 12:54------------------------------
455 ---------------------------------------------------------------------------*/
456 void SwAutoCompleteWord::DocumentDying(const SwDoc
& rDoc
)
458 pImpl
->RemoveDocument(rDoc
);
460 SvxAutoCorrect
* pACorr
= SvxAutoCorrCfg::Get()->GetAutoCorrect();
461 const sal_Bool bDelete
= !pACorr
->GetSwFlags().bAutoCmpltKeepList
;
462 for(USHORT nPos
= aWordLst
.Count(); nPos
; nPos
--)
464 SwAutoCompleteString
* pCurrent
= (SwAutoCompleteString
*)aWordLst
[ nPos
- 1 ];
465 if(pCurrent
->RemoveDocument(rDoc
) && bDelete
)
467 aWordLst
.Remove( nPos
- 1 );
468 USHORT nLRUPos
= aLRULst
.GetPos( (void*)pCurrent
);
469 DBG_ASSERT(nLRUPos
< USHRT_MAX
, "word not found in LRU list" );
470 aLRULst
.Remove( nLRUPos
);