xref: /aoo41x/main/vcl/unx/generic/app/i18n_status.cxx (revision cdf0e10c)
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_vcl.hxx"
30 
31 #if OSL_DEBUG_LEVEL > 1
32 #include <stdio.h>
33 #endif
34 #include <sal/alloca.h>
35 
36 #include <tools/prex.h>
37 #include <X11/Xlib.h>
38 #include <unx/XIM.h>
39 #include <tools/postx.h>
40 
41 #include <unx/salunx.h>
42 #include <unx/i18n_status.hxx>
43 #include <unx/i18n_ic.hxx>
44 #include <unx/saldisp.hxx>
45 #include <unx/salframe.h>
46 #include <unx/saldata.hxx>
47 
48 #include <vcl/wrkwin.hxx>
49 #include <vcl/fixed.hxx>
50 #include <vcl/menubtn.hxx>
51 #include <vcl/menu.hxx>
52 #include <vcl/svapp.hxx>
53 #include <vcl/sysdata.hxx>
54 
55 #include <svdata.hxx>
56 
57 using namespace vcl;
58 using namespace rtl;
59 
60 namespace vcl {
61 
62 class StatusWindow : public WorkWindow
63 {
64 protected:
65     StatusWindow( WinBits nWinBits );
66 public:
67     virtual ~StatusWindow();
68 
69     virtual void setPosition( SalFrame* );
70     virtual void setText( const String & ) = 0;
71     virtual String getText() const = 0;
72     virtual void show( bool bShow, I18NStatus::ShowReason eReason ) = 0;
73     virtual void toggle( bool bOn ) = 0;
74 };
75 
76 }
77 
78 StatusWindow::StatusWindow( WinBits nWinBits ) :
79         WorkWindow( NULL, nWinBits )
80 {
81 }
82 
83 StatusWindow::~StatusWindow() {}
84 
85 void StatusWindow::setPosition( SalFrame* )
86 {
87 }
88 
89 // --------------------------------------------------------------------------
90 
91 namespace vcl {
92 
93 class XIMStatusWindow : public StatusWindow
94 {
95     FixedText				m_aStatusText;
96     SalFrame*				m_pLastParent;
97     Size					m_aWindowSize;
98     bool                    m_bAnchoredAtRight;
99         // true if the right edge (instead of the left edge) should stay at a
100         // fixed position when re-sizing the window
101 
102     // for delayed showing
103     bool					m_bDelayedShow;
104     I18NStatus::ShowReason	m_eDelayedReason;
105     sal_uLong					m_nDelayedEvent;
106     // for toggling
107     bool                    m_bOn;
108 
109     Point updatePosition();
110     void layout();
111     bool checkLastParent() const;
112 
113     DECL_LINK( DelayedShowHdl, void* );
114 public:
115     XIMStatusWindow( bool bOn );
116     virtual ~XIMStatusWindow();
117 
118     virtual void setPosition( SalFrame* );
119     virtual void setText( const String & );
120     virtual String getText() const;
121     virtual void show( bool bShow, I18NStatus::ShowReason eReason );
122     virtual void toggle( bool bOn );
123 
124     // overload WorkWindow::DataChanged
125     virtual void DataChanged( const DataChangedEvent& rEvt );
126 };
127 
128 }
129 
130 XIMStatusWindow::XIMStatusWindow( bool bOn ) :
131         StatusWindow( WB_BORDER | WB_SYSTEMFLOATWIN | WB_TOOLTIPWIN ),
132         m_aStatusText( this, 0 ),
133         m_pLastParent( NULL ),
134         m_bAnchoredAtRight( false ),
135         m_bDelayedShow( false ),
136         m_eDelayedReason( I18NStatus::contextmap ),
137         m_nDelayedEvent( 0 ),
138         m_bOn( bOn )
139 {
140     layout();
141 }
142 
143 XIMStatusWindow::~XIMStatusWindow()
144 {
145     if( m_nDelayedEvent )
146         Application::RemoveUserEvent( m_nDelayedEvent );
147 }
148 
149 void XIMStatusWindow::toggle( bool bOn )
150 {
151     m_bOn = bOn;
152     show( bOn, I18NStatus::contextmap );
153 }
154 
155 void XIMStatusWindow::layout()
156 {
157     m_aWindowSize.Width() = m_aStatusText.GetTextWidth( m_aStatusText.GetText() )+8;
158     Font aFont( m_aStatusText.GetFont() );
159     m_aWindowSize.Height() = aFont.GetHeight()+10;
160     m_aWindowSize = LogicToPixel( m_aWindowSize );
161 
162     Size aControlSize( m_aWindowSize );
163     aControlSize.Width()  -= 4;
164     aControlSize.Height() -= 4;
165 
166     m_aStatusText.SetPosSizePixel( Point( 1, 1 ), aControlSize );
167     m_aStatusText.SetFont( aFont );
168     m_aStatusText.Show( sal_True );
169 
170     if (m_bAnchoredAtRight && IsVisible())
171     {
172         SalFrame* pFrame = (SalFrame*)GetSystemData()->pSalFrame;
173         long nDelta = pFrame->maGeometry.nWidth - m_aWindowSize.Width();
174         pFrame->SetPosSize( pFrame->maGeometry.nX + nDelta,
175                             pFrame->maGeometry.nY,
176                             m_aWindowSize.Width(),
177                             m_aWindowSize.Height(),
178                             SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
179     }
180     else
181         SetOutputSizePixel( m_aWindowSize );
182 }
183 
184 bool XIMStatusWindow::checkLastParent() const
185 {
186     if( m_pLastParent )
187     {
188         const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
189         for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
190         {
191             if( *it == m_pLastParent )
192                 return true;
193         }
194     }
195     return false;
196 }
197 
198 void XIMStatusWindow::DataChanged( const DataChangedEvent& )
199 {
200     m_aStatusText.SetSettings( GetSettings() );
201     layout();
202 }
203 
204 Point XIMStatusWindow::updatePosition()
205 {
206     Point aRet;
207     if( checkLastParent() )
208     {
209         const SystemEnvData* pParentEnvData = m_pLastParent->GetSystemData();
210 
211         SalExtTextInputPosEvent aPosEvent;
212         m_pLastParent->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent );
213         int x, y;
214         XLIB_Window aChild;
215         XTranslateCoordinates( (Display*)pParentEnvData->pDisplay,
216                                (XLIB_Window)pParentEnvData->aShellWindow,
217                                GetX11SalData()->GetDisplay()->GetRootWindow( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() ),
218                                0, 0,
219                                &x, &y,
220                                &aChild );
221 
222         // TODO:  Currently, place the status window to the (physical) left of
223         // the cursor iff in vertical mode (assuming that the columns in
224         // vertical mode are always written from right to left, this causes the
225         // status window to keep out of the text already written).  This
226         // heuristic would break if there is ever a vertical mode in which the
227         // columns are written from left to right.  Also, more elaborate
228         // positioning for (both horizontal and vertical) left-to-right and
229         // right-to-left text would be possible.
230         bool bLeft = aPosEvent.mbVertical;
231             // true if status window is to the left of the cursor
232 
233         int const nGap = 4; // between cursor and status window
234         if (aPosEvent.mbVertical)
235         {
236             aRet.X() = x + aPosEvent.mnX + (bLeft
237                                             ? -m_aWindowSize.Width() - nGap
238                                             : aPosEvent.mnHeight + nGap);
239             aRet.Y() = y + aPosEvent.mnY;
240         }
241         else
242         {
243             aRet.X() = x + aPosEvent.mnX + (bLeft ? -m_aWindowSize.Width() : 0);
244             aRet.Y() = y + aPosEvent.mnY+aPosEvent.mnHeight + nGap;
245         }
246 
247         m_bAnchoredAtRight = bLeft;
248     }
249     return aRet;
250 }
251 
252 void XIMStatusWindow::setPosition( SalFrame* pParent )
253 {
254     if( pParent )
255     {
256         if( pParent != m_pLastParent )
257         {
258             setText( String() );
259             m_pLastParent = pParent;
260             Show( sal_False, SHOW_NOACTIVATE );
261         }
262         if( IsVisible() )
263         {
264             const SystemEnvData* pEnvData = GetSystemData();
265             SalFrame* pStatusFrame = (SalFrame*)pEnvData->pSalFrame;
266             Point aPoint = updatePosition();
267             pStatusFrame->SetPosSize( aPoint.X(), aPoint.Y(), m_aWindowSize.Width(), m_aWindowSize.Height(), SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
268         }
269     }
270 }
271 
272 IMPL_LINK( XIMStatusWindow, DelayedShowHdl, void*, EMPTYARG )
273 {
274     m_nDelayedEvent = 0;
275     const SystemEnvData* pData = GetSystemData();
276     SalFrame* pStatusFrame = (SalFrame*)pData->pSalFrame;
277     if( m_bDelayedShow )
278     {
279         Size aControlSize( m_aWindowSize.Width()-4, m_aWindowSize.Height()-4 );
280         m_aStatusText.SetPosSizePixel( Point( 1, 1 ), aControlSize );
281         Point aPoint = updatePosition();
282         pStatusFrame->SetPosSize( aPoint.X(), aPoint.Y(), m_aWindowSize.Width(), m_aWindowSize.Height(), SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
283     }
284     Show( m_bDelayedShow && m_bOn, SHOW_NOACTIVATE );
285     if( m_bDelayedShow )
286     {
287 		XRaiseWindow( (Display*)pData->pDisplay,
288                       (XLIB_Window)pData->aShellWindow );
289     }
290     return 0;
291 }
292 
293 void XIMStatusWindow::show( bool bShow, I18NStatus::ShowReason eReason )
294 {
295     if( bShow && ! m_aStatusText.GetText().Len() )
296         bShow = false;
297 
298     m_bDelayedShow = bShow;
299     m_eDelayedReason = eReason;
300     if( ! m_nDelayedEvent )
301         m_nDelayedEvent = Application::PostUserEvent( LINK( this, XIMStatusWindow, DelayedShowHdl ) );
302 }
303 
304 void XIMStatusWindow::setText( const String& rText )
305 {
306     m_aStatusText.SetText( rText );
307     m_aWindowSize.Width() = m_aStatusText.GetTextWidth( rText )+8;
308 }
309 
310 String XIMStatusWindow::getText() const
311 {
312     return m_aStatusText.GetText();
313 }
314 
315 // --------------------------------------------------------------------------
316 
317 namespace vcl {
318 
319 class IIIMPStatusWindow : public StatusWindow
320 {
321     MenuButton				m_aStatusBtn;
322     PopupMenu				m_aMenu;
323     SalFrame*				m_pResetFocus;
324     bool                    m_bShow;
325     bool                    m_bOn;
326 
327     DECL_LINK( SelectHdl, MenuButton* );
328 
329     void show();
330 
331 public:
332     IIIMPStatusWindow( SalFrame* pParent, bool bOn ); // for initial position
333     virtual ~IIIMPStatusWindow();
334 
335     virtual void setText( const String & );
336     virtual String getText() const;
337     virtual void show( bool bShow, I18NStatus::ShowReason eReason );
338     virtual void toggle( bool bOn );
339     void layout();
340 
341     // overload Window focus handler
342     virtual void        GetFocus();
343     // overload WorkWindow::DataChanged
344     virtual void DataChanged( const DataChangedEvent& rEvt );
345 };
346 
347 }
348 
349 IIIMPStatusWindow::IIIMPStatusWindow( SalFrame* pParent, bool bOn ) :
350         StatusWindow( WB_MOVEABLE ),
351         m_aStatusBtn( this, WB_BORDER ),
352         m_pResetFocus( pParent ),
353         m_bShow( true ),
354         m_bOn( bOn )
355 {
356     SetText( String( RTL_CONSTASCII_USTRINGPARAM( "IME Status" ) ) );
357 
358     layout();
359 
360     m_aStatusBtn.SetSelectHdl( LINK( this, IIIMPStatusWindow, SelectHdl ) );
361     m_aStatusBtn.SetPopupMenu( &m_aMenu );
362     m_aStatusBtn.Show( sal_True );
363 
364     const ::std::vector< I18NStatus::ChoiceData >& rChoices( I18NStatus::get().getChoices() );
365     int i = 1;
366     for( ::std::vector< I18NStatus::ChoiceData >::const_iterator it = rChoices.begin(); it != rChoices.end(); ++it, i++ )
367         m_aMenu.InsertItem( i, it->aString );
368 
369     if( pParent )
370     {
371         const SystemEnvData* pEnvData = GetSystemData();
372 
373         const SalFrameGeometry& rGeom( pParent->GetUnmirroredGeometry() );
374         int nDistance = rGeom.nTopDecoration;
375         if( nDistance < 20 )
376             nDistance = 20;
377         XMoveWindow( (Display*)pEnvData->pDisplay,
378                      (XLIB_Window)pEnvData->aShellWindow,
379                      rGeom.nX,
380                      rGeom.nY + rGeom.nHeight + nDistance
381                      );
382     }
383 #if OSL_DEBUG_LEVEL > 1
384     else
385         fprintf( stderr, "Warning: could not reposition status window since no frame\n" );
386 #endif
387     EnableAlwaysOnTop( sal_True );
388 }
389 
390 IIIMPStatusWindow::~IIIMPStatusWindow()
391 {
392 }
393 
394 void IIIMPStatusWindow::layout()
395 {
396     Font aFont( m_aStatusBtn.GetFont() );
397     Size aSize( 15*aFont.GetHeight(), aFont.GetHeight()+14 );
398     aSize = m_aStatusBtn.LogicToPixel( aSize );
399 
400     m_aStatusBtn.SetPosSizePixel( Point( 0, 0 ), aSize );
401     SetOutputSizePixel( aSize );
402     if( IsVisible() )
403         Invalidate();
404 }
405 
406 void IIIMPStatusWindow::DataChanged( const DataChangedEvent& )
407 {
408     m_aStatusBtn.SetSettings( GetSettings() );
409     layout();
410 }
411 
412 void IIIMPStatusWindow::setText( const String& rText )
413 {
414     m_aStatusBtn.SetText( rText );
415 }
416 
417 String IIIMPStatusWindow::getText() const
418 {
419     return m_aStatusBtn.GetText();
420 }
421 
422 void IIIMPStatusWindow::show( bool bShow, I18NStatus::ShowReason eReason )
423 {
424     // hide IIIMPStatusWindow only in presentations
425     if( ! bShow
426         && eReason != I18NStatus::presentation
427         )
428         return;
429 
430     m_bShow = bShow;
431     show();
432 }
433 
434 void IIIMPStatusWindow::toggle( bool bOn )
435 {
436     if (bOn != m_bOn)
437     {
438         m_bOn = bOn;
439         show();
440     }
441 }
442 
443 void IIIMPStatusWindow::show()
444 {
445     if (m_bOn && m_bShow && !IsVisible())
446         m_pResetFocus = I18NStatus::get().getParent();
447     Show(m_bOn && m_bShow);
448 }
449 
450 void IIIMPStatusWindow::GetFocus()
451 {
452     /*
453      *  this is here just to put the focus back to the application
454      *  window at startup on clickToFocus WMs
455      */
456     WorkWindow::GetFocus();
457     if( m_pResetFocus )
458     {
459         /*
460          *  look if reset focus still exists
461          *  since reset focus really is an internal hack there should
462          *  not be a method to be called in SalFrame destructor
463          */
464         const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
465         std::list< SalFrame* >::const_iterator it;
466         for( it = rFrames.begin(); it != rFrames.end() && *it != m_pResetFocus; ++it )
467             ;
468         if( it != rFrames.end() )
469         {
470             const SystemEnvData* pParentEnvData = m_pResetFocus->GetSystemData();
471             SalXLib* pXLib = GetX11SalData()->GetDisplay()->GetXLib();
472             pXLib->PushXErrorLevel( true );
473             XSetInputFocus( (Display*)pParentEnvData->pDisplay,
474                             (XLIB_Window)pParentEnvData->aShellWindow,
475                             RevertToNone,
476                             CurrentTime
477                             );
478             XSync( (Display*)pParentEnvData->pDisplay, False );
479             pXLib->PopXErrorLevel();
480         }
481         m_pResetFocus = NULL;
482     }
483 }
484 
485 // --------------------------------------------------------------------------
486 
487 IMPL_LINK( IIIMPStatusWindow, SelectHdl, MenuButton*, pBtn )
488 {
489     if( pBtn == & m_aStatusBtn )
490     {
491         const ::std::vector< I18NStatus::ChoiceData >& rChoices( I18NStatus::get().getChoices() );
492         unsigned int nIndex = m_aStatusBtn.GetCurItemId()-1;
493         if( nIndex < rChoices.size() )
494         {
495             XSetICValues( static_cast<X11SalFrame*>(I18NStatus::get().getParent())->getInputContext()->GetContext(),
496                           XNUnicodeCharacterSubset,
497                           rChoices[nIndex].pData,
498                           NULL);
499             // FIXME: get rid of X11SalFrame
500             X11SalFrame* pParent = static_cast<X11SalFrame*>(I18NStatus::get().getParent());
501             if( pParent && pParent->isMapped() )
502             {
503                 const SystemEnvData* pEnv = pParent->GetSystemData();
504                 SalXLib* pXLib = GetX11SalData()->GetDisplay()->GetXLib();
505                 pXLib->PushXErrorLevel( true );
506                 XSetInputFocus( (Display*)pEnv->pDisplay,
507                                 (XLIB_Window)pEnv->aShellWindow,
508                                 RevertToNone,
509                                 CurrentTime
510                                 );
511                 XSync( (Display*)pEnv->pDisplay, False );
512                 pXLib->PopXErrorLevel();
513             }
514         }
515     }
516     return 0;
517 }
518 
519 /*
520  *  I18NStatus
521  */
522 
523 I18NStatus* I18NStatus::pInstance = NULL;
524 
525 I18NStatus& I18NStatus::get()
526 {
527     if( ! pInstance )
528         pInstance = new I18NStatus();
529     return *pInstance;
530 }
531 
532 // --------------------------------------------------------------------------
533 
534 bool I18NStatus::exists()
535 {
536     return pInstance != NULL;
537 }
538 
539 // --------------------------------------------------------------------------
540 
541 void I18NStatus::free()
542 {
543     if( pInstance )
544         delete pInstance, pInstance = NULL;
545 }
546 
547 // --------------------------------------------------------------------------
548 
549 I18NStatus::I18NStatus() :
550         m_pParent( NULL ),
551         m_pStatusWindow( NULL )
552 {
553 }
554 
555 // --------------------------------------------------------------------------
556 
557 I18NStatus::~I18NStatus()
558 {
559     if( m_pStatusWindow )
560         delete m_pStatusWindow, m_pStatusWindow = NULL;
561     if( pInstance == this )
562         pInstance = NULL;
563 }
564 
565 // --------------------------------------------------------------------------
566 
567 void I18NStatus::setParent( SalFrame* pParent )
568 {
569     m_pParent = pParent;
570     if( ! m_pStatusWindow )
571     {
572         bool bIIIMPmode = m_aChoices.begin() != m_aChoices.end();
573         if( bIIIMPmode )
574             m_pStatusWindow = new IIIMPStatusWindow( pParent,
575                                                      getStatusWindowMode() );
576         else
577             m_pStatusWindow = new XIMStatusWindow( getStatusWindowMode() );
578         setStatusText( m_aCurrentIM );
579     }
580     m_pStatusWindow->setPosition( m_pParent );
581 }
582 
583 // --------------------------------------------------------------------------
584 
585 void I18NStatus::show( bool bShow, ShowReason eReason )
586 {
587     if( m_pStatusWindow )
588     {
589         m_pStatusWindow->setPosition( m_pParent );
590         m_pStatusWindow->show( bShow, eReason );
591     }
592 }
593 
594 // --------------------------------------------------------------------------
595 
596 void I18NStatus::setStatusText( const String& rText )
597 {
598     if( m_pStatusWindow )
599     {
600         /*
601          *  #93614# convert fullwidth ASCII forms to ascii
602          */
603         int nChars = rText.Len()+1;
604         sal_Unicode* pBuffer = (sal_Unicode*)alloca( nChars*sizeof( sal_Unicode ) );
605         const sal_Unicode* pCopy = rText.GetBuffer();
606         for( int i = 0; i < nChars; i++ )
607         {
608             if( pCopy[i] >=0xff00 && pCopy[i] <= 0xff5f )
609                 pBuffer[i] = (pCopy[i] & 0xff) + 0x20;
610             else
611                 pBuffer[i] = pCopy[i];
612         }
613         String aText( pBuffer );
614         m_pStatusWindow->setText( aText );
615         m_pStatusWindow->setPosition( m_pParent );
616 
617         bool bVisible = true;
618         if( m_pParent )
619         {
620             long w, h;
621             m_pParent->GetClientSize( w, h );
622             if( w == 0 || h == 0 )
623             {
624                 bVisible = false;
625             }
626         }
627 
628         m_pStatusWindow->show( bVisible, contextmap );
629     }
630 }
631 
632 // --------------------------------------------------------------------------
633 
634 void I18NStatus::changeIM( const String& rIM )
635 {
636     m_aCurrentIM = rIM;
637 }
638 
639 // --------------------------------------------------------------------------
640 
641 String I18NStatus::getStatusText() const
642 {
643     return m_pStatusWindow ? m_pStatusWindow->getText() :  String();
644 }
645 
646 // --------------------------------------------------------------------------
647 
648 void I18NStatus::clearChoices()
649 {
650     m_aChoices.clear();
651 }
652 
653 // --------------------------------------------------------------------------
654 
655 void I18NStatus::addChoice( const String& rChoice, void* pData )
656 {
657     ChoiceData aData;
658     aData.pData		= pData;
659     aData.aString	= rChoice;
660     m_aChoices.push_back( aData );
661 }
662 
663 // --------------------------------------------------------------------------
664 
665 void I18NStatus::toTop() const
666 {
667     if( m_pStatusWindow )
668 	{
669 		const SystemEnvData* pData = m_pStatusWindow->GetSystemData();
670 		XRaiseWindow( (Display*)pData->pDisplay,
671                       (XLIB_Window)pData->aShellWindow );
672 	}
673 }
674 
675 // --------------------------------------------------------------------------
676 
677 SalFrame* I18NStatus::getStatusFrame() const
678 {
679     SalFrame* pRet = NULL;
680     if( m_pStatusWindow )
681     {
682 		const SystemEnvData* pData = m_pStatusWindow->GetSystemData();
683         pRet = (SalFrame*)pData->pSalFrame;
684     }
685     return pRet;
686 }
687 
688 bool I18NStatus::canToggleStatusWindow() const
689 {
690     return true;
691 }
692 
693 void I18NStatus::toggleStatusWindow()
694 {
695     if (m_pStatusWindow != 0)
696         m_pStatusWindow->toggle(getStatusWindowMode());
697 }
698 
699 bool I18NStatus::getStatusWindowMode()
700 {
701     switch (ImplGetSVData()->maAppData.meShowImeStatusWindow)
702     {
703     default: // ImplSVAppData::ImeStatusWindowMode_UNKNOWN
704         return Application::GetShowImeStatusWindowDefault();
705     case ImplSVAppData::ImeStatusWindowMode_HIDE:
706         return false;
707     case ImplSVAppData::ImeStatusWindowMode_SHOW:
708         return true;
709     }
710 }
711 
712 /*
713  * X11ImeStatus
714  */
715 X11ImeStatus::~X11ImeStatus()
716 {
717     vcl::I18NStatus::free();
718 }
719 
720 bool X11ImeStatus::canToggle()
721 {
722     return vcl::I18NStatus::get().canToggleStatusWindow();
723 }
724 
725 void X11ImeStatus::toggle()
726 {
727     vcl::I18NStatus::get().toggleStatusWindow();
728 }
729 
730 SalI18NImeStatus* X11SalInstance::CreateI18NImeStatus()
731 {
732     return new X11ImeStatus();
733 }
734