1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27
28
29 #define _SVSTDARR_STRINGSDTOR
30 #define _SVSTDARR_STRINGSISORTDTOR
31 #define _SVSTDARR_STRINGS
32 #include <svl/svstdarr.hxx>
33 #include <tools/urlobj.hxx>
34 #include <vcl/dialog.hxx>
35 #include <vcl/msgbox.hxx>
36 #ifndef _SV_BUTTON_HXX //autogen
37 #include <vcl/button.hxx>
38 #endif
39 #ifndef _FIXED_HXX //autogen
40 #include <vcl/fixed.hxx>
41 #endif
42 #include <vcl/lstbox.hxx>
43 #ifndef SVTOOLS_FSTATHELPER_HXX
44 #include <svl/fstathelper.hxx>
45 #endif
46 #include <unotools/pathoptions.hxx>
47 #include <unotools/transliterationwrapper.hxx>
48 #include <swtypes.hxx>
49 #include <swmodule.hxx>
50 #include <shellio.hxx>
51 #include <initui.hxx>
52 #include <glosdoc.hxx>
53 #include <gloslst.hxx>
54 #include <swunohelper.hxx>
55
56 #ifndef _UTLUI_HRC
57 #include <utlui.hrc>
58 #endif
59 #ifndef _GLOSLST_HRC
60 #include <gloslst.hrc>
61 #endif
62
63
64 #define STRING_DELIM (char)0x0A
65 #define GLOS_TIMEOUT 30000 // alle 30 s updaten
66 #define FIND_MAX_GLOS 20
67
68
69 struct TripleString
70 {
71 String sGroup;
72 String sBlock;
73 String sShort;
74 };
75
76 typedef TripleString* TripleStringPtr;
77 SV_DECL_PTRARR_DEL( TripleStrings, TripleStringPtr, 0, 4 )
78 SV_IMPL_PTRARR( TripleStrings, TripleStringPtr )
79
80 class SwGlossDecideDlg : public ModalDialog
81 {
82 OKButton aOk;
83 CancelButton aCancel;
84 HelpButton aHelp;
85 ListBox aListLB;
86 FixedLine aFL;
87
88 DECL_LINK(DoubleClickHdl, ListBox*);
89 DECL_LINK(SelectHdl, ListBox*);
90
91 public:
92 SwGlossDecideDlg(Window* pParent);
GetListBox()93 ListBox& GetListBox() {return aListLB;}
94 };
95
96 /*-----------------21.01.97 13.25-------------------
97
98 --------------------------------------------------*/
99
SwGlossDecideDlg(Window * pParent)100 SwGlossDecideDlg::SwGlossDecideDlg(Window* pParent) :
101 ModalDialog(pParent, SW_RES(DLG_GLOSSARY_DECIDE_DLG)),
102 aOk(this, SW_RES(PB_OK)),
103 aCancel(this, SW_RES(PB_CANCEL)),
104 aHelp(this, SW_RES(PB_HELP)),
105 aListLB(this, SW_RES(LB_LIST)),
106 aFL(this, SW_RES(FL_GLOSS))
107 {
108 FreeResource();
109 aListLB.SetDoubleClickHdl(LINK(this, SwGlossDecideDlg, DoubleClickHdl));
110 aListLB.SetSelectHdl(LINK(this, SwGlossDecideDlg, SelectHdl));
111 }
112
113 /*-----------------21.01.97 13.25-------------------
114
115 --------------------------------------------------*/
116
IMPL_LINK(SwGlossDecideDlg,DoubleClickHdl,ListBox *,EMPTYARG)117 IMPL_LINK(SwGlossDecideDlg, DoubleClickHdl, ListBox*, EMPTYARG)
118 {
119 EndDialog(RET_OK);
120 return 0;
121 }
122 /*-----------------21.01.97 13.29-------------------
123
124 --------------------------------------------------*/
125
IMPL_LINK(SwGlossDecideDlg,SelectHdl,ListBox *,EMPTYARG)126 IMPL_LINK(SwGlossDecideDlg, SelectHdl, ListBox*, EMPTYARG)
127 {
128 aOk.Enable(LISTBOX_ENTRY_NOTFOUND != aListLB.GetSelectEntryPos());
129 return 0;
130 }
131
132 /********************************************************************
133
134 ********************************************************************/
135
136
SwGlossaryList()137 SwGlossaryList::SwGlossaryList() :
138 bFilled(sal_False)
139 {
140 SvtPathOptions aPathOpt;
141 sPath = aPathOpt.GetAutoTextPath();
142 SetTimeout(GLOS_TIMEOUT);
143 }
144
145 /********************************************************************
146
147 ********************************************************************/
148
149
~SwGlossaryList()150 SwGlossaryList::~SwGlossaryList()
151 {
152 ClearGroups();
153 }
154
155 /********************************************************************
156 * Wenn der GroupName bereits bekannt ist, dann wird nur
157 * rShortName gefuellt, sonst wird rGroupName ebenfals gesetzt und
158 * bei Bedarf nach der richtigen Gruppe gefragt
159 ********************************************************************/
160
161
GetShortName(const String & rLongName,String & rShortName,String & rGroupName)162 sal_Bool SwGlossaryList::GetShortName(const String& rLongName,
163 String& rShortName, String& rGroupName )
164 {
165 if(!bFilled)
166 Update();
167
168 TripleStrings aTripleStrings;
169
170 sal_uInt16 nCount = aGroupArr.Count();
171 sal_uInt16 nFound = 0;
172 for(sal_uInt16 i = 0; i < nCount; i++ )
173 {
174 AutoTextGroup* pGroup = aGroupArr.GetObject(i);
175 if(!rGroupName.Len() || rGroupName == pGroup->sName)
176 for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
177 {
178 String sLong = pGroup->sLongNames.GetToken(j, STRING_DELIM);
179 if((rLongName == sLong))
180 {
181 TripleString* pTriple = new TripleString;
182 pTriple->sGroup = pGroup->sName;
183 pTriple->sBlock = sLong;
184 pTriple->sShort = pGroup->sShortNames.GetToken(j, STRING_DELIM);
185 aTripleStrings.Insert(pTriple, nFound++);
186 }
187 }
188 }
189
190 sal_Bool bRet = sal_False;
191 nCount = aTripleStrings.Count();
192 if(1 == nCount )
193 {
194 TripleString* pTriple = aTripleStrings[0];
195 rShortName = pTriple->sShort;
196 rGroupName = pTriple->sGroup;
197 bRet = sal_True;
198 }
199 else if(1 < nCount)
200 {
201 SwGlossDecideDlg aDlg(0);
202 String sTitle = aDlg.GetText();
203 sTitle += ' ';
204 sTitle += aTripleStrings[0]->sBlock;
205 aDlg.SetText(sTitle);
206
207 ListBox& rLB = aDlg.GetListBox();
208 for(sal_uInt16 i = 0; i < nCount; i++ )
209 rLB.InsertEntry(aTripleStrings[i]->sGroup.GetToken(0, GLOS_DELIM));
210
211 rLB.SelectEntryPos(0);
212 if(RET_OK == aDlg.Execute() &&
213 LISTBOX_ENTRY_NOTFOUND != rLB.GetSelectEntryPos())
214 {
215 TripleString* pTriple = aTripleStrings[rLB.GetSelectEntryPos()];
216 rShortName = pTriple->sShort;
217 rGroupName = pTriple->sGroup;
218 bRet = sal_True;
219 }
220 else
221 bRet = sal_False;
222 }
223 return bRet;
224 }
225
226 /********************************************************************
227
228 ********************************************************************/
229
230
GetGroupCount()231 sal_uInt16 SwGlossaryList::GetGroupCount()
232 {
233 if(!bFilled)
234 Update();
235 return aGroupArr.Count();
236 }
237
238 /********************************************************************
239
240 ********************************************************************/
241
242
GetGroupName(sal_uInt16 nPos,sal_Bool bNoPath,String * pTitle)243 String SwGlossaryList::GetGroupName(sal_uInt16 nPos, sal_Bool bNoPath, String* pTitle)
244 {
245 DBG_ASSERT(aGroupArr.Count() > nPos, "Gruppe nicht vorhanden");
246 String sRet(aEmptyStr);
247 if(nPos < aGroupArr.Count())
248 {
249 AutoTextGroup* pGroup = aGroupArr.GetObject(nPos);
250 sRet = pGroup->sName;
251 if(bNoPath)
252 sRet = sRet.GetToken(0, GLOS_DELIM);
253 if(pTitle)
254 *pTitle = pGroup->sTitle;
255 }
256 return sRet;
257
258 }
259
260 /********************************************************************
261
262 ********************************************************************/
263
264
GetBlockCount(sal_uInt16 nGroup)265 sal_uInt16 SwGlossaryList::GetBlockCount(sal_uInt16 nGroup)
266 {
267 DBG_ASSERT(aGroupArr.Count() > nGroup, "Gruppe nicht vorhanden");
268 if(nGroup < aGroupArr.Count())
269 {
270 AutoTextGroup* pGroup = aGroupArr.GetObject(nGroup);
271 return pGroup->nCount;
272 }
273 return 0;
274 }
275
276 /********************************************************************
277
278 ********************************************************************/
279
280
GetBlockName(sal_uInt16 nGroup,sal_uInt16 nBlock,String & rShortName)281 String SwGlossaryList::GetBlockName(sal_uInt16 nGroup, sal_uInt16 nBlock, String& rShortName)
282 {
283 DBG_ASSERT(aGroupArr.Count() > nGroup, "Gruppe nicht vorhanden");
284 if(nGroup < aGroupArr.Count())
285 {
286 AutoTextGroup* pGroup = aGroupArr.GetObject(nGroup);
287 rShortName = pGroup->sShortNames.GetToken(nBlock, STRING_DELIM);
288 return pGroup->sLongNames.GetToken(nBlock, STRING_DELIM);
289 }
290 return aEmptyStr;
291 }
292
293 /********************************************************************
294
295 ********************************************************************/
296
297
Update()298 void SwGlossaryList::Update()
299 {
300 if(!IsActive())
301 Start();
302
303 SvtPathOptions aPathOpt;
304 String sTemp( aPathOpt.GetAutoTextPath() );
305 if(sTemp != sPath)
306 {
307 sPath = sTemp;
308 bFilled = sal_False;
309 ClearGroups();
310 }
311 SwGlossaries* pGlossaries = ::GetGlossaries();
312 const SvStrings* pPathArr = pGlossaries->GetPathArray();
313 String sExt( SwGlossaries::GetExtension() );
314 if(!bFilled)
315 {
316 sal_uInt16 nGroupCount = pGlossaries->GetGroupCnt();
317 for(sal_uInt16 i = 0; i < nGroupCount; i++)
318 {
319 String sGrpName = pGlossaries->GetGroupName(i);
320 sal_uInt16 nPath = (sal_uInt16)sGrpName.GetToken(1, GLOS_DELIM).ToInt32();
321 if(nPath < pPathArr->Count())
322 {
323 AutoTextGroup* pGroup = new AutoTextGroup;
324 pGroup->sName = sGrpName;
325
326 FillGroup(pGroup, pGlossaries);
327 String sName = *(*pPathArr)[nPath];
328 sName += INET_PATH_TOKEN;
329 sName += pGroup->sName.GetToken(0, GLOS_DELIM);
330 sName += sExt;
331
332 FStatHelper::GetModifiedDateTimeOfFile( sName,
333 &pGroup->aDateModified,
334 &pGroup->aDateModified );
335
336 aGroupArr.Insert( pGroup, i );
337 }
338 }
339 bFilled = sal_True;
340 }
341 else
342 {
343 for(sal_uInt16 nPath = 0; nPath < pPathArr->Count(); nPath++)
344 {
345 SvStringsDtor aFoundGroupNames;
346 SvStrings aFiles( 16, 16 );
347 SvPtrarr aDateTimeArr( 16, 16 );
348
349 SWUnoHelper::UCB_GetFileListOfFolder( *(*pPathArr)[nPath], aFiles,
350 &sExt, &aDateTimeArr );
351 for( sal_uInt16 nFiles = 0, nFEnd = aFiles.Count();
352 nFiles < nFEnd; ++nFiles )
353 {
354 String* pTitle = aFiles[ nFiles ];
355 ::DateTime* pDT = (::DateTime*) aDateTimeArr[ nFiles ];
356
357 String sName( pTitle->Copy( 0, pTitle->Len() - sExt.Len() ));
358
359 aFoundGroupNames.Insert( new String(sName),
360 aFoundGroupNames.Count());
361 sName += GLOS_DELIM;
362 sName += String::CreateFromInt32( nPath );
363 AutoTextGroup* pFound = FindGroup( sName );
364 if( !pFound )
365 {
366 pFound = new AutoTextGroup;
367 pFound->sName = sName;
368 FillGroup( pFound, pGlossaries );
369 pFound->aDateModified = *pDT;
370
371 aGroupArr.Insert(pFound, aGroupArr.Count());
372 }
373 else if( pFound->aDateModified < *pDT )
374 {
375 FillGroup(pFound, pGlossaries);
376 pFound->aDateModified = *pDT;
377 }
378
379 // don't need any more these pointers
380 delete pTitle;
381 delete pDT;
382 }
383
384 sal_uInt16 nArrCount = aGroupArr.Count();
385 for( sal_uInt16 i = nArrCount; i; --i)
386 {
387 // evtl. geloeschte Gruppen entfernen
388 AutoTextGroup* pGroup = aGroupArr.GetObject(i - 1);
389 sal_uInt16 nGroupPath = (sal_uInt16)pGroup->sName.GetToken( 1,
390 GLOS_DELIM).ToInt32();
391 // nur die Gruppen werden geprueft, die fuer den
392 // aktuellen Teilpfad registriert sind
393 if(nGroupPath == nPath)
394 {
395 sal_Bool bFound = sal_False;
396 String sCompareGroup = pGroup->sName.GetToken(0, GLOS_DELIM);
397 for( sal_uInt16 j = 0; j < aFoundGroupNames.Count() && !bFound; ++j)
398 {
399 bFound = sCompareGroup == *aFoundGroupNames[j];
400 }
401 if(!bFound)
402 {
403 aGroupArr.Remove(i - 1);
404 delete pGroup;
405 }
406 }
407 }
408 }
409 }
410 }
411
412 /********************************************************************
413
414 ********************************************************************/
415
416
Timeout()417 void SwGlossaryList::Timeout()
418 {
419 // nur, wenn eine SwView den Fokus hat, wird automatisch upgedated
420 if(::GetActiveView())
421 Update();
422 }
423
424 /********************************************************************
425
426 ********************************************************************/
427
428
FindGroup(const String & rGroupName)429 AutoTextGroup* SwGlossaryList::FindGroup(const String& rGroupName)
430 {
431 for(sal_uInt16 i = 0; i < aGroupArr.Count(); i++)
432 {
433 AutoTextGroup* pRet = aGroupArr.GetObject(i);
434 if(pRet->sName == rGroupName)
435 return pRet;
436 }
437 return 0;
438 }
439
440 /********************************************************************
441
442 ********************************************************************/
443
444
FillGroup(AutoTextGroup * pGroup,SwGlossaries * pGlossaries)445 void SwGlossaryList::FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGlossaries)
446 {
447 SwTextBlocks* pBlock = pGlossaries->GetGroupDoc(pGroup->sName);
448 pGroup->nCount = pBlock ? pBlock->GetCount() : 0;
449 pGroup->sLongNames = pGroup->sShortNames = aEmptyStr;
450 if(pBlock)
451 pGroup->sTitle = pBlock->GetName();
452
453 for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
454 {
455 pGroup->sLongNames += pBlock->GetLongName(j);
456 pGroup->sLongNames += STRING_DELIM;
457 pGroup->sShortNames += pBlock->GetShortName(j);
458 pGroup->sShortNames += STRING_DELIM;
459 }
460 pGlossaries->PutGroupDoc(pBlock);
461 }
462
463 /********************************************************************
464 Alle (nicht mehr als FIND_MAX_GLOS) gefunden Bausteine mit
465 passendem Anfang zurueckgeben
466 ********************************************************************/
467
HasLongName(const String & rBegin,SvStringsISortDtor * pLongNames)468 sal_Bool SwGlossaryList::HasLongName(const String& rBegin, SvStringsISortDtor* pLongNames )
469 {
470 if(!bFilled)
471 Update();
472 sal_uInt16 nFound = 0;
473 sal_uInt16 nCount = aGroupArr.Count();
474 sal_uInt16 nBeginLen = rBegin.Len();
475 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
476
477 for(sal_uInt16 i = 0; i < nCount; i++ )
478 {
479 AutoTextGroup* pGroup = aGroupArr.GetObject(i);
480 for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
481 {
482 String sBlock = pGroup->sLongNames.GetToken(j, STRING_DELIM);
483 if( rSCmp.isEqual( sBlock.Copy(0, nBeginLen), rBegin ) &&
484 nBeginLen + 1 < sBlock.Len())
485 {
486 String* pBlock = new String(sBlock);
487 pLongNames->Insert(pBlock);
488 nFound++;
489 if(FIND_MAX_GLOS == nFound)
490 break;
491 }
492 }
493 }
494 return nFound > 0;
495 }
496
497 /********************************************************************
498
499 ********************************************************************/
ClearGroups()500 void SwGlossaryList::ClearGroups()
501 {
502 sal_uInt16 nCount = aGroupArr.Count();
503 for( sal_uInt16 i = 0; i < nCount; ++i )
504 delete aGroupArr.GetObject( i );
505
506 aGroupArr.Remove( 0, nCount );
507 bFilled = sal_False;
508 }
509
510
511