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