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_cui.hxx" 30 31 // include --------------------------------------------------------------- 32 33 #include <stdio.h> 34 35 #define _CUI_CHARMAP_CXX_ 36 #include <tools/shl.hxx> 37 #include <tools/debug.hxx> 38 #include <vcl/sound.hxx> 39 #include <vcl/svapp.hxx> 40 #include <vcl/msgbox.hxx> 41 #include <svtools/colorcfg.hxx> 42 #include <svl/eitem.hxx> 43 #include <svl/intitem.hxx> 44 #include <svl/stritem.hxx> 45 #include <svl/itempool.hxx> 46 47 #include <rtl/textenc.h> 48 #include <svx/ucsubset.hxx> 49 50 #include <cuires.hrc> 51 #include <dialmgr.hxx> 52 #include "cuicharmap.hxx" 53 #include <sfx2/request.hxx> 54 #include <sfx2/sfxsids.hrc> 55 #include <sfx2/app.hxx> 56 #include <editeng/fontitem.hxx> 57 #include "charmap.hrc" 58 #include "macroass.hxx" 59 60 // class SvxCharacterMap ================================================= 61 62 SvxCharacterMap::SvxCharacterMap( Window* pParent, sal_Bool bOne, const SfxItemSet* pSet ) : 63 SfxModalDialog( pParent, CUI_RES( RID_SVXDLG_CHARMAP ) ), 64 mpCharMapData( 0 ) 65 { 66 SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, FN_PARAM_1, sal_False ); 67 if ( pItem ) 68 bOne = pItem->GetValue(); 69 70 mpCharMapData = new SvxCharMapData( this, bOne, &CUI_MGR() ); 71 72 SFX_ITEMSET_ARG( pSet, pCharItem, SfxInt32Item, SID_ATTR_CHAR, sal_False ); 73 if ( pCharItem ) 74 SetChar( pCharItem->GetValue() ); 75 76 SFX_ITEMSET_ARG( pSet, pDisableItem, SfxBoolItem, FN_PARAM_2, sal_False ); 77 if ( pDisableItem && pDisableItem->GetValue() ) 78 DisableFontSelection(); 79 80 SFX_ITEMSET_ARG( pSet, pFontItem, SvxFontItem, SID_ATTR_CHAR_FONT, sal_False ); 81 SFX_ITEMSET_ARG( pSet, pFontNameItem, SfxStringItem, SID_FONT_NAME, sal_False ); 82 if ( pFontItem ) 83 { 84 Font aFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetSize() ); 85 aFont.SetCharSet( pFontItem->GetCharSet() ); 86 aFont.SetPitch( pFontItem->GetPitch() ); 87 SetCharFont( aFont ); 88 } 89 else if ( pFontNameItem ) 90 { 91 Font aFont( GetCharFont() ); 92 aFont.SetName( pFontNameItem->GetValue() ); 93 SetCharFont( aFont ); 94 } 95 96 FreeResource(); 97 CreateOutputItemSet( pSet ? *pSet->GetPool() : SFX_APP()->GetPool() ); 98 } 99 100 // ----------------------------------------------------------------------- 101 102 SvxCharacterMap::~SvxCharacterMap() 103 { 104 delete mpCharMapData; 105 } 106 107 // ----------------------------------------------------------------------- 108 109 const Font& SvxCharacterMap::GetCharFont() const 110 { 111 return mpCharMapData->aFont; 112 } 113 114 // ----------------------------------------------------------------------- 115 116 void SvxCharacterMap::SetChar( sal_UCS4 c ) 117 { 118 mpCharMapData->aShowSet.SelectCharacter( c ); 119 } 120 121 // ----------------------------------------------------------------------- 122 123 sal_UCS4 SvxCharacterMap::GetChar() const 124 { 125 return mpCharMapData->aShowSet.GetSelectCharacter(); 126 } 127 128 // ----------------------------------------------------------------------- 129 130 String SvxCharacterMap::GetCharacters() const 131 { 132 return mpCharMapData->aShowText.GetText(); 133 } 134 135 136 // ----------------------------------------------------------------------- 137 138 void SvxCharacterMap::DisableFontSelection() 139 { 140 mpCharMapData->aFontText.Disable(); 141 mpCharMapData->aFontLB.Disable(); 142 } 143 144 void SvxCharacterMap::SetCharFont( const Font& rFont ) 145 { 146 mpCharMapData->SetCharFont( rFont ); 147 } 148 149 short SvxCharacterMap::Execute() 150 { 151 short nResult = SfxModalDialog::Execute(); 152 if ( nResult == RET_OK ) 153 { 154 SfxItemSet* pSet = GetItemSet(); 155 if ( pSet ) 156 { 157 const SfxItemPool* pPool = pSet->GetPool(); 158 const Font& rFont( GetCharFont() ); 159 pSet->Put( SfxStringItem( pPool->GetWhich(SID_CHARMAP), GetCharacters() ) ); 160 pSet->Put( SvxFontItem( rFont.GetFamily(), rFont.GetName(), 161 rFont.GetStyleName(), rFont.GetPitch(), rFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) ); 162 pSet->Put( SfxStringItem( pPool->GetWhich(SID_FONT_NAME), rFont.GetName() ) ); 163 pSet->Put( SfxInt32Item( pPool->GetWhich(SID_ATTR_CHAR), GetChar() ) ); 164 } 165 } 166 167 return nResult; 168 } 169 170 171 // class SvxShowText ===================================================== 172 173 SvxShowText::SvxShowText( Window* pParent, const ResId& rResId, sal_Bool bCenter ) 174 : Control( pParent, rResId ), 175 mbCenter( bCenter) 176 {} 177 178 // ----------------------------------------------------------------------- 179 180 void SvxShowText::Paint( const Rectangle& ) 181 { 182 Color aTextCol = GetTextColor(); 183 184 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 185 const Color aWindowTextColor( rStyleSettings.GetDialogTextColor() ); 186 SetTextColor( aWindowTextColor ); 187 188 const String aText = GetText(); 189 const Size aSize = GetOutputSizePixel(); 190 Point aPoint( 2, mnY ); 191 192 // adjust position using ink boundary if possible 193 Rectangle aBoundRect; 194 if( !GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty() ) 195 aPoint.X() = (aSize.Width() - GetTextWidth( aText )) / 2; 196 else 197 { 198 // adjust position before it gets out of bounds 199 aBoundRect += aPoint; 200 201 // shift back vertically if needed 202 int nYLDelta = aBoundRect.Top(); 203 int nYHDelta = aSize.Height() - aBoundRect.Bottom(); 204 if( nYLDelta <= 0 ) 205 aPoint.Y() -= nYLDelta - 1; 206 else if( nYHDelta <= 0 ) 207 aPoint.Y() += nYHDelta - 1; 208 209 if( mbCenter ) 210 { 211 // move glyph to middle of cell 212 aPoint.X() = -aBoundRect.Left() 213 + (aSize.Width() - aBoundRect.GetWidth()) / 2; 214 } 215 else 216 { 217 // shift back horizontally if needed 218 int nXLDelta = aBoundRect.Left(); 219 int nXHDelta = aSize.Width() - aBoundRect.Right(); 220 if( nXLDelta <= 0 ) 221 aPoint.X() -= nXLDelta - 1; 222 else if( nXHDelta <= 0 ) 223 aPoint.X() += nXHDelta - 1; 224 } 225 } 226 227 DrawText( aPoint, aText ); 228 SetTextColor( aTextCol ); 229 } 230 231 // ----------------------------------------------------------------------- 232 233 void SvxShowText::SetFont( const Font& rFont ) 234 { 235 long nWinHeight = GetOutputSizePixel().Height(); 236 Font aFont = rFont; 237 aFont.SetWeight( WEIGHT_NORMAL ); 238 aFont.SetAlign( ALIGN_TOP ); 239 aFont.SetSize( PixelToLogic( Size( 0, nWinHeight/2 ) ) ); 240 aFont.SetTransparent( sal_True ); 241 Control::SetFont( aFont ); 242 mnY = ( nWinHeight - GetTextHeight() ) / 2; 243 244 Invalidate(); 245 } 246 247 // ----------------------------------------------------------------------- 248 249 void SvxShowText::SetText( const String& rText ) 250 { 251 Control::SetText( rText ); 252 Invalidate(); 253 } 254 255 // ----------------------------------------------------------------------- 256 257 SvxShowText::~SvxShowText() 258 {} 259 260 // class SvxCharacterMap ================================================= 261 262 SvxCharMapData::SvxCharMapData( SfxModalDialog* pDialog, sal_Bool bOne_, ResMgr* pResContext ) 263 : mpDialog( pDialog ), 264 aShowSet ( pDialog, ResId( CT_SHOWSET, *pResContext ) ), 265 aShowText ( pDialog, ResId( CT_SHOWTEXT, *pResContext ) ), 266 // aShowShortcut ( pDialog, ResId( CT_ASSIGN, *pResContext ) ), 267 aOKBtn ( pDialog, ResId( BTN_CHAR_OK, *pResContext ) ), 268 aCancelBtn ( pDialog, ResId( BTN_CHAR_CANCEL, *pResContext ) ), 269 aHelpBtn ( pDialog, ResId( BTN_CHAR_HELP, *pResContext ) ), 270 aDeleteBtn ( pDialog, ResId( BTN_DELETE, *pResContext ) ), 271 // aAssignBtn ( pDialog, ResId( BT_ASSIGN, *pResContext ) ), 272 aFontText ( pDialog, ResId( FT_FONT, *pResContext ) ), 273 aFontLB ( pDialog, ResId( LB_FONT, *pResContext ) ), 274 aSubsetText ( pDialog, ResId( FT_SUBSET, *pResContext ) ), 275 aSubsetLB ( pDialog, ResId( LB_SUBSET, *pResContext ) ), 276 aSymbolText ( pDialog, ResId( FT_SYMBOLE, *pResContext ) ), 277 aShowChar ( pDialog, ResId( CT_SHOWCHAR, *pResContext ), sal_True ), 278 aCharCodeText ( pDialog, ResId( FT_CHARCODE, *pResContext ) ), 279 // aAssignText ( pDialog, ResId( FT_ASSIGN, *pResContext ) ), 280 bOne( bOne_ ), 281 pSubsetMap( NULL ) 282 { 283 aFont = pDialog->GetFont(); 284 aFont.SetTransparent( sal_True ); 285 aFont.SetFamily( FAMILY_DONTKNOW ); 286 aFont.SetPitch( PITCH_DONTKNOW ); 287 aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW ); 288 289 if ( bOne ) 290 { 291 Size aDlgSize = pDialog->GetSizePixel(); 292 pDialog->SetSizePixel( Size( aDlgSize.Width(), 293 aDlgSize.Height()-aShowText.GetSizePixel().Height() ) ); 294 aSymbolText.Hide(); 295 aShowText.Hide(); 296 aDeleteBtn.Hide(); 297 } 298 299 String aDefStr( aFont.GetName() ); 300 String aLastName; 301 int nCount = mpDialog->GetDevFontCount(); 302 for ( int i = 0; i < nCount; i++ ) 303 { 304 String aFontName( mpDialog->GetDevFont( i ).GetName() ); 305 if ( aFontName != aLastName ) 306 { 307 aLastName = aFontName; 308 sal_uInt16 nPos = aFontLB.InsertEntry( aFontName ); 309 aFontLB.SetEntryData( nPos, (void*)(sal_uLong)i ); 310 } 311 } 312 // the font may not be in the list => 313 // try to find a font name token in list and select found font, 314 // else select topmost entry 315 FASTBOOL bFound = (aFontLB.GetEntryPos( aDefStr ) == LISTBOX_ENTRY_NOTFOUND ); 316 if( !bFound ) 317 { 318 for ( xub_StrLen i = 0; i < aDefStr.GetTokenCount(); ++i ) 319 { 320 String aToken = aDefStr.GetToken(i); 321 if ( aFontLB.GetEntryPos( aToken ) != LISTBOX_ENTRY_NOTFOUND ) 322 { 323 aDefStr = aToken; 324 bFound = sal_True; 325 break; 326 } 327 } 328 } 329 330 if ( bFound ) 331 aFontLB.SelectEntry( aDefStr ); 332 else if ( aFontLB.GetEntryCount() ) 333 aFontLB.SelectEntryPos(0); 334 FontSelectHdl( &aFontLB ); 335 336 aOKBtn.SetClickHdl( LINK( this, SvxCharMapData, OKHdl ) ); 337 aFontLB.SetSelectHdl( LINK( this, SvxCharMapData, FontSelectHdl ) ); 338 aSubsetLB.SetSelectHdl( LINK( this, SvxCharMapData, SubsetSelectHdl ) ); 339 aShowSet.SetDoubleClickHdl( LINK( this, SvxCharMapData, CharDoubleClickHdl ) ); 340 aShowSet.SetSelectHdl( LINK( this, SvxCharMapData, CharSelectHdl ) ); 341 aShowSet.SetHighlightHdl( LINK( this, SvxCharMapData, CharHighlightHdl ) ); 342 aShowSet.SetPreSelectHdl( LINK( this, SvxCharMapData, CharPreSelectHdl ) ); 343 aDeleteBtn.SetClickHdl( LINK( this, SvxCharMapData, DeleteHdl ) ); 344 // aAssignBtn.SetClickHdl( LINK( this, SvxCharMapData, AssignHdl ) ); 345 346 if( SvxShowCharSet::getSelectedChar() == ' ') 347 aOKBtn.Disable(); 348 else 349 aOKBtn.Enable(); 350 351 // left align aShowText field 352 int nLeftEdge = aSymbolText.GetPosPixel().X(); 353 nLeftEdge += aSymbolText.GetTextWidth( aSymbolText.GetText() ); 354 Size aNewSize = aShowText.GetOutputSizePixel(); 355 aShowText.SetPosPixel( Point( nLeftEdge+4, aShowText.GetPosPixel().Y() ) ); 356 } 357 358 // ----------------------------------------------------------------------- 359 360 void SvxCharMapData::SetCharFont( const Font& rFont ) 361 { 362 // first get the underlying info in order to get font names 363 // like "Times New Roman;Times" resolved 364 Font aTmp( mpDialog->GetFontMetric( rFont ) ); 365 366 if ( aFontLB.GetEntryPos( aTmp.GetName() ) == LISTBOX_ENTRY_NOTFOUND ) 367 return; 368 369 aFontLB.SelectEntry( aTmp.GetName() ); 370 aFont = aTmp; 371 FontSelectHdl( &aFontLB ); 372 373 // for compatibility reasons 374 mpDialog->ModalDialog::SetFont( aFont ); 375 } 376 377 // ----------------------------------------------------------------------- 378 379 IMPL_LINK( SvxCharMapData, OKHdl, OKButton *, EMPTYARG ) 380 { 381 String aStr = aShowText.GetText(); 382 383 if ( !aStr.Len() ) 384 { 385 sal_UCS4 cChar = aShowSet.GetSelectCharacter(); 386 // using the new UCS4 constructor 387 rtl::OUString aOUStr( &cChar, 1 ); 388 aShowText.SetText( aOUStr ); 389 } 390 mpDialog->EndDialog( sal_True ); 391 return 0; 392 } 393 394 // ----------------------------------------------------------------------- 395 396 IMPL_LINK( SvxCharMapData, FontSelectHdl, ListBox *, EMPTYARG ) 397 { 398 sal_uInt16 nPos = aFontLB.GetSelectEntryPos(), 399 nFont = (sal_uInt16)(sal_uLong)aFontLB.GetEntryData( nPos ); 400 aFont = mpDialog->GetDevFont( nFont ); 401 aFont.SetWeight( WEIGHT_DONTKNOW ); 402 aFont.SetItalic( ITALIC_NONE ); 403 aFont.SetWidthType( WIDTH_DONTKNOW ); 404 aFont.SetPitch( PITCH_DONTKNOW ); 405 aFont.SetFamily( FAMILY_DONTKNOW ); 406 407 // notify children using this font 408 aShowSet.SetFont( aFont ); 409 aShowChar.SetFont( aFont ); 410 aShowText.SetFont( aFont ); 411 412 // right align some fields to aShowSet 413 int nRightEdge = aShowSet.GetPosPixel().X() + aShowSet.GetOutputSizePixel().Width(); 414 Size aNewSize = aSubsetLB.GetOutputSizePixel(); 415 aNewSize.setWidth( nRightEdge - aSubsetLB.GetPosPixel().X() ); 416 aSubsetLB.SetOutputSizePixel( aNewSize ); 417 418 // setup unicode subset listbar with font specific subsets, 419 // hide unicode subset listbar for symbol fonts 420 // TODO: get info from the Font once it provides it 421 if( pSubsetMap) 422 delete pSubsetMap; 423 pSubsetMap = NULL; 424 425 sal_Bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL); 426 if( bNeedSubset ) 427 { 428 FontCharMap aFontCharMap; 429 aShowSet.GetFontCharMap( aFontCharMap ); 430 pSubsetMap = new SubsetMap( &aFontCharMap ); 431 432 // update subset listbox for new font's unicode subsets 433 aSubsetLB.Clear(); 434 // TODO: is it worth to improve the stupid linear search? 435 bool bFirst = true; 436 const Subset* s; 437 while( NULL != (s = pSubsetMap->GetNextSubset( bFirst )) ) 438 { 439 sal_uInt16 nPos_ = aSubsetLB.InsertEntry( s->GetName() ); 440 aSubsetLB.SetEntryData( nPos_, (void*)s ); 441 // NOTE: subset must live at least as long as the selected font 442 if( bFirst ) 443 aSubsetLB.SelectEntryPos( nPos_ ); 444 bFirst = false; 445 } 446 if( aSubsetLB.GetEntryCount() <= 1 ) 447 bNeedSubset = sal_False; 448 } 449 450 aSubsetText.Show( bNeedSubset); 451 aSubsetLB.Show( bNeedSubset); 452 453 return 0; 454 } 455 456 // ----------------------------------------------------------------------- 457 458 IMPL_LINK( SvxCharMapData, SubsetSelectHdl, ListBox *, EMPTYARG ) 459 { 460 sal_uInt16 nPos = aSubsetLB.GetSelectEntryPos(); 461 const Subset* pSubset = reinterpret_cast<const Subset*> (aSubsetLB.GetEntryData(nPos)); 462 if( pSubset ) 463 { 464 sal_UCS4 cFirst = pSubset->GetRangeMin(); 465 aShowSet.SelectCharacter( cFirst ); 466 } 467 aSubsetLB.SelectEntryPos( nPos ); 468 return 0; 469 } 470 471 // ----------------------------------------------------------------------- 472 473 IMPL_LINK( SvxCharMapData, CharDoubleClickHdl, Control *, EMPTYARG ) 474 { 475 mpDialog->EndDialog( sal_True ); 476 return 0; 477 } 478 479 // ----------------------------------------------------------------------- 480 481 IMPL_LINK( SvxCharMapData, CharSelectHdl, Control *, EMPTYARG ) 482 { 483 if ( !bOne ) 484 { 485 String aText = aShowText.GetText(); 486 487 if ( aText.Len() == CHARMAP_MAXLEN ) 488 Sound::Beep( SOUND_WARNING ); 489 else 490 { 491 sal_UCS4 cChar = aShowSet.GetSelectCharacter(); 492 // using the new UCS4 constructor 493 rtl::OUString aOUStr( &cChar, 1 ); 494 aShowText.SetText( aText + aOUStr ); 495 } 496 497 } 498 aOKBtn.Enable(); 499 return 0; 500 } 501 502 // ----------------------------------------------------------------------- 503 504 IMPL_LINK( SvxCharMapData, CharHighlightHdl, Control *, EMPTYARG ) 505 { 506 String aText; 507 sal_UCS4 cChar = aShowSet.GetSelectCharacter(); 508 sal_Bool bSelect = (cChar > 0); 509 510 // show char sample 511 if ( bSelect ) 512 { 513 // using the new UCS4 constructor 514 aText = rtl::OUString( &cChar, 1 ); 515 516 const Subset* pSubset = NULL; 517 if( pSubsetMap ) 518 pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); 519 if( pSubset ) 520 aSubsetLB.SelectEntry( pSubset->GetName() ); 521 else 522 aSubsetLB.SetNoSelection(); 523 } 524 aShowChar.SetText( aText ); 525 aShowChar.Update(); 526 527 // show char code 528 if ( bSelect ) 529 { 530 char aBuf[32]; 531 snprintf( aBuf, sizeof(aBuf), "U+%04X", static_cast<unsigned>(cChar) ); 532 if( cChar < 0x0100 ) 533 snprintf( aBuf+6, sizeof(aBuf)-6, " (%u)", static_cast<unsigned>(cChar) ); 534 aText = String::CreateFromAscii( aBuf ); 535 } 536 aCharCodeText.SetText( aText ); 537 538 return 0; 539 } 540 541 // ----------------------------------------------------------------------- 542 543 IMPL_LINK( SvxCharMapData, CharPreSelectHdl, Control *, EMPTYARG ) 544 { 545 // adjust subset selection 546 if( pSubsetMap ) 547 { 548 sal_UCS4 cChar = aShowSet.GetSelectCharacter(); 549 const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); 550 if( pSubset ) 551 aSubsetLB.SelectEntry( pSubset->GetName() ); 552 } 553 554 aOKBtn.Enable(); 555 return 0; 556 } 557 558 // ----------------------------------------------------------------------- 559 560 IMPL_LINK( SvxCharMapData, DeleteHdl, PushButton *, EMPTYARG ) 561 { 562 aShowText.SetText( String() ); 563 aOKBtn.Disable(); 564 return 0; 565 } 566 567 #include <sfx2/objsh.hxx> 568 #include <vcl/msgbox.hxx> 569 #include <svl/stritem.hxx> 570 571 IMPL_LINK( SvxCharMapData, AssignHdl, PushButton *, EMPTYARG ) 572 { 573 SfxAllItemSet aSet( SfxObjectShell::Current()->GetPool() ); 574 aSet.Put( SfxStringItem( SID_CHARMAP, String::CreateFromAscii("test") ) ); 575 SfxModalDialog* pDlg = new SfxMacroAssignDlg( mpDialog, com::sun::star::uno::Reference < com::sun::star::frame::XFrame >(), aSet ); 576 if ( pDlg && pDlg->Execute() == RET_OK ) 577 { 578 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); 579 const SfxPoolItem* pItem; 580 if( SFX_ITEM_SET == pOutSet->GetItemState( SID_CHARMAP, sal_False, &pItem ) ) 581 { 582 // show assigned shortcut 583 } 584 } 585 586 delete pDlg; 587 588 return 0; 589 } 590