xref: /trunk/main/vcl/os2/source/app/salinst.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 #define INCL_DOSMISC
29 #define INCL_DOSMODULEMGR
30 #define INCL_DOSPROCESS
31 
32 #include <string.h>
33 #include <svpm.h>
34 #include <process.h>
35 
36 #define _SV_SALINST_CXX
37 
38 #ifndef _VOS_MUTEX_HXX
39 #include <vos/mutex.hxx>
40 #endif
41 #include <tools/debug.hxx>
42 
43 #ifndef _SV_SALIDS_HRC
44 #include <salids.hrc>
45 #endif
46 #include <vcl/apptypes.hxx>
47 #include <saldata.hxx>
48 #include <salinst.h>
49 #include <salframe.h>
50 #include <salobj.h>
51 #include <saltimer.h>
52 #include <salbmp.h>
53 #include <vcl/salimestatus.hxx>
54 #include <vcl/timer.hxx>
55 #include <tools/solarmutex.hxx>
56 
57 // =======================================================================
58 
59 void SalAbort( const XubString& rErrorText )
60 {
61     ImplFreeSalGDI();
62 
63     if( !rErrorText.Len() )
64         fprintf( stderr, "Application Error " );
65     else
66         fprintf( stderr, "%s ",
67             ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() );
68     abort();
69 }
70 
71 // =======================================================================
72 
73 ULONG GetCurrentThreadId()
74 {
75     PTIB pptib = NULL;
76     PPIB pppib = NULL;
77 
78     DosGetInfoBlocks( &pptib, &pppib );
79     return pptib->tib_ptib2->tib2_ultid;
80 }
81 
82 // =======================================================================
83 
84 MRESULT EXPENTRY SalComWndProc( HWND hWnd, ULONG nMsg, MPARAM nMP1, MPARAM nMP2 );
85 
86 // =======================================================================
87 
88 class SalYieldMutex : public vos::OMutex
89 {
90 public:
91     Os2SalInstance*         mpInstData;
92     ULONG                   mnCount;
93     ULONG                   mnThreadId;
94 
95 public:
96                             SalYieldMutex( Os2SalInstance* pInstData );
97 
98     virtual void SAL_CALL       acquire();
99     virtual void SAL_CALL       release();
100     virtual sal_Bool SAL_CALL   tryToAcquire();
101 
102     ULONG                   GetAcquireCount( ULONG nThreadId );
103 };
104 
105 // -----------------------------------------------------------------------
106 
107 SalYieldMutex::SalYieldMutex( Os2SalInstance* pInstData )
108 {
109     mpInstData  = pInstData;
110     mnCount     = 0;
111     mnThreadId  = 0;
112 }
113 
114 // -----------------------------------------------------------------------
115 
116 void SalYieldMutex::acquire()
117 {
118     OMutex::acquire();
119     mnCount++;
120     mnThreadId = GetCurrentThreadId();
121 }
122 
123 // -----------------------------------------------------------------------
124 
125 void SalYieldMutex::release()
126 {
127     ULONG nThreadId = GetCurrentThreadId();
128     if ( mnThreadId != nThreadId )
129         OMutex::release();
130     else
131     {
132         SalData* pSalData = GetSalData();
133         if ( pSalData->mnAppThreadId != nThreadId )
134         {
135             if ( mnCount == 1 )
136             {
137                 mpInstData->mpSalWaitMutex->acquire();
138                 if ( mpInstData->mnYieldWaitCount )
139                     WinPostMsg( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
140                 mnThreadId = 0;
141                 mnCount--;
142                 OMutex::release();
143                 mpInstData->mpSalWaitMutex->release();
144             }
145             else
146             {
147                 mnCount--;
148                 OMutex::release();
149             }
150         }
151         else
152         {
153             if ( mnCount == 1 )
154                 mnThreadId = 0;
155             mnCount--;
156             OMutex::release();
157         }
158     }
159 }
160 
161 // -----------------------------------------------------------------------
162 
163 sal_Bool SalYieldMutex::tryToAcquire()
164 {
165     if ( OMutex::tryToAcquire() )
166     {
167         mnCount++;
168         mnThreadId = GetCurrentThreadId();
169         return sal_True;
170     }
171     else
172         return sal_False;
173 }
174 
175 // -----------------------------------------------------------------------
176 
177 ULONG SalYieldMutex::GetAcquireCount( ULONG nThreadId )
178 {
179     if ( nThreadId == mnThreadId )
180         return mnCount;
181     else
182         return 0;
183 }
184 
185 // -----------------------------------------------------------------------
186 
187 void ImplSalYieldMutexAcquireWithWait()
188 {
189     Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
190     if ( !pInst )
191         return;
192 
193     // If we are the main thread, then we must wait with wait, because
194     // in if we don't reschedule, then we create deadlocks if a Windows
195     // Function is called from another thread. If we arn't the main thread,
196     // than we call qcquire directly.
197     ULONG nThreadId = GetCurrentThreadId();
198     SalData* pSalData = GetSalData();
199     if ( pSalData->mnAppThreadId == nThreadId )
200     {
201         // Wenn wir den Mutex nicht bekommen, muessen wir solange
202         // warten, bis wir Ihn bekommen
203         BOOL bAcquire = FALSE;
204         do
205         {
206             if ( pInst->mpSalYieldMutex->tryToAcquire() )
207                 bAcquire = TRUE;
208             else
209             {
210                 pInst->mpSalWaitMutex->acquire();
211                 if ( pInst->mpSalYieldMutex->tryToAcquire() )
212                 {
213                     bAcquire = TRUE;
214                     pInst->mpSalWaitMutex->release();
215                 }
216                 else
217                 {
218                     pInst->mnYieldWaitCount++;
219                     pInst->mpSalWaitMutex->release();
220                     QMSG aTmpMsg;
221                     WinGetMsg( pSalData->mhAB, &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
222                     pInst->mnYieldWaitCount--;
223                     if ( pInst->mnYieldWaitCount )
224                         WinPostMsg( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0 , 0 );
225                 }
226             }
227         }
228         while ( !bAcquire );
229     }
230     else
231         pInst->mpSalYieldMutex->acquire();
232 }
233 
234 // -----------------------------------------------------------------------
235 
236 BOOL ImplSalYieldMutexTryToAcquire()
237 {
238     Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
239     if ( pInst )
240         return pInst->mpSalYieldMutex->tryToAcquire();
241     else
242         return FALSE;
243 }
244 
245 // -----------------------------------------------------------------------
246 
247 void ImplSalYieldMutexAcquire()
248 {
249     Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
250     if ( pInst )
251         pInst->mpSalYieldMutex->acquire();
252 }
253 
254 // -----------------------------------------------------------------------
255 
256 void ImplSalYieldMutexRelease()
257 {
258     Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
259     if ( pInst )
260         pInst->mpSalYieldMutex->release();
261 }
262 
263 // -----------------------------------------------------------------------
264 
265 ULONG ImplSalReleaseYieldMutex()
266 {
267     Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
268     if ( !pInst )
269         return 0;
270 
271     SalYieldMutex*  pYieldMutex = pInst->mpSalYieldMutex;
272     ULONG           nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
273     ULONG           n = nCount;
274     while ( n )
275     {
276         pYieldMutex->release();
277         n--;
278     }
279 
280     return nCount;
281 }
282 
283 // -----------------------------------------------------------------------
284 
285 void ImplSalAcquireYieldMutex( ULONG nCount )
286 {
287     Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
288     if ( !pInst )
289         return;
290 
291     SalYieldMutex*  pYieldMutex = pInst->mpSalYieldMutex;
292     while ( nCount )
293     {
294         pYieldMutex->acquire();
295         nCount--;
296     }
297 }
298 
299 // -----------------------------------------------------------------------
300 
301 bool Os2SalInstance::CheckYieldMutex()
302 {
303     bool bRet = true;
304     SalData*    pSalData = GetSalData();
305     ULONG       nCurThreadId = GetCurrentThreadId();
306     if ( pSalData->mnAppThreadId != nCurThreadId )
307     {
308         if ( pSalData->mpFirstInstance )
309         {
310             SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
311             if ( pYieldMutex->mnThreadId != nCurThreadId )
312             {
313                 bRet = false;
314             }
315         }
316     }
317     else
318     {
319         if ( pSalData->mpFirstInstance )
320         {
321             SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
322             if ( pYieldMutex->mnThreadId != nCurThreadId )
323             {
324                 bRet = false;
325             }
326         }
327     }
328     return bRet;
329 }
330 
331 // =======================================================================
332 
333 void InitSalData()
334 {
335     SalData* pSalData = new SalData;
336     memset( pSalData, 0, sizeof( SalData ) );
337     SetSalData( pSalData );
338 }
339 
340 // -----------------------------------------------------------------------
341 
342 void DeInitSalData()
343 {
344     SalData* pSalData = GetSalData();
345     if ( pSalData->mpFontMetrics )
346         delete pSalData->mpFontMetrics;
347     delete pSalData;
348     SetSalData( NULL );
349 }
350 
351 // -----------------------------------------------------------------------
352 
353 void InitSalMain()
354 {
355     PPIB pib;
356     PTIB tib;
357     HAB hAB;
358     HMQ hMQ;
359     SalData* pData = GetAppSalData();
360 #if OSL_DEBUG_LEVEL>0
361 printf("InitSalMain\n");
362 #endif
363 
364     // morph application to PM
365     DosGetInfoBlocks(&tib, &pib);
366     // Change flag from VIO to PM:
367     if (pib->pib_ultype==2) pib->pib_ultype = 3;
368 
369     // create anchor block
370     hAB = WinInitialize( 0 );
371     if ( !hAB )
372         return;
373 
374     // create message queue
375     hMQ = WinCreateMsgQueue( hAB, 60 );
376     if ( !hMQ )
377     {
378         WinTerminate( hAB );
379         return;
380     }
381 
382     if ( pData ) // Im AppServer NULL
383     {
384         // Ankerblock und Messagequeue merken
385         pData->mhAB = hAB;
386         pData->mhMQ = hMQ;
387     }
388 
389 }
390 
391 void DeInitSalMain()
392 {
393 #if OSL_DEBUG_LEVEL>0
394 printf("DeInitSalMain\n");
395 #endif
396 
397     SalData* pData = GetAppSalData();
398     // destroy message queue and anchor block
399     WinDestroyMsgQueue( pData->mhMQ );
400     WinTerminate( pData->mhAB );
401 
402 }
403 
404 // -----------------------------------------------------------------------
405 
406 SalInstance* CreateSalInstance()
407 {
408     SalData*        pSalData = GetSalData();
409 
410     // determine the os2 version
411     ULONG nMayor;
412     ULONG nMinor;
413     DosQuerySysInfo( QSV_VERSION_MAJOR, QSV_VERSION_MAJOR, &nMayor, sizeof( nMayor ) );
414     DosQuerySysInfo( QSV_VERSION_MINOR, QSV_VERSION_MINOR, &nMinor, sizeof( nMinor ) );
415     aSalShlData.mnVersion = (USHORT)(nMayor*10 + nMinor);
416 
417     pSalData->mnAppThreadId = GetCurrentThreadId();
418 
419     // register frame class
420     if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_FRAME_CLASSNAME,
421                             (PFNWP)SalFrameWndProc, CS_MOVENOTIFY /* 17/08 CS_HITTEST | CS_MOVENOTIFY */,
422                             SAL_FRAME_WNDEXTRA ) )
423     {
424         return NULL;
425     }
426     // register subframe class
427     if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_SUBFRAME_CLASSNAME,
428                             (PFNWP)SalFrameWndProc, CS_SAVEBITS| CS_MOVENOTIFY,
429                             SAL_FRAME_WNDEXTRA ) )
430     {
431         return NULL;
432     }
433     // register object class
434     if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_COM_CLASSNAME,
435                             (PFNWP)SalComWndProc, 0, 0 ))
436     {
437         return NULL;
438     }
439 
440     HWND hComWnd = WinCreateWindow( HWND_OBJECT, (PCSZ)SAL_COM_CLASSNAME,
441                                     (PCSZ)"", 0, 0, 0, 0, 0,
442                                     HWND_OBJECT, HWND_TOP,
443                                     222, NULL, NULL);
444     if ( !hComWnd )
445         return NULL;
446 
447 #if OSL_DEBUG_LEVEL>0
448     debug_printf("CreateSalInstance hComWnd %x\n", hComWnd);
449 #endif
450     Os2SalInstance* pInst = new Os2SalInstance;
451 
452     // init instance (only one instance in this version !!!)
453     pSalData->mpFirstInstance   = pInst;
454     pInst->mhAB     = pSalData->mhAB;
455     pInst->mhMQ     = pSalData->mhMQ;
456     pInst->mnArgc   = pSalData->mnArgc;
457     pInst->mpArgv   = pSalData->mpArgv;
458     pInst->mhComWnd = hComWnd;
459 
460     // AppIcon ermitteln
461     ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, pInst->mhAppIcon);
462 
463     // init static GDI Data
464     ImplInitSalGDI();
465 
466     return pInst;
467 }
468 
469 // -----------------------------------------------------------------------
470 
471 void DestroySalInstance( SalInstance* pInst )
472 {
473     SalData* pSalData = GetSalData();
474 
475     //  (only one instance in this version !!!)
476     ImplFreeSalGDI();
477 
478 #ifdef ENABLE_IME
479     // IME-Daten freigeben
480     if ( pSalData->mpIMEData )
481         ImplReleaseSALIMEData();
482 #endif
483 
484     // reset instance
485     if ( pSalData->mpFirstInstance == pInst )
486         pSalData->mpFirstInstance = NULL;
487 
488     delete pInst;
489 }
490 
491 // -----------------------------------------------------------------------
492 
493 Os2SalInstance::Os2SalInstance()
494 {
495     mhComWnd                = 0;
496     mpSalYieldMutex         = new SalYieldMutex( this );
497     mpSalWaitMutex          = new vos::OMutex;
498     mnYieldWaitCount         = 0;
499     mpSalYieldMutex->acquire();
500     ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex );
501 }
502 
503 // -----------------------------------------------------------------------
504 
505 Os2SalInstance::~Os2SalInstance()
506 {
507     ::tools::SolarMutex::SetSolarMutex( 0 );
508     mpSalYieldMutex->release();
509     delete mpSalYieldMutex;
510     delete mpSalWaitMutex;
511     WinDestroyWindow( mhComWnd);
512 }
513 
514 // -----------------------------------------------------------------------
515 
516 vos::IMutex* Os2SalInstance::GetYieldMutex()
517 {
518     return mpSalYieldMutex;
519 }
520 // -----------------------------------------------------------------------
521 
522 ULONG Os2SalInstance::ReleaseYieldMutex()
523 {
524     return ImplSalReleaseYieldMutex();
525 }
526 
527 // -----------------------------------------------------------------------
528 
529 void Os2SalInstance::AcquireYieldMutex( ULONG nCount )
530 {
531     ImplSalAcquireYieldMutex( nCount );
532 }
533 
534 // -----------------------------------------------------------------------
535 
536 static void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents )
537 {
538     QMSG            aMsg;
539     bool bWasMsg = false, bOneEvent = false;
540     bool bQuit = false;
541 
542     Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
543     int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
544     do
545     {
546         if ( WinPeekMsg( pInst->mhAB, &aMsg, 0, 0, 0, PM_REMOVE ) )
547         {
548             WinDispatchMsg( pInst->mhAB, &aMsg );
549             bOneEvent = bWasMsg = true;
550             if (aMsg.msg == WM_QUIT)
551                 bQuit = true;
552         }
553         else
554             bOneEvent = false;
555     } while( --nMaxEvents && bOneEvent );
556 
557     if ( bWait && ! bWasMsg )
558     {
559         if ( WinGetMsg( pInst->mhAB, &aMsg, 0, 0, 0 ) )
560             WinDispatchMsg( pInst->mhAB, &aMsg );
561         else
562             bQuit = true;
563     }
564 
565     if (bQuit)
566     {
567         ImplSalYieldMutexAcquireWithWait();
568         Os2SalFrame*   pFrame = GetSalData()->mpFirstFrame;
569         if ( pFrame )
570         {
571             if (pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 ))
572                 WinCancelShutdown( pFrame->mhAB, FALSE );
573         }
574         ImplSalYieldMutexRelease();
575     }
576 
577 }
578 
579 // -----------------------------------------------------------------------
580 
581 void Os2SalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
582 {
583     SalYieldMutex*  pYieldMutex = mpSalYieldMutex;
584     SalData*        pSalData = GetSalData();
585     ULONG           nCurThreadId = GetCurrentThreadId();
586     ULONG           nCount = pYieldMutex->GetAcquireCount( nCurThreadId );
587     ULONG           n = nCount;
588     while ( n )
589     {
590         pYieldMutex->release();
591         n--;
592     }
593     if ( pSalData->mnAppThreadId != nCurThreadId )
594     {
595         // #97739# A SendMessage call blocks until the called thread (here: the main thread)
596         // returns. During a yield however, messages are processed in the main thread that might
597         // result in a new message loop due to opening a dialog. Thus, SendMessage would not
598         // return which will block this thread!
599         // Solution: just give up the time slice and hope that messages are processed
600         // by the main thread anyway (where all windows are created)
601         // If the mainthread is not currently handling messages, then our SendMessage would
602         // also do nothing, so this seems to be reasonable.
603 
604         // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
605         if( ImplGetSVData()->maAppData.mnModalMode )
606             DosSleep(1);
607         else
608             WinSendMsg( mhComWnd, SAL_MSG_THREADYIELD, (MPARAM)bWait, (MPARAM)bHandleAllCurrentEvents );
609 
610         n = nCount;
611         while ( n )
612         {
613             pYieldMutex->acquire();
614             n--;
615         }
616     }
617     else
618     {
619         ImplSalYield( bWait, bHandleAllCurrentEvents );
620 
621         n = nCount;
622         while ( n )
623         {
624             ImplSalYieldMutexAcquireWithWait();
625             n--;
626         }
627     }
628 }
629 
630 // -----------------------------------------------------------------------
631 
632 MRESULT EXPENTRY SalComWndProc( HWND hWnd, ULONG nMsg,
633                                 MPARAM nMP1, MPARAM nMP2 )
634 {
635     //debug_printf( "SalComWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
636 
637     switch ( nMsg )
638     {
639         case SAL_MSG_PRINTABORTJOB:
640             //ImplSalPrinterAbortJobAsync( (HDC)wParam );
641             break;
642         case SAL_MSG_THREADYIELD:
643             ImplSalYield( (bool)nMP1, (bool) nMP2);
644             return 0;
645         // If we get this message, because another GetMessage() call
646         // has recieved this message, we must post this message to
647         // us again, because in the other case we wait forever.
648         case SAL_MSG_RELEASEWAITYIELD:
649             {
650             Os2SalInstance* pInst = GetSalData()->mpFirstInstance;
651             if ( pInst && pInst->mnYieldWaitCount )
652                 WinPostMsg( hWnd, SAL_MSG_RELEASEWAITYIELD, nMP1, nMP2 );
653             }
654             return 0;
655         case SAL_MSG_STARTTIMER:
656             ImplSalStartTimer( (ULONG)nMP2, FALSE);
657             return 0;
658         case SAL_MSG_CREATEFRAME:
659             return (MRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)nMP2, (ULONG)nMP1 );
660         case SAL_MSG_DESTROYFRAME:
661             delete (SalFrame*)nMP2;
662             return 0;
663         case SAL_MSG_DESTROYHWND:
664             //We only destroy the native window here. We do NOT destroy the SalFrame contained
665             //in the structure (GetWindowPtr()).
666             if (WinDestroyWindow((HWND)nMP2) == 0)
667             {
668                 OSL_ENSURE(0, "DestroyWindow failed!");
669                 //Failure: We remove the SalFrame from the window structure. So we avoid that
670                 // the window structure may contain an invalid pointer, once the SalFrame is deleted.
671                SetWindowPtr((HWND)nMP2, 0);
672             }
673             return 0;
674         case SAL_MSG_CREATEOBJECT:
675             return (MRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (Os2SalFrame*)(ULONG)nMP2 );
676         case SAL_MSG_DESTROYOBJECT:
677             delete (SalObject*)nMP2;
678             return 0;
679         case SAL_MSG_CREATESOUND:
680             //return (MRESULT)((Os2SalSound*)nMP2)->ImplCreate();
681             return 0;
682         case SAL_MSG_DESTROYSOUND:
683             //((Os2SalSound*)nMP2)->ImplDestroy();
684             return 0;
685         case SAL_MSG_POSTTIMER:
686             SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, (ULONG)nMP2 );
687             break;
688         case WM_TIMER:
689             SalTimerProc( hWnd, 0, 0, 0 );
690             break;
691     }
692 
693     return WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
694 }
695 
696 // -----------------------------------------------------------------------
697 
698 bool Os2SalInstance::AnyInput( USHORT nType )
699 {
700     SalData* pSalData = GetSalData();
701     QMSG    aQMSG;
702 
703     if ( (nType & (INPUT_ANY)) == INPUT_ANY )
704     {
705         // Any Input
706         if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, 0, 0, PM_NOREMOVE ) )
707             return TRUE;
708     }
709     else
710     {
711         if ( nType & INPUT_MOUSE )
712         {
713             // Test auf Mouseinput
714             if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
715                              WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE ) )
716                 return TRUE;
717         }
718 
719         if ( nType & INPUT_KEYBOARD )
720         {
721             // Test auf Keyinput
722             if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
723                              WM_CHAR, WM_CHAR, PM_NOREMOVE ) )
724                 return !(SHORT1FROMMP( aQMSG.mp1 ) & KC_KEYUP);
725         }
726 
727         if ( nType & INPUT_PAINT )
728         {
729             // Test auf Paintinput
730             if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
731                              WM_PAINT, WM_PAINT, PM_NOREMOVE ) )
732                 return TRUE;
733         }
734 
735         if ( nType & INPUT_TIMER )
736         {
737             // Test auf Timerinput
738             if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0,
739                              WM_TIMER, WM_TIMER, PM_NOREMOVE ) )
740                 return TRUE;
741         }
742 
743         if ( nType & INPUT_OTHER )
744         {
745             // Test auf sonstigen Input
746             if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, 0, 0, PM_NOREMOVE ) )
747                 return TRUE;
748         }
749     }
750 
751     return FALSE;
752 }
753 
754 // -----------------------------------------------------------------------
755 
756 SalFrame* Os2SalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle )
757 {
758     // Um auf Main-Thread umzuschalten
759     return (SalFrame*)WinSendMsg( mhComWnd, SAL_MSG_CREATEFRAME, (MPARAM)nSalFrameStyle, (MPARAM)pSystemParentData->hWnd );
760 }
761 
762 // -----------------------------------------------------------------------
763 
764 SalFrame* Os2SalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle )
765 {
766     // Um auf Main-Thread umzuschalten
767     HWND mhWndClient;
768 //31/05/06 YD use client as owner(parent) so positioning will not need to
769 // take care of borders and captions
770     if ( pParent )
771         mhWndClient = static_cast<Os2SalFrame*>(pParent)->mhWndClient;
772     else
773         mhWndClient = 0;
774     return (SalFrame*)WinSendMsg( mhComWnd, SAL_MSG_CREATEFRAME, (MPARAM)nSalFrameStyle, (MPARAM)mhWndClient );
775 }
776 
777 
778 // -----------------------------------------------------------------------
779 
780 void Os2SalInstance::DestroyFrame( SalFrame* pFrame )
781 {
782     WinSendMsg( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (MPARAM)pFrame );
783 }
784 
785 // -----------------------------------------------------------------------
786 
787 SalObject* Os2SalInstance::CreateObject( SalFrame* pParent,
788                                          SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows
789                                          BOOL /*bShow*/ )
790 {
791     // Um auf Main-Thread umzuschalten
792     return (SalObject*)WinSendMsg( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (MPARAM)pParent );
793 }
794 
795 
796 // -----------------------------------------------------------------------
797 
798 void Os2SalInstance::DestroyObject( SalObject* pObject )
799 {
800     WinSendMsg( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (MPARAM)pObject );
801 }
802 
803 // -----------------------------------------------------------------------
804 
805 void* Os2SalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
806 {
807     rReturnedBytes  = 1;
808     rReturnedType   = AsciiCString;
809     return (void*) "";
810 }
811 
812 void Os2SalInstance::AddToRecentDocumentList(const rtl::OUString& /*rFileUrl*/, const rtl::OUString& /*rMimeType*/)
813 {
814 }
815 
816 // -----------------------------------------------------------------------
817 
818 SalTimer* Os2SalInstance::CreateSalTimer()
819 {
820     return new Os2SalTimer();
821 }
822 
823 // -----------------------------------------------------------------------
824 
825 SalBitmap* Os2SalInstance::CreateSalBitmap()
826 {
827     return new Os2SalBitmap();
828 }
829 
830 // -----------------------------------------------------------------------
831 
832 class Os2ImeStatus : public SalI18NImeStatus
833 {
834   public:
835     Os2ImeStatus() {}
836     virtual ~Os2ImeStatus() {}
837 
838     // asks whether there is a status window available
839     // to toggle into menubar
840     virtual bool canToggle() { return false; }
841     virtual void toggle() {}
842 };
843 
844 SalI18NImeStatus* Os2SalInstance::CreateI18NImeStatus()
845 {
846     return new Os2ImeStatus();
847 }
848 
849 // -----------------------------------------------------------------------
850 
851 const ::rtl::OUString& SalGetDesktopEnvironment()
852 {
853     static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "OS/2" ) );
854     return aDesktopEnvironment;
855 }
856 
857 SalSession* Os2SalInstance::CreateSalSession()
858 {
859     return NULL;
860 }
861 
862