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_svx.hxx" 30 31 // include --------------------------------------------------------------- 32 33 #include <stdio.h> 34 35 #define _SVX_CHARMAP_CXX_ 36 #include <vcl/svapp.hxx> 37 #include <svtools/colorcfg.hxx> 38 39 #include <rtl/textenc.h> 40 #include <svx/ucsubset.hxx> 41 42 #include <svx/dialogs.hrc> 43 44 #include <svx/charmap.hxx> 45 #include <svx/dialmgr.hxx> 46 #include <svx/svxdlg.hxx> 47 48 #include "charmapacc.hxx" 49 #include <com/sun/star/accessibility/AccessibleEventObject.hpp> 50 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 51 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 52 #include <comphelper/types.hxx> 53 #include <svl/itemset.hxx> 54 55 #include "rtl/ustrbuf.hxx" 56 57 using namespace ::com::sun::star::accessibility; 58 using namespace ::com::sun::star::uno; 59 using namespace ::com::sun::star; 60 61 // ----------------------------------------------------------------------- 62 sal_uInt32& SvxShowCharSet::getSelectedChar() 63 { 64 static sal_uInt32 cSelectedChar = ' '; // keeps selected character over app livetime 65 return cSelectedChar; 66 } 67 68 // class SvxShowCharSet ================================================== 69 70 #define SBWIDTH 16 71 72 SvxShowCharSet::SvxShowCharSet( Window* pParent, const ResId& rResId ) : 73 Control( pParent, rResId ) 74 ,m_pAccessible(NULL) 75 ,aVscrollSB( this, WB_VERT) 76 { 77 nSelectedIndex = -1; // TODO: move into init list when it is no longer static 78 79 aOrigSize = GetOutputSizePixel(); 80 aOrigPos = GetPosPixel(); 81 82 SetStyle( GetStyle() | WB_CLIPCHILDREN ); 83 aVscrollSB.SetScrollHdl( LINK( this, SvxShowCharSet, VscrollHdl ) ); 84 aVscrollSB.EnableDrag( sal_True ); 85 // other settings like aVscroll depend on selected font => see SetFont 86 87 bDrag = sal_False; 88 InitSettings( sal_True, sal_True ); 89 } 90 91 // ----------------------------------------------------------------------- 92 93 void SvxShowCharSet::GetFocus() 94 { 95 Control::GetFocus(); 96 SelectIndex( nSelectedIndex, sal_True ); 97 } 98 99 // ----------------------------------------------------------------------- 100 101 void SvxShowCharSet::LoseFocus() 102 { 103 Control::LoseFocus(); 104 SelectIndex( nSelectedIndex, sal_False ); 105 } 106 107 // ----------------------------------------------------------------------- 108 109 void SvxShowCharSet::StateChanged( StateChangedType nType ) 110 { 111 if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 112 InitSettings( sal_True, sal_False ); 113 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 114 InitSettings( sal_False, sal_True ); 115 116 Control::StateChanged( nType ); 117 } 118 119 // ----------------------------------------------------------------------- 120 121 void SvxShowCharSet::DataChanged( const DataChangedEvent& rDCEvt ) 122 { 123 if ( ( rDCEvt.GetType() == DATACHANGED_SETTINGS ) 124 && ( rDCEvt.GetFlags() & SETTINGS_STYLE ) ) 125 InitSettings( sal_True, sal_True ); 126 else 127 Control::DataChanged( rDCEvt ); 128 } 129 130 // ----------------------------------------------------------------------- 131 132 void SvxShowCharSet::MouseButtonDown( const MouseEvent& rMEvt ) 133 { 134 if ( rMEvt.IsLeft() ) 135 { 136 if ( rMEvt.GetClicks() == 1 ) 137 { 138 GrabFocus(); 139 bDrag = sal_True; 140 CaptureMouse(); 141 142 int nIndex = PixelToMapIndex( rMEvt.GetPosPixel() ); 143 SelectIndex( nIndex ); 144 } 145 146 if ( !(rMEvt.GetClicks() % 2) ) 147 aDoubleClkHdl.Call( this ); 148 } 149 } 150 151 // ----------------------------------------------------------------------- 152 153 void SvxShowCharSet::MouseButtonUp( const MouseEvent& rMEvt ) 154 { 155 if ( bDrag && rMEvt.IsLeft() ) 156 { 157 // released mouse over character map 158 if ( Rectangle(Point(), GetOutputSize()).IsInside(rMEvt.GetPosPixel())) 159 aSelectHdl.Call( this ); 160 ReleaseMouse(); 161 bDrag = sal_False; 162 } 163 } 164 165 // ----------------------------------------------------------------------- 166 167 void SvxShowCharSet::MouseMove( const MouseEvent& rMEvt ) 168 { 169 if ( rMEvt.IsLeft() && bDrag ) 170 { 171 Point aPos = rMEvt.GetPosPixel(); 172 Size aSize = GetSizePixel(); 173 174 if ( aPos.X() < 0 ) 175 aPos.X() = 0; 176 else if ( aPos.X() > aSize.Width()-5 ) 177 aPos.X() = aSize.Width()-5; 178 if ( aPos.Y() < 0 ) 179 aPos.Y() = 0; 180 else if ( aPos.Y() > aSize.Height()-5 ) 181 aPos.Y() = aSize.Height()-5; 182 183 int nIndex = PixelToMapIndex( aPos ); 184 SelectIndex( nIndex ); 185 } 186 } 187 188 // ----------------------------------------------------------------------- 189 190 void SvxShowCharSet::Command( const CommandEvent& rCEvt ) 191 { 192 if( !HandleScrollCommand( rCEvt, 0, &aVscrollSB ) ) 193 Control::Command( rCEvt ); 194 } 195 196 // ----------------------------------------------------------------------------- 197 198 sal_uInt16 SvxShowCharSet::GetRowPos(sal_uInt16 _nPos) const 199 { 200 return _nPos / COLUMN_COUNT ; 201 } 202 203 // ----------------------------------------------------------------------------- 204 205 sal_uInt16 SvxShowCharSet::GetColumnPos(sal_uInt16 _nPos) const 206 { 207 return _nPos % COLUMN_COUNT ; 208 } 209 210 // ----------------------------------------------------------------------- 211 212 int SvxShowCharSet::FirstInView( void ) const 213 { 214 int nIndex = 0; 215 if( aVscrollSB.IsVisible() ) 216 nIndex += aVscrollSB.GetThumbPos() * COLUMN_COUNT; 217 return nIndex; 218 } 219 220 // ----------------------------------------------------------------------- 221 222 int SvxShowCharSet::LastInView( void ) const 223 { 224 sal_uIntPtr nIndex = FirstInView(); 225 nIndex += ROW_COUNT * COLUMN_COUNT - 1; 226 sal_uIntPtr nCompare = sal::static_int_cast<sal_uIntPtr>( maFontCharMap.GetCharCount() - 1 ); 227 if( nIndex > nCompare ) 228 nIndex = nCompare; 229 return nIndex; 230 } 231 232 // ----------------------------------------------------------------------- 233 234 inline Point SvxShowCharSet::MapIndexToPixel( int nIndex ) const 235 { 236 const int nBase = FirstInView(); 237 int x = ((nIndex - nBase) % COLUMN_COUNT) * nX; 238 int y = ((nIndex - nBase) / COLUMN_COUNT) * nY; 239 return Point( x, y ); 240 } 241 // ----------------------------------------------------------------------------- 242 243 int SvxShowCharSet::PixelToMapIndex( const Point& point) const 244 { 245 int nBase = FirstInView(); 246 return (nBase + (point.X()/nX) + (point.Y()/nY) * COLUMN_COUNT); 247 } 248 249 // ----------------------------------------------------------------------- 250 251 void SvxShowCharSet::KeyInput( const KeyEvent& rKEvt ) 252 { 253 KeyCode aCode = rKEvt.GetKeyCode(); 254 255 if( aCode.GetModifier() ) 256 { 257 Control::KeyInput( rKEvt ); 258 return; 259 } 260 261 int tmpSelected = nSelectedIndex; 262 263 switch ( aCode.GetCode() ) 264 { 265 case KEY_SPACE: 266 aSelectHdl.Call( this ); 267 break; 268 case KEY_LEFT: 269 --tmpSelected; 270 break; 271 case KEY_RIGHT: 272 ++tmpSelected; 273 break; 274 case KEY_UP: 275 tmpSelected -= COLUMN_COUNT; 276 break; 277 case KEY_DOWN: 278 tmpSelected += COLUMN_COUNT; 279 break; 280 case KEY_PAGEUP: 281 tmpSelected -= ROW_COUNT * COLUMN_COUNT; 282 break; 283 case KEY_PAGEDOWN: 284 tmpSelected += ROW_COUNT * COLUMN_COUNT; 285 break; 286 case KEY_HOME: 287 tmpSelected = 0; 288 break; 289 case KEY_END: 290 tmpSelected = maFontCharMap.GetCharCount() - 1; 291 break; 292 case KEY_TAB: // some fonts have a character at these unicode control codes 293 case KEY_ESCAPE: 294 case KEY_RETURN: 295 Control::KeyInput( rKEvt ); 296 tmpSelected = - 1; // mark as invalid 297 break; 298 default: 299 { 300 sal_UCS4 cChar = rKEvt.GetCharCode(); 301 sal_UCS4 cNext = maFontCharMap.GetNextChar( cChar - 1 ); 302 tmpSelected = maFontCharMap.GetIndexFromChar( cNext ); 303 if( tmpSelected < 0 || (cChar != cNext) ) 304 { 305 Control::KeyInput( rKEvt ); 306 tmpSelected = - 1; // mark as invalid 307 } 308 } 309 } 310 311 if ( tmpSelected >= 0 ) 312 { 313 SelectIndex( tmpSelected, sal_True ); 314 aPreSelectHdl.Call( this ); 315 } 316 } 317 318 // ----------------------------------------------------------------------- 319 320 void SvxShowCharSet::Paint( const Rectangle& ) 321 { 322 DrawChars_Impl( FirstInView(), LastInView() ); 323 } 324 // ----------------------------------------------------------------------------- 325 void SvxShowCharSet::DeSelect() 326 { 327 DrawChars_Impl(nSelectedIndex,nSelectedIndex); 328 } 329 // ----------------------------------------------------------------------- 330 331 void SvxShowCharSet::DrawChars_Impl( int n1, int n2 ) 332 { 333 if( n1 > LastInView() || n2 < FirstInView() ) 334 return; 335 336 Size aOutputSize = GetOutputSizePixel(); 337 if( aVscrollSB.IsVisible() ) 338 aOutputSize.setWidth( aOutputSize.Width() - SBWIDTH ); 339 340 int i; 341 for ( i = 1; i < COLUMN_COUNT; ++i ) 342 DrawLine( Point( nX * i, 0 ), Point( nX * i, aOutputSize.Height() ) ); 343 for ( i = 1; i < ROW_COUNT; ++i ) 344 DrawLine( Point( 0, nY * i ), Point( aOutputSize.Width(), nY * i ) ); 345 346 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 347 const Color aWindowTextColor( rStyleSettings.GetFieldTextColor() ); 348 Color aHighlightColor( rStyleSettings.GetHighlightColor() ); 349 Color aHighlightTextColor( rStyleSettings.GetHighlightTextColor() ); 350 Color aFaceColor( rStyleSettings.GetFaceColor() ); 351 Color aLightColor( rStyleSettings.GetLightColor() ); 352 Color aShadowColor( rStyleSettings.GetShadowColor() ); 353 354 int nTextHeight = GetTextHeight(); 355 Rectangle aBoundRect; 356 for( i = n1; i <= n2; ++i ) 357 { 358 Point pix = MapIndexToPixel( i ); 359 int x = pix.X(); 360 int y = pix.Y(); 361 362 rtl::OUStringBuffer buf; 363 buf.appendUtf32( maFontCharMap.GetCharFromIndex( i ) ); 364 String aCharStr(buf.makeStringAndClear()); 365 int nTextWidth = GetTextWidth(aCharStr); 366 int tx = x + (nX - nTextWidth + 1) / 2; 367 int ty = y + (nY - nTextHeight + 1) / 2; 368 Point aPointTxTy( tx, ty ); 369 370 // adjust position before it gets out of bounds 371 if( GetTextBoundRect( aBoundRect, aCharStr ) && !aBoundRect.IsEmpty() ) 372 { 373 // zero advance width => use ink width to center glyph 374 if( !nTextWidth ) 375 { 376 aPointTxTy.X() = x - aBoundRect.Left() 377 + (nX - aBoundRect.GetWidth() + 1) / 2; 378 } 379 380 aBoundRect += aPointTxTy; 381 382 // shift back vertically if needed 383 int nYLDelta = aBoundRect.Top() - y; 384 int nYHDelta = (y + nY) - aBoundRect.Bottom(); 385 if( nYLDelta <= 0 ) 386 aPointTxTy.Y() -= nYLDelta - 1; 387 else if( nYHDelta <= 0 ) 388 aPointTxTy.Y() += nYHDelta - 1; 389 390 // shift back horizontally if needed 391 int nXLDelta = aBoundRect.Left() - x; 392 int nXHDelta = (x + nX) - aBoundRect.Right(); 393 if( nXLDelta <= 0 ) 394 aPointTxTy.X() -= nXLDelta - 1; 395 else if( nXHDelta <= 0 ) 396 aPointTxTy.X() += nXHDelta - 1; 397 } 398 399 Color aTextCol = GetTextColor(); 400 if ( i != nSelectedIndex ) 401 { 402 SetTextColor( aWindowTextColor ); 403 DrawText( aPointTxTy, aCharStr ); 404 } 405 else 406 { 407 Color aLineCol = GetLineColor(); 408 Color aFillCol = GetFillColor(); 409 SetLineColor(); 410 Point aPointUL( x + 1, y + 1 ); 411 if( HasFocus() ) 412 { 413 SetFillColor( aHighlightColor ); 414 DrawRect( Rectangle( aPointUL, Size(nX-1,nY-1) ) ); 415 416 SetTextColor( aHighlightTextColor ); 417 DrawText( aPointTxTy, aCharStr ); 418 } 419 else 420 { 421 SetFillColor( aFaceColor ); 422 DrawRect( Rectangle( aPointUL, Size( nX-1, nY-1) ) ); 423 424 SetLineColor( aLightColor ); 425 DrawLine( aPointUL, Point( x+nX-1, y+1) ); 426 DrawLine( aPointUL, Point( x+1, y+nY-1) ); 427 428 SetLineColor( aShadowColor ); 429 DrawLine( Point( x+1, y+nY-1), Point( x+nX-1, y+nY-1) ); 430 DrawLine( Point( x+nX-1, y+nY-1), Point( x+nX-1, y+1) ); 431 432 DrawText( aPointTxTy, aCharStr ); 433 } 434 SetLineColor( aLineCol ); 435 SetFillColor( aFillCol ); 436 } 437 SetTextColor( aTextCol ); 438 } 439 } 440 441 // ----------------------------------------------------------------------- 442 443 void SvxShowCharSet::InitSettings( sal_Bool bForeground, sal_Bool bBackground ) 444 { 445 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); 446 447 if ( bForeground ) 448 { 449 Color aTextColor( rStyleSettings.GetDialogTextColor() ); 450 451 if ( IsControlForeground() ) 452 aTextColor = GetControlForeground(); 453 SetTextColor( aTextColor ); 454 } 455 456 if ( bBackground ) 457 { 458 if ( IsControlBackground() ) 459 SetBackground( GetControlBackground() ); 460 else 461 SetBackground( rStyleSettings.GetWindowColor() ); 462 } 463 464 Invalidate(); 465 } 466 467 // ----------------------------------------------------------------------- 468 469 sal_UCS4 SvxShowCharSet::GetSelectCharacter() const 470 { 471 if( nSelectedIndex >= 0 ) 472 getSelectedChar() = maFontCharMap.GetCharFromIndex( nSelectedIndex ); 473 return getSelectedChar(); 474 } 475 476 // ----------------------------------------------------------------------- 477 478 void SvxShowCharSet::SetFont( const Font& rFont ) 479 { 480 // save last selected unicode 481 if( nSelectedIndex >= 0 ) 482 getSelectedChar() = maFontCharMap.GetCharFromIndex( nSelectedIndex ); 483 484 Font aFont = rFont; 485 aFont.SetWeight( WEIGHT_LIGHT ); 486 aFont.SetAlign( ALIGN_TOP ); 487 int nFontHeight = (aOrigSize.Height() - 5) * 2 / (3 * ROW_COUNT); 488 aFont.SetSize( PixelToLogic( Size( 0, nFontHeight ) ) ); 489 aFont.SetTransparent( sal_True ); 490 Control::SetFont( aFont ); 491 GetFontCharMap( maFontCharMap ); 492 493 // hide scrollbar when there is nothing to scroll 494 sal_Bool bNeedVscroll = (maFontCharMap.GetCharCount() > ROW_COUNT*COLUMN_COUNT); 495 496 nX = (aOrigSize.Width() - (bNeedVscroll ? SBWIDTH : 0)) / COLUMN_COUNT; 497 nY = aOrigSize.Height() / ROW_COUNT; 498 499 if( bNeedVscroll) 500 { 501 aVscrollSB.SetPosSizePixel( nX * COLUMN_COUNT, 0, SBWIDTH, nY * ROW_COUNT ); 502 aVscrollSB.SetRangeMin( 0 ); 503 int nLastRow = (maFontCharMap.GetCharCount() - 1 + COLUMN_COUNT) / COLUMN_COUNT; 504 aVscrollSB.SetRangeMax( nLastRow ); 505 aVscrollSB.SetPageSize( ROW_COUNT-1 ); 506 aVscrollSB.SetVisibleSize( ROW_COUNT ); 507 } 508 509 // restore last selected unicode 510 int nMapIndex = maFontCharMap.GetIndexFromChar( getSelectedChar() ); 511 SelectIndex( nMapIndex ); 512 513 // rearrange CharSet element in sync with nX- and nY-multiples 514 Size aNewSize( nX * COLUMN_COUNT + (bNeedVscroll ? SBWIDTH : 0), nY * ROW_COUNT ); 515 Point aNewPos = aOrigPos + Point( (aOrigSize.Width() - aNewSize.Width()) / 2, 0 ); 516 SetPosPixel( aNewPos ); 517 SetOutputSizePixel( aNewSize ); 518 519 aVscrollSB.Show( bNeedVscroll ); 520 Invalidate(); 521 } 522 523 // ----------------------------------------------------------------------- 524 525 void SvxShowCharSet::SelectIndex( int nNewIndex, sal_Bool bFocus ) 526 { 527 if( nNewIndex < 0 ) 528 { 529 // need to scroll see closest unicode 530 sal_uInt32 cPrev = maFontCharMap.GetPrevChar( getSelectedChar() ); 531 int nMapIndex = maFontCharMap.GetIndexFromChar( cPrev ); 532 int nNewPos = nMapIndex / COLUMN_COUNT; 533 aVscrollSB.SetThumbPos( nNewPos ); 534 nSelectedIndex = bFocus ? nMapIndex+1 : -1; 535 Invalidate(); 536 Update(); 537 } 538 else if( nNewIndex < FirstInView() ) 539 { 540 // need to scroll up to see selected item 541 int nOldPos = aVscrollSB.GetThumbPos(); 542 int nDelta = (FirstInView() - nNewIndex + COLUMN_COUNT-1) / COLUMN_COUNT; 543 aVscrollSB.SetThumbPos( nOldPos - nDelta ); 544 nSelectedIndex = nNewIndex; 545 Invalidate(); 546 if( nDelta ) 547 Update(); 548 } 549 else if( nNewIndex > LastInView() ) 550 { 551 // need to scroll down to see selected item 552 int nOldPos = aVscrollSB.GetThumbPos(); 553 int nDelta = (nNewIndex - LastInView() + COLUMN_COUNT) / COLUMN_COUNT; 554 aVscrollSB.SetThumbPos( nOldPos + nDelta ); 555 if( nNewIndex < maFontCharMap.GetCharCount() ) 556 { 557 nSelectedIndex = nNewIndex; 558 Invalidate(); 559 } 560 if( nOldPos != aVscrollSB.GetThumbPos() ) 561 { 562 Invalidate(); 563 Update(); 564 } 565 } 566 else 567 { 568 // remove highlighted view 569 Color aLineCol = GetLineColor(); 570 Color aFillCol = GetFillColor(); 571 SetLineColor(); 572 SetFillColor( GetBackground().GetColor() ); 573 574 Point aOldPixel = MapIndexToPixel( nSelectedIndex ); 575 aOldPixel.Move( +1, +1); 576 DrawRect( Rectangle( aOldPixel, Size( nX-1, nY-1 ) ) ); 577 SetLineColor( aLineCol ); 578 SetFillColor( aFillCol ); 579 580 int nOldIndex = nSelectedIndex; 581 nSelectedIndex = nNewIndex; 582 DrawChars_Impl( nOldIndex, nOldIndex ); 583 DrawChars_Impl( nNewIndex, nNewIndex ); 584 } 585 586 if( nSelectedIndex >= 0 ) 587 { 588 getSelectedChar() = maFontCharMap.GetCharFromIndex( nSelectedIndex ); 589 if( m_pAccessible ) 590 { 591 ::svx::SvxShowCharSetItem* pItem = ImplGetItem(nSelectedIndex); 592 m_pAccessible->fireEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), makeAny(pItem->GetAccessible()) ); // this call asures that m_pItem is set 593 594 OSL_ENSURE(pItem->m_pItem,"No accessible created!"); 595 Any aOldAny, aNewAny; 596 aNewAny <<= AccessibleStateType::FOCUSED; 597 pItem->m_pItem->fireEvent( AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); 598 599 aNewAny <<= AccessibleStateType::SELECTED; 600 pItem->m_pItem->fireEvent( AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); 601 } 602 } 603 604 605 aHighHdl.Call( this ); 606 } 607 608 // ----------------------------------------------------------------------- 609 610 void SvxShowCharSet::SelectCharacter( sal_UCS4 cNew, sal_Bool bFocus ) 611 { 612 // get next available char of current font 613 sal_UCS4 cNext = maFontCharMap.GetNextChar( cNew - 1 ); 614 615 int nMapIndex = maFontCharMap.GetIndexFromChar( cNext ); 616 SelectIndex( nMapIndex, bFocus ); 617 if( !bFocus ) 618 { 619 // move selected item to top row if not in focus 620 aVscrollSB.SetThumbPos( nMapIndex / COLUMN_COUNT ); 621 Invalidate(); 622 } 623 } 624 625 // ----------------------------------------------------------------------- 626 627 IMPL_LINK( SvxShowCharSet, VscrollHdl, ScrollBar *, EMPTYARG ) 628 { 629 if( nSelectedIndex < FirstInView() ) 630 { 631 SelectIndex( FirstInView() + (nSelectedIndex % COLUMN_COUNT) ); 632 } 633 else if( nSelectedIndex > LastInView() ) 634 { 635 if( m_pAccessible ) 636 { 637 ::com::sun::star::uno::Any aOldAny, aNewAny; 638 int nLast = LastInView(); 639 for ( ; nLast != nSelectedIndex; ++nLast) 640 { 641 aOldAny <<= ImplGetItem(nLast)->GetAccessible(); 642 m_pAccessible ->fireEvent( AccessibleEventId::CHILD, aOldAny, aNewAny ); 643 } 644 } 645 SelectIndex( (LastInView() - COLUMN_COUNT + 1) + (nSelectedIndex % COLUMN_COUNT) ); 646 } 647 648 Invalidate(); 649 return 0; 650 } 651 652 // ----------------------------------------------------------------------- 653 654 SvxShowCharSet::~SvxShowCharSet() 655 { 656 if ( m_pAccessible ) 657 ReleaseAccessible(); 658 } 659 // ----------------------------------------------------------------------------- 660 void SvxShowCharSet::ReleaseAccessible() 661 { 662 m_aItems.clear(); 663 m_pAccessible = NULL; 664 m_xAccessible = NULL; 665 } 666 // ----------------------------------------------------------------------------- 667 ::com::sun::star::uno::Reference< XAccessible > SvxShowCharSet::CreateAccessible() 668 { 669 OSL_ENSURE(!m_pAccessible,"Accessible already created!"); 670 m_pAccessible = new ::svx::SvxShowCharSetVirtualAcc(this); 671 m_xAccessible = m_pAccessible; 672 return m_xAccessible; 673 } 674 // ----------------------------------------------------------------------------- 675 ::svx::SvxShowCharSetItem* SvxShowCharSet::ImplGetItem( int _nPos ) 676 { 677 ItemsMap::iterator aFind = m_aItems.find(_nPos); 678 if ( aFind == m_aItems.end() ) 679 { 680 OSL_ENSURE(m_pAccessible,"Who wants to create a child of my table without a parent?"); 681 aFind = m_aItems.insert(ItemsMap::value_type(_nPos,new ::svx::SvxShowCharSetItem(*this,m_pAccessible->getTable(),sal::static_int_cast< sal_uInt16 >(_nPos)))).first; 682 rtl::OUStringBuffer buf; 683 buf.appendUtf32( maFontCharMap.GetCharFromIndex( _nPos ) ); 684 aFind->second->maText = buf.makeStringAndClear(); 685 Point pix = MapIndexToPixel( _nPos ); 686 aFind->second->maRect = Rectangle( Point( pix.X() + 1, pix.Y() + 1 ), Size(nX-1,nY-1) ); 687 } 688 689 return aFind->second; 690 } 691 // ----------------------------------------------------------------------------- 692 void SvxShowCharSet::ImplFireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ) 693 { 694 if( m_pAccessible ) 695 m_pAccessible->fireEvent( nEventId, rOldValue, rNewValue ); 696 } 697 // ----------------------------------------------------------------------------- 698 ScrollBar* SvxShowCharSet::getScrollBar() 699 { 700 return &aVscrollSB; 701 } 702 // ----------------------------------------------------------------------- 703 sal_Int32 SvxShowCharSet::getMaxCharCount() const 704 { 705 return maFontCharMap.GetCharCount(); 706 } 707 708 709 // class SubsetMap ======================================================= 710 // TODO: should be moved into Font Attributes stuff 711 // we let it mature here though because it is currently the only use 712 713 SubsetMap::SubsetMap( const FontCharMap* pFontCharMap ) 714 : Resource( SVX_RES(RID_SUBSETMAP) ) 715 { 716 InitList(); 717 ApplyCharMap( pFontCharMap ); 718 FreeResource(); 719 } 720 721 const Subset* SubsetMap::GetNextSubset( bool bFirst ) const 722 { 723 if( bFirst ) 724 maSubsetIterator = maSubsets.begin(); 725 if( maSubsetIterator == maSubsets.end() ) 726 return NULL; 727 const Subset* s = &*(maSubsetIterator++); 728 return s; 729 } 730 731 const Subset* SubsetMap::GetSubsetByUnicode( sal_UCS4 cChar ) const 732 { 733 // TODO: is it worth to avoid a linear search? 734 for( const Subset* s = GetNextSubset( true ); s; s = GetNextSubset( false ) ) 735 if( (s->GetRangeMin() <= cChar) && (cChar <= s->GetRangeMax()) ) 736 return s; 737 return NULL; 738 } 739 740 inline Subset::Subset( sal_UCS4 nMin, sal_UCS4 nMax, int resId) 741 : mnRangeMin(nMin), mnRangeMax(nMax), maRangeName( SVX_RES(resId) ) 742 {} 743 744 void SubsetMap::InitList() 745 { 746 static SubsetList aAllSubsets; 747 static bool bInit = true; 748 if( bInit ) 749 { 750 bInit = false; 751 752 // TODO: eventually merge or split unicode subranges 753 // a "native writer" should decide for his subsets 754 aAllSubsets.push_back( Subset( 0x0020, 0x007F, RID_SUBSETSTR_BASIC_LATIN ) ); 755 aAllSubsets.push_back( Subset( 0x0080, 0x00FF, RID_SUBSETSTR_LATIN_1 ) ); 756 aAllSubsets.push_back( Subset( 0x0100, 0x017F, RID_SUBSETSTR_LATIN_EXTENDED_A ) ); 757 aAllSubsets.push_back( Subset( 0x0180, 0x024F, RID_SUBSETSTR_LATIN_EXTENDED_B ) ); 758 aAllSubsets.push_back( Subset( 0x0250, 0x02AF, RID_SUBSETSTR_IPA_EXTENSIONS ) ); 759 aAllSubsets.push_back( Subset( 0x02B0, 0x02FF, RID_SUBSETSTR_SPACING_MODIFIERS ) ); 760 aAllSubsets.push_back( Subset( 0x0300, 0x036F, RID_SUBSETSTR_COMB_DIACRITICAL ) ); 761 aAllSubsets.push_back( Subset( 0x0370, 0x03FF, RID_SUBSETSTR_BASIC_GREEK ) ); 762 // aAllSubsets.push_back( Subset( 0x03D0, 0x03F3, RID_SUBSETSTR_GREEK_SYMS_COPTIC ) ); 763 aAllSubsets.push_back( Subset( 0x0400, 0x04FF, RID_SUBSETSTR_CYRILLIC ) ); 764 aAllSubsets.push_back( Subset( 0x0530, 0x058F, RID_SUBSETSTR_ARMENIAN ) ); 765 aAllSubsets.push_back( Subset( 0x0590, 0x05FF, RID_SUBSETSTR_BASIC_HEBREW ) ); 766 // aAllSubsets.push_back( Subset( 0x0591, 0x05C4, RID_SUBSETSTR_HEBREW_EXTENDED ) ); 767 aAllSubsets.push_back( Subset( 0x0600, 0x065F, RID_SUBSETSTR_BASIC_ARABIC ) ); 768 aAllSubsets.push_back( Subset( 0x0660, 0x06FF, RID_SUBSETSTR_ARABIC_EXTENDED ) ); 769 aAllSubsets.push_back( Subset( 0x0700, 0x074F, RID_SUBSETSTR_SYRIAC ) ); 770 aAllSubsets.push_back( Subset( 0x0780, 0x07BF, RID_SUBSETSTR_THAANA ) ); 771 aAllSubsets.push_back( Subset( 0x0900, 0x097F, RID_SUBSETSTR_DEVANAGARI ) ); 772 aAllSubsets.push_back( Subset( 0x0980, 0x09FF, RID_SUBSETSTR_BENGALI ) ); 773 aAllSubsets.push_back( Subset( 0x0A00, 0x0A7F, RID_SUBSETSTR_GURMUKHI ) ); 774 aAllSubsets.push_back( Subset( 0x0A80, 0x0AFF, RID_SUBSETSTR_GUJARATI ) ); 775 aAllSubsets.push_back( Subset( 0x0B00, 0x0B7F, RID_SUBSETSTR_ORIYA ) ); 776 aAllSubsets.push_back( Subset( 0x0B80, 0x0BFF, RID_SUBSETSTR_TAMIL ) ); 777 aAllSubsets.push_back( Subset( 0x0C00, 0x0C7F, RID_SUBSETSTR_TELUGU ) ); 778 aAllSubsets.push_back( Subset( 0x0C80, 0x0CFF, RID_SUBSETSTR_KANNADA ) ); 779 aAllSubsets.push_back( Subset( 0x0D00, 0x0D7F, RID_SUBSETSTR_MALAYALAM ) ); 780 aAllSubsets.push_back( Subset( 0x0D80, 0x0DFF, RID_SUBSETSTR_SINHALA ) ); 781 aAllSubsets.push_back( Subset( 0x0E00, 0x0E7F, RID_SUBSETSTR_THAI ) ); 782 aAllSubsets.push_back( Subset( 0x0E80, 0x0EFF, RID_SUBSETSTR_LAO ) ); 783 aAllSubsets.push_back( Subset( 0x0F00, 0x0FBF, RID_SUBSETSTR_TIBETAN ) ); 784 aAllSubsets.push_back( Subset( 0x1000, 0x109F, RID_SUBSETSTR_MYANMAR ) ); 785 aAllSubsets.push_back( Subset( 0x10A0, 0x10FF, RID_SUBSETSTR_BASIC_GEORGIAN ) ); 786 // aAllSubsets.push_back( Subset( 0x10A0, 0x10C5, RID_SUBSETSTR_GEORGIAN_EXTENDED ) ); 787 aAllSubsets.push_back( Subset( 0x1100, 0x11FF, RID_SUBSETSTR_HANGUL_JAMO ) ); 788 aAllSubsets.push_back( Subset( 0x1200, 0x137F, RID_SUBSETSTR_ETHIOPIC ) ); 789 aAllSubsets.push_back( Subset( 0x13A0, 0x13FF, RID_SUBSETSTR_CHEROKEE ) ); 790 aAllSubsets.push_back( Subset( 0x1400, 0x167F, RID_SUBSETSTR_CANADIAN_ABORIGINAL ) ); 791 aAllSubsets.push_back( Subset( 0x1680, 0x169F, RID_SUBSETSTR_OGHAM ) ); 792 aAllSubsets.push_back( Subset( 0x16A0, 0x16F0, RID_SUBSETSTR_RUNIC ) ); 793 aAllSubsets.push_back( Subset( 0x1700, 0x171F, RID_SUBSETSTR_TAGALOG ) ); 794 aAllSubsets.push_back( Subset( 0x1720, 0x173F, RID_SUBSETSTR_HANUNOO ) ); 795 aAllSubsets.push_back( Subset( 0x1740, 0x175F, RID_SUBSETSTR_BUHID ) ); 796 aAllSubsets.push_back( Subset( 0x1760, 0x177F, RID_SUBSETSTR_TAGBANWA ) ); 797 aAllSubsets.push_back( Subset( 0x1780, 0x17FF, RID_SUBSETSTR_KHMER ) ); 798 aAllSubsets.push_back( Subset( 0x1800, 0x18AF, RID_SUBSETSTR_MONGOLIAN ) ); 799 aAllSubsets.push_back( Subset( 0x1E00, 0x1EFF, RID_SUBSETSTR_LATIN_EXTENDED_ADDS ) ); 800 aAllSubsets.push_back( Subset( 0x1F00, 0x1FFF, RID_SUBSETSTR_GREEK_EXTENDED ) ); 801 802 aAllSubsets.push_back( Subset( 0x2000, 0x206F, RID_SUBSETSTR_GENERAL_PUNCTUATION ) ); 803 aAllSubsets.push_back( Subset( 0x2070, 0x209F, RID_SUBSETSTR_SUB_SUPER_SCRIPTS ) ); 804 aAllSubsets.push_back( Subset( 0x20A0, 0x20CF, RID_SUBSETSTR_CURRENCY_SYMBOLS ) ); 805 aAllSubsets.push_back( Subset( 0x20D0, 0x20FF, RID_SUBSETSTR_COMB_DIACRITIC_SYMS ) ); 806 aAllSubsets.push_back( Subset( 0x2100, 0x214F, RID_SUBSETSTR_LETTERLIKE_SYMBOLS ) ); 807 aAllSubsets.push_back( Subset( 0x2150, 0x218F, RID_SUBSETSTR_NUMBER_FORMS ) ); 808 aAllSubsets.push_back( Subset( 0x2190, 0x21FF, RID_SUBSETSTR_ARROWS ) ); 809 aAllSubsets.push_back( Subset( 0x2200, 0x22FF, RID_SUBSETSTR_MATH_OPERATORS ) ); 810 aAllSubsets.push_back( Subset( 0x2300, 0x23FF, RID_SUBSETSTR_MISC_TECHNICAL ) ); 811 aAllSubsets.push_back( Subset( 0x2400, 0x243F, RID_SUBSETSTR_CONTROL_PICTURES ) ); 812 aAllSubsets.push_back( Subset( 0x2440, 0x245F, RID_SUBSETSTR_OPTICAL_CHAR_REC ) ); 813 aAllSubsets.push_back( Subset( 0x2460, 0x24FF, RID_SUBSETSTR_ENCLOSED_ALPHANUM ) ); 814 aAllSubsets.push_back( Subset( 0x2500, 0x257F, RID_SUBSETSTR_BOX_DRAWING ) ); 815 aAllSubsets.push_back( Subset( 0x2580, 0x259F, RID_SUBSETSTR_BLOCK_ELEMENTS ) ); 816 aAllSubsets.push_back( Subset( 0x25A0, 0x25FF, RID_SUBSETSTR_GEOMETRIC_SHAPES ) ); 817 aAllSubsets.push_back( Subset( 0x2600, 0x26FF, RID_SUBSETSTR_MISC_DINGBATS ) ); 818 aAllSubsets.push_back( Subset( 0x2700, 0x27BF, RID_SUBSETSTR_DINGBATS ) ); 819 820 aAllSubsets.push_back( Subset( 0x27C0, 0x27FF, RID_SUBSETSTR_MISC_MATH_SYMS_A ) ); 821 aAllSubsets.push_back( Subset( 0x27F0, 0x27FF, RID_SUBSETSTR_SUPPL_ARROWS_A ) ); 822 aAllSubsets.push_back( Subset( 0x2800, 0x28FF, RID_SUBSETSTR_BRAILLE_PATTERNS ) ); 823 aAllSubsets.push_back( Subset( 0x2900, 0x297F, RID_SUBSETSTR_SUPPL_ARROWS_B ) ); 824 aAllSubsets.push_back( Subset( 0x2980, 0x29FF, RID_SUBSETSTR_MISC_MATH_SYMS_B ) ); 825 aAllSubsets.push_back( Subset( 0x2E80, 0x2EFF, RID_SUBSETSTR_CJK_RADICAL_SUPPL ) ); 826 aAllSubsets.push_back( Subset( 0x2F00, 0x2FDF, RID_SUBSETSTR_KANXI_RADICALS ) ); 827 aAllSubsets.push_back( Subset( 0x2FF0, 0x2FFF, RID_SUBSETSTR_IDEO_DESC_CHARS ) ); 828 829 aAllSubsets.push_back( Subset( 0x3000, 0x303F, RID_SUBSETSTR_CJK_SYMS_PUNCTUATION ) ); 830 aAllSubsets.push_back( Subset( 0x3040, 0x309F, RID_SUBSETSTR_HIRAGANA ) ); 831 aAllSubsets.push_back( Subset( 0x30A0, 0x30FF, RID_SUBSETSTR_KATAKANA ) ); 832 aAllSubsets.push_back( Subset( 0x3100, 0x312F, RID_SUBSETSTR_BOPOMOFO ) ); 833 aAllSubsets.push_back( Subset( 0x3130, 0x318F, RID_SUBSETSTR_HANGUL_COMPAT_JAMO ) ); 834 aAllSubsets.push_back( Subset( 0x3190, 0x319F, RID_SUBSETSTR_KANBUN ) ); 835 aAllSubsets.push_back( Subset( 0x31A0, 0x31BF, RID_SUBSETSTR_BOPOMOFO_EXTENDED ) ); 836 aAllSubsets.push_back( Subset( 0x31C0, 0x31FF, RID_SUBSETSTR_KATAKANA_PHONETIC ) ); 837 aAllSubsets.push_back( Subset( 0x3200, 0x32FF, RID_SUBSETSTR_ENCLOSED_CJK_LETTERS ) ); 838 aAllSubsets.push_back( Subset( 0x3300, 0x33FF, RID_SUBSETSTR_CJK_COMPATIBILITY ) ); 839 840 aAllSubsets.push_back( Subset( 0x3400, 0x4DFF, RID_SUBSETSTR_CJK_EXT_A_UNIFIED_IDGRAPH ) ); 841 aAllSubsets.push_back( Subset( 0x4E00, 0x9FA5, RID_SUBSETSTR_CJK_UNIFIED_IDGRAPH ) ); 842 aAllSubsets.push_back( Subset( 0xA000, 0xA4CF, RID_SUBSETSTR_YI ) ); 843 aAllSubsets.push_back( Subset( 0xAC00, 0xB097, RID_SUBSETSTR_HANGUL_GA ) ); 844 aAllSubsets.push_back( Subset( 0xB098, 0xB2E3, RID_SUBSETSTR_HANGUL_NA ) ); 845 aAllSubsets.push_back( Subset( 0xB2E4, 0xB77B, RID_SUBSETSTR_HANGUL_DA ) ); 846 aAllSubsets.push_back( Subset( 0xB77C, 0xB9C7, RID_SUBSETSTR_HANGUL_RA ) ); 847 aAllSubsets.push_back( Subset( 0xB9C8, 0xBC13, RID_SUBSETSTR_HANGUL_MA ) ); 848 aAllSubsets.push_back( Subset( 0xBC14, 0xC0AB, RID_SUBSETSTR_HANGUL_BA ) ); 849 aAllSubsets.push_back( Subset( 0xC0AC, 0xC543, RID_SUBSETSTR_HANGUL_SA ) ); 850 aAllSubsets.push_back( Subset( 0xC544, 0xC78F, RID_SUBSETSTR_HANGUL_AH ) ); 851 aAllSubsets.push_back( Subset( 0xC790, 0xCC27, RID_SUBSETSTR_HANGUL_JA ) ); 852 aAllSubsets.push_back( Subset( 0xCC28, 0xCE73, RID_SUBSETSTR_HANGUL_CHA ) ); 853 aAllSubsets.push_back( Subset( 0xCE74, 0xD0BF, RID_SUBSETSTR_HANGUL_KA ) ); 854 aAllSubsets.push_back( Subset( 0xD0C0, 0xD30B, RID_SUBSETSTR_HANGUL_TA ) ); 855 aAllSubsets.push_back( Subset( 0xD30C, 0xD557, RID_SUBSETSTR_HANGUL_PA ) ); 856 aAllSubsets.push_back( Subset( 0xD558, 0xD7A3, RID_SUBSETSTR_HANGUL_HA ) ); 857 // aAllSubsets.push_back( Subset( 0xAC00, 0xD7AF, RID_SUBSETSTR_HANGUL ) ); 858 859 // aAllSubsets.push_back( Subset( 0xD800, 0xDFFF, RID_SUBSETSTR_SURROGATE ) ); 860 aAllSubsets.push_back( Subset( 0xE000, 0xF8FF, RID_SUBSETSTR_PRIVATE_USE_AREA ) ); 861 aAllSubsets.push_back( Subset( 0xF900, 0xFAFF, RID_SUBSETSTR_CJK_COMPAT_IDGRAPHS ) ); 862 aAllSubsets.push_back( Subset( 0xFB00, 0xFB4F, RID_SUBSETSTR_ALPHA_PRESENTATION ) ); 863 aAllSubsets.push_back( Subset( 0xFB50, 0xFDFF, RID_SUBSETSTR_ARABIC_PRESENT_A ) ); 864 aAllSubsets.push_back( Subset( 0xFE20, 0xFE2F, RID_SUBSETSTR_COMBINING_HALF_MARKS ) ); 865 aAllSubsets.push_back( Subset( 0xFE30, 0xFE4F, RID_SUBSETSTR_CJK_COMPAT_FORMS ) ); 866 aAllSubsets.push_back( Subset( 0xFE50, 0xFE6F, RID_SUBSETSTR_SMALL_FORM_VARIANTS ) ); 867 aAllSubsets.push_back( Subset( 0xFE70, 0xFEFF, RID_SUBSETSTR_ARABIC_PRESENT_B ) ); 868 aAllSubsets.push_back( Subset( 0xFF00, 0xFFEF, RID_SUBSETSTR_HALFW_FULLW_FORMS ) ); 869 aAllSubsets.push_back( Subset( 0xFFF0, 0xFFFF, RID_SUBSETSTR_SPECIALS ) ); 870 } 871 872 maSubsets = aAllSubsets; 873 } 874 875 void SubsetMap::ApplyCharMap( const FontCharMap* pFontCharMap ) 876 { 877 if( !pFontCharMap ) 878 return; 879 880 // remove subsets that are not matched in any range 881 SubsetList::iterator it_next = maSubsets.begin(); 882 while( it_next != maSubsets.end() ) 883 { 884 SubsetList::iterator it = it_next++; 885 const Subset& rSubset = *it; 886 sal_uInt32 cMin = rSubset.GetRangeMin(); 887 sal_uInt32 cMax = rSubset.GetRangeMax(); 888 889 int nCount = pFontCharMap->CountCharsInRange( cMin, cMax ); 890 if( nCount <= 0 ) 891 maSubsets.erase( it ); 892 } 893 } 894