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); 93 ListBox& GetListBox() {return aListLB;} 94 }; 95 96 /*-----------------21.01.97 13.25------------------- 97 98 --------------------------------------------------*/ 99 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 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 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 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 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 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 231 sal_uInt16 SwGlossaryList::GetGroupCount() 232 { 233 if(!bFilled) 234 Update(); 235 return aGroupArr.Count(); 236 } 237 238 /******************************************************************** 239 240 ********************************************************************/ 241 242 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 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 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 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 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 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 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 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 ********************************************************************/ 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