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