/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <string.h>

#define INCL_DOS
#define INCL_PM
#define INCL_WIN
#include <svpm.h>

// =======================================================================

#define _SV_SALFRAME_CXX

#ifndef DEBUG_HXX
#include <tools/debug.hxx>
#endif

#define private public

#ifndef _SV_SALLANG_HXX
#include <sallang.hxx>
#endif
#ifndef _SV_SALIDS_HRC
#include <salids.hrc>
#endif
#include <saldata.hxx>
#include <salinst.h>
#include <salgdi.h>
#include <salframe.h>
#include <vcl/timer.hxx>
#include <vcl/settings.hxx>
#ifndef _SV_KEYCOES_HXX
#include <vcl/keycodes.hxx>
#endif
#include <saltimer.h>

#if OSL_DEBUG_LEVEL>10
extern "C" int debug_printf(const char *f, ...);

static BOOL _bCapture;

#else
#define debug_printf( ...) { 1; }
#endif

// =======================================================================

HPOINTER ImplLoadPointer( ULONG nId );

static void SetMaximizedFrameGeometry( HWND hWnd, Os2SalFrame* pFrame );
static void UpdateFrameGeometry( HWND hWnd, Os2SalFrame* pFrame );
static void ImplSalCalcFrameSize( HWND hWnd,
                                  LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY );
static void ImplSalCalcFrameSize( const Os2SalFrame* pFrame,
                                  LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY );
MRESULT EXPENTRY SalFrameSubClassWndProc( HWND hWnd, ULONG nMsg,
                                  MPARAM nMP1, MPARAM nMP2 );

// =======================================================================

static LanguageType eImplKeyboardLanguage = LANGUAGE_DONTKNOW;
BOOL Os2SalFrame::mbInReparent = FALSE;
ULONG Os2SalFrame::mnInputLang = 0;

// =======================================================================

// define a new flag
#define SWP_CENTER			(SWP_NOAUTOCLOSE<<4)
#define SWP_SHOWMAXIMIZED	(SWP_ACTIVATE | SWP_SHOW | SWP_MAXIMIZE)
#define SWP_SHOWMINIMIZED	(SWP_ACTIVATE | SWP_SHOW | SWP_MINIMIZE)
#define SWP_SHOWNORMAL		(SWP_ACTIVATE | SWP_SHOW | SWP_RESTORE)

static LONG nScreenHeight  = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN);
static LONG nScreenWidth   = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );

BOOL APIENTRY _WinQueryWindowRect( HWND hwnd, PRECTL prclDest)
{
	BOOL rc = WinQueryWindowRect( hwnd, prclDest);
	ULONG tmp = prclDest->yBottom;
	prclDest->yBottom = prclDest->yTop;
	prclDest->yTop = tmp;
	return rc;
}

BOOL APIENTRY _WinQueryPointerPos (HWND hwndDesktop, PPOINTL pptl)
{
	BOOL rc = WinQueryPointerPos( hwndDesktop, pptl);
	pptl->y = nScreenHeight - pptl->y;
	return rc;
}

BOOL APIENTRY _WinQueryWindowPos( Os2SalFrame* pFrame, PSWP pswp)
{
	SWP swpOwner;
	BOOL rc = WinQueryWindowPos( pFrame->mhWndFrame, pswp);

#if OSL_DEBUG_LEVEL>1
	debug_printf( "> WinQueryWindowPos hwnd %x at %d,%d (%dx%d)\n", 
					pFrame->mhWndFrame, pswp->x, pswp->y, pswp->cx, pswp->cy);
#endif

	Os2SalFrame* pParentFrame = pFrame->mpParentFrame;

	//YD adjust to owner coordinates
	if ( pParentFrame )
	{
		POINTL ptlOwner = {0};
		
		// coords are relative to screen, map to parent frame client area 
		ptlOwner.x = pswp->x;
		ptlOwner.y = pswp->y;
		WinMapWindowPoints( HWND_DESKTOP, pParentFrame->mhWndClient, &ptlOwner, 1);			
		pswp->x = ptlOwner.x;
		pswp->y = ptlOwner.y;
		// get parent client area size
		WinQueryWindowPos( pParentFrame->mhWndClient, &swpOwner);
	} else
	{
		// no owner info, use DESKTOP????
		swpOwner.cx = nScreenWidth;
		swpOwner.cy = nScreenHeight;
	}

	// invert Y coordinate
	pswp->y = swpOwner.cy - (pswp->y + pswp->cy);

#if OSL_DEBUG_LEVEL>1
	debug_printf( "< WinQueryWindowPos hwnd %x at %d,%d (%dx%d)\n", 
					pFrame->mhWndFrame, pswp->x, pswp->y, pswp->cx, pswp->cy);
#endif
	return rc;
}

BOOL APIENTRY _WinSetWindowPos( Os2SalFrame* pFrame, HWND hwndInsertBehind, LONG x, LONG y,
    LONG cx, LONG cy, ULONG fl)
{
	SWP 	swpOwner = {0};
	POINTL 	ptlOwner = {0};
	HWND	hParent = NULL;

#if OSL_DEBUG_LEVEL>1
	debug_printf( ">WinSetWindowPos hwnd %x at %d,%d (%dx%d) fl 0x%08x\n", 
					pFrame->mhWndFrame, x, y, cx, cy, fl);
#endif

	// first resize window if requested
	if ( (fl & SWP_SIZE) ) { 
		ULONG	flag = SWP_SIZE;
		LONG	nX = 0, nY = 0;
		LONG	frameFrameX, frameFrameY, frameCaptionY;

		ImplSalCalcFrameSize( pFrame, frameFrameX, frameFrameY, frameCaptionY );
		// if we change y size, we need to move the window down
		// because os2 window origin is lower left corner
		if (pFrame->maGeometry.nHeight != cy) {
			SWP		aSWP;
			WinQueryWindowPos( pFrame->mhWndFrame, &aSWP);
			nX = aSWP.x;
			nY = aSWP.y - (cy + 2*frameFrameY + frameCaptionY - aSWP.cy);
			flag |= SWP_MOVE;
		}
		WinSetWindowPos( pFrame->mhWndFrame, NULL, nX, nY, 
			cx+2*frameFrameX, cy+2*frameFrameY+frameCaptionY, flag);
		fl = fl & ~SWP_SIZE;
	}
	else // otherwise get current size
	{
		SWP swp = {0};
		WinQueryWindowPos( pFrame->mhWndClient, &swp);
		cx = swp.cx;
		cy = swp.cy;
	}

	// get parent window handle
	Os2SalFrame* pParentFrame = pFrame->mpParentFrame;

	// use desktop if parent is not defined
	hParent = pParentFrame ? pParentFrame->mhWndClient : HWND_DESKTOP;
	// if parent is not visible, use desktop as reference
	hParent = WinIsWindowVisible( hParent) ? hParent : HWND_DESKTOP;

	WinQueryWindowPos( hParent, &swpOwner);

	//YD adjust to owner coordinates only when moving and not centering
	//if (!(fl & SWP_CENTER) && (fl & SWP_MOVE)) 
	if ((fl & SWP_MOVE)) 
	{

		// if SWP_CENTER is specified, change position to parent center
		if (fl & SWP_CENTER) {
			ptlOwner.x = (swpOwner.cx - cx) / 2;
			ptlOwner.y = (swpOwner.cy - cy) / 2;
#if OSL_DEBUG_LEVEL>0
			debug_printf( "_WinSetWindowPos SWP_CENTER\n");
#endif
			fl = fl & ~SWP_CENTER;
		} else {  
			// coords are relative to parent frame client area, map to screen 
			// map Y to OS/2 system coordinates
			ptlOwner.x = x;
			ptlOwner.y = swpOwner.cy - (y + cy);

#if OSL_DEBUG_LEVEL>0
			debug_printf( "_WinSetWindowPos owner 0x%x at %d,%d (%dx%d) OS2\n", 
				hParent, ptlOwner.x, ptlOwner.y, swpOwner.cx, swpOwner.cy);
#endif
		}
		// map from client area to screen
		WinMapWindowPoints( hParent, HWND_DESKTOP, &ptlOwner, 1);			
		x = ptlOwner.x;
		y = ptlOwner.y;

#if OSL_DEBUG_LEVEL>0
		debug_printf( "_WinSetWindowPos owner 0x%x at %d,%d (%dx%d) MAPPED OS2\n", 
			hParent, ptlOwner.x, ptlOwner.y, swpOwner.cx, swpOwner.cy);
#endif
	}

#if OSL_DEBUG_LEVEL>0
	debug_printf( "<WinSetWindowPos hwnd %x at %d,%d (%dx%d) fl=%x\n", 
					pFrame->mhWndFrame, x, y, cx, cy, fl);
#endif
	return WinSetWindowPos( pFrame->mhWndFrame, hwndInsertBehind, x, y, 0, 0, fl);
}

// =======================================================================

#if OSL_DEBUG_LEVEL > 0
static void dumpWindowInfo( char* fnc, HWND hwnd)
{
	SWP aSWP;
	HWND	hwnd2;
	char	szTitle[256];
	
#if 0
	_WinQueryWindowPos( hwnd, &aSWP );
	strcpy(szTitle,"");
	WinQueryWindowText(hwnd, sizeof(szTitle), szTitle);	
	debug_printf( "%s: window %08x at %d,%d (size %dx%d) '%s'\n", fnc, hwnd,
				aSWP.x, aSWP.y, aSWP.cx, aSWP.cy, szTitle);
	hwnd2 = WinQueryWindow(hwnd, QW_PARENT);
	_WinQueryWindowPos( hwnd2, &aSWP );
	strcpy(szTitle,"");
	WinQueryWindowText(hwnd2, sizeof(szTitle), szTitle);	
	debug_printf( "%s: parent %08x at %d,%d (size %dx%d) '%s'\n", fnc, hwnd2,
				aSWP.x, aSWP.y, aSWP.cx, aSWP.cy, szTitle);
	hwnd2 = WinQueryWindow(hwnd, QW_OWNER);
	_WinQueryWindowPos( hwnd2, &aSWP );
	strcpy(szTitle,"");
	WinQueryWindowText(hwnd2, sizeof(szTitle), szTitle);	
	debug_printf( "%s: owner %08x at %d,%d (size %dx%d) '%s'\n", fnc, hwnd2,
				aSWP.x, aSWP.y, aSWP.cx, aSWP.cy, szTitle);
#endif
}
#endif

// =======================================================================

#ifdef ENABLE_IME

struct ImplSalIMEProc
{
    ULONG       nOrd;
    PFN*        pProc;
};

#define SAL_IME_PROC_COUNT          12

// -----------------------------------------------------------------------

static SalIMEData* GetSalIMEData()
{
    SalData* pSalData = GetSalData();

    if ( !pSalData->mbIMEInit )
    {
        pSalData->mbIMEInit = TRUE;

        HMODULE hMod = 0;
        if ( 0 == DosLoadModule( NULL, 0, "OS2IM", &hMod ) )
        {
            SalIMEData*     pIMEData = new SalIMEData;
            BOOL            bError = FALSE;
            ImplSalIMEProc  aProcAry[SAL_IME_PROC_COUNT] =
            {
            { 101, (PFN*)&(pIMEData->mpAssocIME) },
            { 104, (PFN*)&(pIMEData->mpGetIME) },
            { 106, (PFN*)&(pIMEData->mpReleaseIME) },
            { 117, (PFN*)&(pIMEData->mpSetConversionFont) },
            { 144, (PFN*)&(pIMEData->mpSetConversionFontSize) },
            { 118, (PFN*)&(pIMEData->mpGetConversionString) },
            { 122, (PFN*)&(pIMEData->mpGetResultString) },
            { 115, (PFN*)&(pIMEData->mpSetCandidateWin) },
            { 130, (PFN*)&(pIMEData->mpQueryIMEProperty) },
            { 131, (PFN*)&(pIMEData->mpRequestIME) },
            { 128, (PFN*)&(pIMEData->mpSetIMEMode) },
            { 127, (PFN*)&(pIMEData->mpQueryIMEMode) }
            };

            pIMEData->mhModIME = hMod;
            for ( USHORT i = 0; i < SAL_IME_PROC_COUNT; i++ )
            {
                if ( 0 != DosQueryProcAddr( pIMEData->mhModIME, aProcAry[i].nOrd, 0, aProcAry[i].pProc ) )
                {
                    bError = TRUE;
                    break;
                }
            }

            if ( bError )
            {
                DosFreeModule( pIMEData->mhModIME );
                delete pIMEData;
            }
            else
                pSalData->mpIMEData = pIMEData;
        }
    }

    return pSalData->mpIMEData;
}

// -----------------------------------------------------------------------

void ImplReleaseSALIMEData()
{
    SalData* pSalData = GetSalData();

    if ( pSalData->mpIMEData )
    {
        DosFreeModule( pSalData->mpIMEData->mhModIME );
        delete pSalData->mpIMEData;
    }
}

#endif

// =======================================================================

static void ImplSaveFrameState( Os2SalFrame* pFrame )
{
    // Position, Groesse und Status fuer GetWindowState() merken
    if ( !pFrame->mbFullScreen )
    {
        SWP aSWP;
        BOOL bVisible = WinIsWindowVisible( pFrame->mhWndFrame);

        // Query actual state (maState uses screen coords)
        WinQueryWindowPos( pFrame->mhWndFrame, &aSWP );

        if ( aSWP.fl & SWP_MINIMIZE )
        {
#if OSL_DEBUG_LEVEL>0
			debug_printf("Os2SalFrame::GetWindowState %08x SAL_FRAMESTATE_MINIMIZED\n",
					pFrame->mhWndFrame);
#endif
            pFrame->maState.mnState |= SAL_FRAMESTATE_MINIMIZED;
            if ( bVisible )
                pFrame->mnShowState = SWP_SHOWMAXIMIZED;
        }
        else if ( aSWP.fl & SWP_MAXIMIZE )
        {
#if OSL_DEBUG_LEVEL>0
			debug_printf("Os2SalFrame::GetWindowState %08x SAL_FRAMESTATE_MAXIMIZED\n",
					pFrame->mhWndFrame);
#endif
            pFrame->maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED;
            pFrame->maState.mnState |= SAL_FRAMESTATE_MAXIMIZED;
            if ( bVisible )
                pFrame->mnShowState = SWP_SHOWMINIMIZED;
            pFrame->mbRestoreMaximize = TRUE;
        }
        else
        {
			LONG nFrameX, nFrameY, nCaptionY;
			ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY );
			// to be consistent with Unix, the frame state is without(!) decoration
			long nTopDeco = nFrameY + nCaptionY;
			long nLeftDeco = nFrameX;
			long nBottomDeco = nFrameY;
			long nRightDeco = nFrameX;

            pFrame->maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED);
            // subtract decoration, store screen coords
            pFrame->maState.mnX      = aSWP.x+nLeftDeco;
            pFrame->maState.mnY      = nScreenHeight - (aSWP.y+aSWP.cy)+nTopDeco;
            pFrame->maState.mnWidth  = aSWP.cx-nLeftDeco-nRightDeco;
            pFrame->maState.mnHeight = aSWP.cy-nTopDeco-nBottomDeco;
#if OSL_DEBUG_LEVEL>0
			debug_printf("Os2SalFrame::GetWindowState %08x (%dx%d) at %d,%d VCL\n",
					pFrame->mhWndFrame,
					pFrame->maState.mnWidth,pFrame->maState.mnHeight,pFrame->maState.mnX,pFrame->maState.mnY);
#endif
            if ( bVisible )
                pFrame->mnShowState = SWP_SHOWNORMAL;
            pFrame->mbRestoreMaximize = FALSE;
			//debug_printf( "ImplSaveFrameState: window %08x at %d,%d (size %dx%d)\n", 
			//	pFrame->mhWndFrame,
			//	pFrame->maState.mnX, pFrame->maState.mnY, pFrame->maState.mnWidth, pFrame->maState.mnHeight);
        }
    }
}

// -----------------------------------------------------------------------

long ImplSalCallbackDummy( void*, SalFrame*, USHORT, const void* )
{
    return 0;
}

// -----------------------------------------------------------------------

static void ImplSalCalcFrameSize( HWND hWnd,
                                  LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY )
{
    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
    if ( !pFrame )
        return;
	return ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY );
}

static void ImplSalCalcFrameSize( const Os2SalFrame* pFrame,
                                  LONG& nFrameX, LONG& nFrameY, LONG& nCaptionY )
{
    if ( pFrame->mbSizeBorder )
    {
        nFrameX = WinQuerySysValue( HWND_DESKTOP, SV_CXSIZEBORDER );
        nFrameY = WinQuerySysValue( HWND_DESKTOP, SV_CYSIZEBORDER );
    }
    else if ( pFrame->mbFixBorder )
    {
        nFrameX = WinQuerySysValue( HWND_DESKTOP, SV_CXDLGFRAME );
        nFrameY = WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME );
    }
    else if ( pFrame->mbBorder )
    {
        nFrameX = WinQuerySysValue( HWND_DESKTOP, SV_CXBORDER );
        nFrameY = WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER );
    }
    else
    {
        nFrameX = 0;
        nFrameY = 0;
    }
    if ( pFrame->mbCaption )
        nCaptionY = WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR );
    else
        nCaptionY = 0;
	
#if OSL_DEBUG_LEVEL>0
	//if (_bCapture)
		debug_printf("ImplSalCalcFrameSize 0x%08x x=%d y=%d t=%d\n", pFrame->mhWndFrame, nFrameX, nFrameY, nCaptionY);
#endif
}

// -----------------------------------------------------------------------

static void ImplSalCalcFullScreenSize( const Os2SalFrame* pFrame,
                                       LONG& rX, LONG& rY, LONG& rDX, LONG& rDY )
{
    // set window to screen size
    LONG nFrameX, nFrameY, nCaptionY;
    LONG rScreenDX = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
    LONG rScreenDY = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );

    // Framegroessen berechnen
    ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY );

    rX  = -nFrameX;
    rY  = -(nFrameY+nCaptionY);
    rDX = rScreenDX+(nFrameX*2);
    rDY = rScreenDY+(nFrameY*2)+nCaptionY;
}

// -----------------------------------------------------------------------

static void ImplSalFrameFullScreenPos( Os2SalFrame* pFrame, BOOL bAlways = FALSE )
{
    SWP aSWP;
    _WinQueryWindowPos( pFrame, &aSWP );
    if ( bAlways || !(aSWP.fl & SWP_MINIMIZE) )
    {
        // set window to screen size
        LONG nX;
        LONG nY;
        LONG nWidth;
        LONG nHeight;
        ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight );
        _WinSetWindowPos( pFrame, 0,
                         nX, nY, nWidth, nHeight,
                         SWP_MOVE | SWP_SIZE );
    }
}

// -----------------------------------------------------------------------

// Uebersetzungstabelle von System-Keycodes in StarView-Keycodes
#define KEY_TAB_SIZE     (VK_ENDDRAG+1)

static USHORT aImplTranslateKeyTab[KEY_TAB_SIZE] =
{
    // StarView-Code      System-Code                         Index
    0,                    //                                  0x00
    0,                    // VK_BUTTON1                       0x01
    0,                    // VK_BUTTON2                       0x02
    0,                    // VK_BUTTON3                       0x03
    0,                    // VK_BREAK                         0x04
    KEY_BACKSPACE,        // VK_BACKSPACE                     0x05
    KEY_TAB,              // VK_TAB                           0x06
    KEY_TAB,              // VK_BACKTAB                       0x07
    KEY_RETURN,           // VK_NEWLINE                       0x08
    0,                    // VK_SHIFT                         0x09
    0,                    // VK_CTRL                          0x0A
    0,                    // VK_ALT                           0x0B
    0,                    // VK_ALTGRAF                       0x0C
    0,                    // VK_PAUSE                         0x0D
    0,                    // VK_CAPSLOCK                      0x0E
    KEY_ESCAPE,           // VK_ESC                           0x0F
    KEY_SPACE,            // VK_SPACE                         0x10
    KEY_PAGEUP,           // VK_PAGEUP                        0x11
    KEY_PAGEDOWN,         // VK_PAGEDOWN                      0x12
    KEY_END,              // VK_END                           0x13
    KEY_HOME,             // VK_HOME                          0x14
    KEY_LEFT,             // VK_LEFT                          0x15
    KEY_UP,               // VK_UP                            0x16
    KEY_RIGHT,            // VK_RIGHT                         0x17
    KEY_DOWN,             // VK_DOWN                          0x18
    0,                    // VK_PRINTSCRN                     0x19
    KEY_INSERT,           // VK_INSERT                        0x1A
    KEY_DELETE,           // VK_DELETE                        0x1B
    0,                    // VK_SCRLLOCK                      0x1C
    0,                    // VK_NUMLOCK                       0x1D
    KEY_RETURN,           // VK_ENTER                         0x1E
    0,                    // VK_SYSRQ                         0x1F
    KEY_F1,               // VK_F1                            0x20
    KEY_F2,               // VK_F2                            0x21
    KEY_F3,               // VK_F3                            0x22
    KEY_F4,               // VK_F4                            0x23
    KEY_F5,               // VK_F5                            0x24
    KEY_F6,               // VK_F6                            0x25
    KEY_F7,               // VK_F7                            0x26
    KEY_F8,               // VK_F8                            0x27
    KEY_F9,               // VK_F9                            0x28
    KEY_F10,              // VK_F10                           0x29
    KEY_F11,              // VK_F11                           0x2A
    KEY_F12,              // VK_F12                           0x2B
    KEY_F13,              // VK_F13                           0x2C
    KEY_F14,              // VK_F14                           0x2D
    KEY_F15,              // VK_F15                           0x2E
    KEY_F16,              // VK_F16                           0x2F
    KEY_F17,              // VK_F17                           0x30
    KEY_F18,              // VK_F18                           0x31
    KEY_F19,              // VK_F19                           0x32
    KEY_F20,              // VK_F20                           0x33
    KEY_F21,              // VK_F21                           0x34
    KEY_F22,              // VK_F22                           0x35
    KEY_F23,              // VK_F23                           0x36
    KEY_F24,              // VK_F24                           0x37
    0                     // VK_ENDDRAG                       0x38
};

// =======================================================================

SalFrame* ImplSalCreateFrame( Os2SalInstance* pInst, HWND hWndParent, ULONG nSalFrameStyle )
{
    SalData*    	pSalData = GetSalData();
    Os2SalFrame*   	pFrame = new Os2SalFrame;
    HWND        	hWndFrame;
    HWND        	hWndClient;
    ULONG    		nFrameFlags = FCF_NOBYTEALIGN | FCF_SCREENALIGN;
    ULONG    		nFrameStyle = 0;
    ULONG    		nClientStyle = WS_CLIPSIBLINGS;
    BOOL        	bSubFrame = FALSE;

#if OSL_DEBUG_LEVEL>0
    debug_printf(">ImplSalCreateFrame hWndParent 0x%x, nSalFrameStyle 0x%x\n", hWndParent, nSalFrameStyle);
#endif

	if ( hWndParent )
	{
		bSubFrame = TRUE;
		pFrame->mbNoIcon = TRUE;
	}

    // determine creation data (bei Moveable nehmen wir DLG-Border, damit
    // es besser aussieht)
    if ( nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE )
        nFrameFlags |= FCF_CLOSEBUTTON;

	if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE ) {
		pFrame->mbCaption = TRUE;
		nFrameStyle = WS_ANIMATE;
		nFrameFlags |= FCF_SYSMENU | FCF_TITLEBAR | FCF_DLGBORDER;
		if ( !hWndParent )
			nFrameFlags |= FCF_MINBUTTON;

		if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE )
		{
			pFrame->mbSizeBorder = TRUE;
			nFrameFlags |= FCF_SIZEBORDER;
			if ( !hWndParent )
				nFrameFlags |= FCF_MAXBUTTON;
		}
		else
			pFrame->mbFixBorder = TRUE;

		// add task list style if not a tool window
		if ( !(nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW) ) {
			nFrameFlags |= FCF_TASKLIST;
		}
	}
	
	if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW )
	{
		pFrame->mbNoIcon = TRUE;
		// YD gives small caption -> nExSysStyle |= WS_EX_TOOLWINDOW;
	}

    if ( nSalFrameStyle & SAL_FRAME_STYLE_FLOAT )
    {
        //nExSysStyle |= WS_EX_TOOLWINDOW;
        pFrame->mbFloatWin = TRUE;
    }
    //if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP )
    //    nExSysStyle |= WS_EX_TOPMOST;

    // init frame data
    pFrame->mnStyle = nSalFrameStyle;

    // determine show style
    pFrame->mnShowState = SWP_SHOWNORMAL;

    // create frame
	//YD FIXME this is a potential bug with multiple threads and cuncurrent
	//window creation, because this field is accessed in
	//WM_CREATE to get window data, 
    pSalData->mpCreateFrame = pFrame;

	//YD FIXME if SAL_FRAME_CHILD is specified, use hWndParent as parent handle...
    hWndFrame = WinCreateStdWindow( HWND_DESKTOP, nFrameStyle, &nFrameFlags,
					(PSZ)(bSubFrame ? SAL_SUBFRAME_CLASSNAME : SAL_FRAME_CLASSNAME), 
					NULL,
					nClientStyle, 0, 0, &hWndClient );
    debug_printf("ImplSalCreateFrame hWndParent 0x%x, hWndFrame 0x%x, hWndClient 0x%x\n", hWndParent, hWndFrame, hWndClient);
    if ( !hWndFrame )
    {
        delete pFrame;
        return NULL;
    }

    // Parent setzen (Owner)
    if ( hWndParent != 0 && hWndParent != HWND_DESKTOP ) 
        WinSetOwner( hWndFrame, hWndParent );

    Os2SalFrame* pParentFrame = GetWindowPtr( hWndParent );
    if ( pParentFrame )
		pFrame->mpParentFrame = pParentFrame;

    // Icon setzen (YD win32 does it in the class registration)
    if ( nFrameFlags & FCF_MINBUTTON )
        WinSendMsg( hWndFrame, WM_SETICON, (MPARAM)pInst->mhAppIcon, (MPARAM)0 );

    // If we have an Window with an Caption Bar and without
    // an MaximizeBox, we change the SystemMenu
    if ( (nFrameFlags & (FCF_TITLEBAR | FCF_MAXBUTTON)) == (FCF_TITLEBAR) )
    {
        HWND hSysMenu = WinWindowFromID( hWndFrame, FID_SYSMENU );
        if ( hSysMenu )
        {
            if ( !(nFrameFlags & (FCF_MINBUTTON | FCF_MAXBUTTON)) )
				WinEnableMenuItem(hSysMenu, SC_RESTORE, FALSE);
            if ( !(nFrameFlags & FCF_MINBUTTON) )
				WinEnableMenuItem(hSysMenu, SC_MINIMIZE, FALSE);
            if ( !(nFrameFlags & FCF_MAXBUTTON) )
				WinEnableMenuItem(hSysMenu, SC_MAXIMIZE, FALSE);
            if ( !(nFrameFlags & FCF_SIZEBORDER) )
				WinEnableMenuItem(hSysMenu, SC_SIZE, FALSE);
        }
    }
    if ( (nFrameFlags & FCF_SYSMENU) && !(nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE) )
    {
        HWND hSysMenu = WinWindowFromID( hWndFrame, FID_SYSMENU );
        if ( hSysMenu )
        {
            WinEnableMenuItem(hSysMenu, SC_CLOSE, FALSE);
        }
    }

    // ticket#124 subclass frame window: we need to intercept TRACK message
    aSalShlData.mpFrameProc = WinSubclassWindow( hWndFrame, SalFrameSubClassWndProc);

    // init OS/2 frame data
    pFrame->mhAB            = pInst->mhAB;

    // YD 18/08 under OS/2, invisible frames have size 0,0 at 0,0, so 
    // we need to set an initial size/position manually
    SWP aSWP;
    memset( &aSWP, 0, sizeof( aSWP ) );
    WinQueryTaskSizePos( pInst->mhAB, 0, &aSWP );
    WinSetWindowPos( hWndFrame, NULL, aSWP.x, aSWP.y, aSWP.cx, aSWP.cy,
                     SWP_MOVE | SWP_SIZE);

#ifdef ENABLE_IME
    // Input-Context einstellen
    SalIMEData* pIMEData = GetSalIMEData();
    if ( pIMEData )
    {
        pFrame->mhIMEContext = 0;
        if ( 0 != pIMEData->mpAssocIME( hWndClient, pFrame->mhIMEContext, &pFrame->mhDefIMEContext ) )
            pFrame->mhDefIMEContext = 0;
    }
    else
    {
        pFrame->mhIMEContext = 0;
        pFrame->mhDefIMEContext = 0;
    }
#endif

    RECTL rectl;
    _WinQueryWindowRect( hWndClient, &rectl );
    pFrame->mnWidth  = rectl.xRight;
    pFrame->mnHeight = rectl.yBottom;
    debug_printf( "ImplSalCreateFrame %dx%d\n", pFrame->mnWidth, pFrame->mnHeight);
    ImplSaveFrameState( pFrame );
    pFrame->mbDefPos = TRUE;

	UpdateFrameGeometry( hWndFrame, pFrame );

    if( pFrame->mnShowState == SWP_SHOWMAXIMIZED )
	{
		// #96084 set a useful internal window size because
		// the window will not be maximized (and the size updated) before show()
        SetMaximizedFrameGeometry( hWndFrame, pFrame );
	}

#if OSL_DEBUG_LEVEL > 1
	dumpWindowInfo( "<ImplSalCreateFrame (exit)", hWndFrame);
#endif

    return pFrame;
}

// =======================================================================

Os2SalFrame::Os2SalFrame()
{
    SalData* pSalData = GetSalData();

    mbGraphics          = NULL;
    mhPointer           = WinQuerySysPointer( HWND_DESKTOP, SPTR_ARROW, FALSE );
    mpGraphics          = NULL;
    mpInst              = NULL;
    mbFullScreen        = FALSE;
    mbAllwayOnTop       = FALSE;
    mbVisible           = FALSE;
    mbMinHide           = FALSE;
    mbInShow            = FALSE;
    mbRestoreMaximize   = FALSE;
    mbInMoveMsg         = FALSE;
    mbInSizeMsg         = FALSE;
    mbDefPos            = TRUE;
    mbOverwriteState    = TRUE;
    mbHandleIME         = FALSE;
    mbConversionMode    = FALSE;
    mbCandidateMode     = FALSE;
    mbCaption           = FALSE;
    //mhDefIMEContext     = 0;
    mpGraphics          = NULL;
    mnShowState         = SWP_SHOWNORMAL;
    mnWidth             = 0;
    mnHeight            = 0;
    mnMinWidth          = 0;
    mnMinHeight         = 0;
    mnMaxWidth          = SHRT_MAX;
    mnMaxHeight         = SHRT_MAX;
    mnInputLang         = 0;
    mnKeyboardHandle    = 0;
    mbGraphics          = FALSE;
    mbCaption           = FALSE;
    mbBorder            = FALSE;
    mbFixBorder         = FALSE;
    mbSizeBorder        = FALSE;
    mbFullScreen        = FALSE;
    //mbPresentation      = FALSE;
    mbInShow            = FALSE;
    mbRestoreMaximize   = FALSE;
    mbInMoveMsg         = FALSE;
    mbInSizeMsg         = FALSE;
    //mbFullScreenToolWin = FALSE;
    mbDefPos            = TRUE;
    mbOverwriteState    = TRUE;
    //mbIME               = FALSE;
    mbHandleIME         = FALSE;
    //mbSpezIME           = FALSE;
    //mbAtCursorIME       = FALSE;
    mbCandidateMode     = FALSE;
    mbFloatWin          = FALSE;
    mbNoIcon            = FALSE;
    //mSelectedhMenu      = 0;
    //mLastActivatedhMenu = 0;
	mpParentFrame		= NULL;

    memset( &maState, 0, sizeof( SalFrameState ) );
    maSysData.nSize     = sizeof( SystemEnvData );
    memset( &maGeometry, 0, sizeof( maGeometry ) );

    // insert frame in framelist
    mpNextFrame = pSalData->mpFirstFrame;
    pSalData->mpFirstFrame = this;
}

// -----------------------------------------------------------------------

Os2SalFrame::~Os2SalFrame()
{
    SalData* pSalData = GetSalData();

    // destroy DC
    if ( mpGraphics )
    {
        ImplSalDeInitGraphics( mpGraphics );
        WinReleasePS( mpGraphics->mhPS );
        delete mpGraphics;
    }

    // destroy system frame
    WinDestroyWindow( mhWndFrame );

    // remove frame from framelist
    if ( this == pSalData->mpFirstFrame )
        pSalData->mpFirstFrame = mpNextFrame;
    else
    {
        Os2SalFrame* pTempFrame = pSalData->mpFirstFrame;
        while ( pTempFrame->mpNextFrame != this )
            pTempFrame = pTempFrame->mpNextFrame;

        pTempFrame->mpNextFrame = mpNextFrame;
    }
}

// -----------------------------------------------------------------------

static HDC ImplWinGetDC( HWND hWnd )
{
    HDC hDC = WinQueryWindowDC( hWnd );
    if ( !hDC )
        hDC = WinOpenWindowDC( hWnd );
    return hDC;
}

// -----------------------------------------------------------------------

SalGraphics* Os2SalFrame::GetGraphics()
{
    if ( mbGraphics )
        return NULL;

    if ( !mpGraphics )
    {
        SalData* pSalData = GetSalData();
        mpGraphics = new Os2SalGraphics;
        mpGraphics->mhPS      = WinGetPS( mhWndClient );
        mpGraphics->mhDC      = ImplWinGetDC( mhWndClient );
        mpGraphics->mhWnd     = mhWndClient;
        mpGraphics->mnHeight  = mnHeight;
        mpGraphics->mbPrinter = FALSE;
        mpGraphics->mbVirDev  = FALSE;
        mpGraphics->mbWindow  = TRUE;
        mpGraphics->mbScreen  = TRUE;
        ImplSalInitGraphics( mpGraphics );
        mbGraphics = TRUE;
    }
    else
        mbGraphics = TRUE;

    return mpGraphics;
}

// -----------------------------------------------------------------------

void Os2SalFrame::ReleaseGraphics( SalGraphics* )
{
    mbGraphics = FALSE;
}

// -----------------------------------------------------------------------

BOOL Os2SalFrame::PostEvent( void* pData )
{
    return (BOOL)WinPostMsg( mhWndClient, SAL_MSG_USEREVENT, 0, (MPARAM)pData );
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetTitle( const XubString& rTitle )
{
    // set window title
	ByteString title( rTitle, gsl_getSystemTextEncoding() );
	debug_printf("Os2SalFrame::SetTitle %x '%s'\n", mhWndFrame, title.GetBuffer() );
    WinSetWindowText( mhWndFrame, title.GetBuffer() );
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetIcon( USHORT nIcon )
{
	debug_printf("Os2SalFrame::SetIcon\n");

    // If we have a window without an Icon (for example a dialog), ignore this call
    if ( mbNoIcon )
        return;

    // 0 means default (class) icon
    HPOINTER hIcon = NULL;
    if ( !nIcon )
        nIcon = 1;

    ImplLoadSalIcon( nIcon, hIcon );

    DBG_ASSERT( hIcon , "Os2SalFrame::SetIcon(): Could not load icon !" );

    // Icon setzen
	WinSendMsg( mhWndFrame, WM_SETICON, (MPARAM)hIcon, (MPARAM)0 );
}

// -----------------------------------------------------------------------

SalFrame* Os2SalFrame::GetParent() const
{
	//debug_printf("Os2SalFrame::GetParent\n");
    return GetWindowPtr( WinQueryWindow(mhWndFrame, QW_OWNER) );
}

// -----------------------------------------------------------------------

static void ImplSalShow( HWND hWnd, ULONG bVisible, ULONG bNoActivate )
{
    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
    if ( !pFrame )
        return;

    if ( bVisible )
    {
        pFrame->mbDefPos = FALSE;
        pFrame->mbOverwriteState = TRUE;
        pFrame->mbInShow = TRUE;

#if OSL_DEBUG_LEVEL > 0
		debug_printf( "ImplSalShow hwnd %x visible flag %d, no activate: flag %d\n", hWnd, bVisible, bNoActivate);
#endif

        if( bNoActivate )
			WinSetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_SHOW);
        else
            WinSetWindowPos(hWnd, NULL, 0, 0, 0, 0, pFrame->mnShowState);

        pFrame->mbInShow = FALSE;

        // Direct Paint only, if we get the SolarMutx
        if ( ImplSalYieldMutexTryToAcquire() )
        {
            WinUpdateWindow( hWnd );
            ImplSalYieldMutexRelease();
        }
    }
    else
    {
#if OSL_DEBUG_LEVEL > 0
		debug_printf( "ImplSalShow hwnd %x HIDE\n");
#endif
		WinSetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_HIDE);
    }
}


// -----------------------------------------------------------------------


void Os2SalFrame::SetExtendedFrameStyle( SalExtStyle nExtStyle )
{
}

// -----------------------------------------------------------------------

void Os2SalFrame::Show( BOOL bVisible, BOOL bNoActivate )
{
    // Post this Message to the window, because this only works
    // in the thread of the window, which has create this window.
    // We post this message to avoid deadlocks
    if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
        WinPostMsg( mhWndFrame, SAL_MSG_SHOW, (MPARAM)bVisible, (MPARAM)bNoActivate );
    else
        ImplSalShow( mhWndFrame, bVisible, bNoActivate );
}

// -----------------------------------------------------------------------

void Os2SalFrame::Enable( BOOL bEnable )
{
    WinEnableWindow( mhWndFrame, bEnable );
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetMinClientSize( long nWidth, long nHeight )
{
    debug_printf("Os2SalFrame::SetMinClientSize\n");
    mnMinWidth  = nWidth;
    mnMinHeight = nHeight;
}

void Os2SalFrame::SetMaxClientSize( long nWidth, long nHeight )
{
    debug_printf("Os2SalFrame::SetMaxClientSize\n");
    mnMaxWidth  = nWidth;
    mnMaxHeight = nHeight;
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight,
                                                   USHORT nFlags )
{
    // calculation frame size
    USHORT 	nEvent = 0;
	ULONG	nPosFlags = 0;

#if OSL_DEBUG_LEVEL > 0
	//dumpWindowInfo( "-Os2SalFrame::SetPosSize", mhWndFrame);
	debug_printf( ">Os2SalFrame::SetPosSize go to %d,%d (%dx%d) VCL\n",nX,nY,nWidth,nHeight);
#endif

	SWP aSWP;
	_WinQueryWindowPos( this, &aSWP );
    BOOL bVisible = WinIsWindowVisible( mhWndFrame );
    if ( !bVisible )
    {
        if ( mbFloatWin )
			mnShowState = SWP_SHOW;
        else
			mnShowState = SWP_SHOWNORMAL;
    }
    else
    {
        if ( (aSWP.fl & SWP_MINIMIZE) || (aSWP.fl & SWP_MAXIMIZE) )
			WinSetWindowPos(mhWndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE );
    }

    if ( (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) ) {
        nPosFlags |= SWP_MOVE;
#if OSL_DEBUG_LEVEL > 0
		debug_printf( "-Os2SalFrame::SetPosSize MOVE to %d,%d\n", nX, nY);
#endif
        //DBG_ASSERT( nX && nY, " Windowposition of (0,0) requested!" );
        nEvent = SALEVENT_MOVE;
	}

    if ( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) ) {
        nPosFlags |= SWP_SIZE;
#if OSL_DEBUG_LEVEL > 0
		debug_printf( "-Os2SalFrame::SetPosSize SIZE to %d,%d\n", nWidth,nHeight);
#endif
        nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE;
	}
	
    // Default-Position, dann zentrieren, ansonsten Position beibehalten
    if ( mbDefPos  && !(nPosFlags & SWP_MOVE))
    {
        // calculate bottom left corner of frame
        mbDefPos = FALSE;
		nPosFlags |= SWP_MOVE | SWP_CENTER;
        nEvent = SALEVENT_MOVERESIZE;
#if OSL_DEBUG_LEVEL > 10
		debug_printf( "-Os2SalFrame::SetPosSize CENTER\n");
		debug_printf( "-Os2SalFrame::SetPosSize default position to %d,%d\n", nX, nY);
#endif
    }

    // Adjust Window in the screen
    BOOL bCheckOffScreen = TRUE;

    // but don't do this for floaters or ownerdraw windows that are currently moved interactively
    if( (mnStyle & SAL_FRAME_STYLE_FLOAT) && !(mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
        bCheckOffScreen = FALSE;

    if( mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
    {
        // may be the window is currently being moved (mouse is captured), then no check is required
        if( mhWndClient == WinQueryCapture( HWND_DESKTOP) )
            bCheckOffScreen = FALSE;
        else
            bCheckOffScreen = TRUE;
    }

    if( bCheckOffScreen )
    {
        if ( nX+nWidth > nScreenWidth )
            nX = nScreenWidth - nWidth;
        if ( nY+nHeight > nScreenHeight )
            nY = nScreenHeight - nHeight;
        if ( nX < 0 )
            nX = 0;
        if ( nY < 0 )
            nY = 0;
    }

    // bring floating windows always to top
    // do not change zorder, otherwise tooltips will bring main window to top (ticket:14)
    //if( (mnStyle & SAL_FRAME_STYLE_FLOAT) )
    //    nPosFlags |= SWP_ZORDER; // do not change z-order

    // set new position
    _WinSetWindowPos( this, HWND_TOP, nX, nY, nWidth, nHeight, nPosFlags); // | SWP_RESTORE

    UpdateFrameGeometry( mhWndFrame, this );

    // Notification -- really ???
    if( nEvent )
        CallCallback( nEvent, NULL );

#if OSL_DEBUG_LEVEL > 0
	dumpWindowInfo( "<Os2SalFrame::SetPosSize (exit)", mhWndFrame);
#endif

}

// -----------------------------------------------------------------------

void Os2SalFrame::SetParent( SalFrame* pNewParent )
{
    APIRET rc;
#if OSL_DEBUG_LEVEL>0
    debug_printf("Os2SalFrame::SetParent mhWndFrame 0x%08x to 0x%08x\n", 
			static_cast<Os2SalFrame*>(this)->mhWndFrame,
			static_cast<Os2SalFrame*>(pNewParent)->mhWndClient);
#endif
    Os2SalFrame::mbInReparent = TRUE;
    //rc = WinSetParent(static_cast<Os2SalFrame*>(this)->mhWndFrame, 
    //                  static_cast<Os2SalFrame*>(pNewParent)->mhWndClient, TRUE);
    rc = WinSetOwner(static_cast<Os2SalFrame*>(this)->mhWndFrame, 
                      static_cast<Os2SalFrame*>(pNewParent)->mhWndClient);
	mpParentFrame = static_cast<Os2SalFrame*>(pNewParent);
    Os2SalFrame::mbInReparent = FALSE;
}

bool Os2SalFrame::SetPluginParent( SystemParentData* pNewParent )
{
    APIRET rc;
    if ( pNewParent->hWnd == 0 )
    {
        pNewParent->hWnd = HWND_DESKTOP;
    }

    Os2SalFrame::mbInReparent = TRUE;
    rc = WinSetOwner(static_cast<Os2SalFrame*>(this)->mhWndFrame, 
                      pNewParent->hWnd);
    Os2SalFrame::mbInReparent = FALSE;
    return true;
}


// -----------------------------------------------------------------------

void Os2SalFrame::GetWorkArea( RECTL &rRect )
{
    rRect.xLeft     = rRect.yTop = 0;
    rRect.xRight    = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN )-1;
    rRect.yBottom   = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN )-1;
}

// -----------------------------------------------------------------------

void Os2SalFrame::GetWorkArea( Rectangle &rRect )
{
    RECTL aRect;
	GetWorkArea( aRect);
    rRect.nLeft     = aRect.xLeft;
    rRect.nRight    = aRect.xRight; // win -1;
    rRect.nTop      = aRect.yTop;
    rRect.nBottom   = aRect.yBottom; // win -1;
}

// -----------------------------------------------------------------------

void Os2SalFrame::GetClientSize( long& rWidth, long& rHeight )
{
    rWidth  = maGeometry.nWidth;
    rHeight = maGeometry.nHeight;
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetWindowState( const SalFrameState* pState )
{
	LONG	nX;
	LONG 	nY;
	LONG 	nWidth;
	LONG 	nHeight;
	ULONG	nPosSize = 0;

#if OSL_DEBUG_LEVEL>0
	debug_printf("Os2SalFrame::SetWindowState\n");
	debug_printf("Os2SalFrame::SetWindowState %08x (%dx%d) at %d,%d VCL\n",
		mhWndFrame,
		pState->mnWidth,pState->mnHeight,pState->mnX,pState->mnY);
#endif

    BOOL bVisible = WinIsWindowVisible( mhWndFrame );

    // get screen coordinates
    SWP	aSWP;
    WinQueryWindowPos( mhWndFrame, &aSWP );
	LONG nFrameX, nFrameY, nCaptionY;
	ImplSalCalcFrameSize( this, nFrameX, nFrameY, nCaptionY );

    long nTopDeco = nFrameY + nCaptionY;
    long nLeftDeco = nFrameX;
    long nBottomDeco = nFrameY;
    long nRightDeco = nFrameX;

    // Fenster-Position/Groesse in den Bildschirm einpassen
    if ((pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y)) )
        nPosSize |= SWP_MOVE;
    if ((pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)) )
        nPosSize |= SWP_SIZE;

    if ( pState->mnMask & SAL_FRAMESTATE_MASK_X )
        nX = (int)pState->mnX - nLeftDeco;
    else
        nX = aSWP.x;

	// keep Y inverted since height is still unknown, will invert later
    if ( pState->mnMask & SAL_FRAMESTATE_MASK_Y )
        nY = (int)pState->mnY - nTopDeco;
    else
        nY = nScreenHeight - (aSWP.y+aSWP.cy);

    if ( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH )
        nWidth = (int)pState->mnWidth + nLeftDeco + nRightDeco;
    else
        nWidth = aSWP.cx;
    if ( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT )
        nHeight = (int)pState->mnHeight + nTopDeco + nBottomDeco;
    else
        nHeight = aSWP.cy;
	
#if OSL_DEBUG_LEVEL>0
	debug_printf("Os2SalFrame::SetWindowState (%dx%d) at %d,%d\n", nWidth,nHeight,nX,nY);
#endif

    // Adjust Window in the screen:
    // if it does not fit into the screen do nothing, ie default pos/size will be used
    // if there is an overlap with the screen border move the window while keeping its size

    //if( nWidth > nScreenWidth || nHeight > nScreenHeight )
    //    nPosSize |= (SWP_NOMOVE | SWP_NOSIZE);

    if ( nX+nWidth > nScreenWidth )
        nX = (nScreenWidth) - nWidth;
    if ( nY+nHeight > nScreenHeight )
        nY = (nScreenHeight) - nHeight;
    if ( nX < 0 )
        nX = 0;
    if ( nY < 0 )
        nY = 0;

    // Restore-Position setzen
	SWP aPlacement;
	WinQueryWindowPos( mhWndFrame, &aPlacement );

    // Status setzen
	bVisible = WinIsWindowVisible( mhWndFrame);
	BOOL bUpdateHiddenFramePos = FALSE;
    if ( !bVisible )
    {
        aPlacement.fl = SWP_HIDE;

        if ( mbOverwriteState )
        {
            if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
            {
                if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
                    mnShowState = SWP_SHOWMINIMIZED;
                else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
				{
                    mnShowState = SWP_SHOWMAXIMIZED;
					bUpdateHiddenFramePos = TRUE;
				}
                else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
                    mnShowState = SWP_SHOWNORMAL;
            }
        }
    }
    else
    {
        if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE )
        {
            if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED )
            {
                //if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
                //    aPlacement.flags |= WPF_RESTORETOMAXIMIZED;
                aPlacement.fl = SWP_SHOWMINIMIZED;
            }
            else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED )
                aPlacement.fl = SWP_SHOWMAXIMIZED;
            else if ( pState->mnState & SAL_FRAMESTATE_NORMAL )
                aPlacement.fl = SWP_RESTORE;
        }
    }

    // Wenn Fenster nicht minimiert/maximiert ist oder nicht optisch
    // umgesetzt werden muss, dann SetWindowPos() benutzen, da
    // SetWindowPlacement() die TaskBar mit einrechnet
    if ( !(aPlacement.fl & SWP_MINIMIZE) 
		 && !( aPlacement.fl & SWP_MAXIMIZE ) 
	 	 && (!bVisible || (aPlacement.fl == SWP_RESTORE)) )
    {
		if( bUpdateHiddenFramePos )
		{
			// #96084 set a useful internal window size because
			// the window will not be maximized (and the size updated) before show()
            SetMaximizedFrameGeometry( mhWndFrame, this );
		}
		else
			WinSetWindowPos( mhWndFrame, 0, nX, 
				nScreenHeight - (nY+nHeight), nWidth, nHeight, nPosSize);
    }
    else
    {
        if( (nPosSize & (SWP_MOVE|SWP_SIZE)) )
        {
			aPlacement.x = nX;
			aPlacement.y = nScreenHeight-(nY+nHeight);
			aPlacement.cx = nWidth;
			aPlacement.cy = nHeight;
        }
		WinSetWindowPos( mhWndFrame, 0, aPlacement.x, aPlacement.y, 
						 aPlacement.cx, aPlacement.cy, aPlacement.fl );
    }

#if OSL_DEBUG_LEVEL>0
	debug_printf("Os2SalFrame::SetWindowState DONE\n");
#endif
}

// -----------------------------------------------------------------------

BOOL Os2SalFrame::GetWindowState( SalFrameState* pState )
{
    if ( maState.mnWidth && maState.mnHeight )
    {
        *pState = maState;
        // #94144# allow Minimize again, should be masked out when read from configuration
        // 91625 - Don't save minimize
        //if ( !(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) )
        if ( !(pState->mnState & (SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED)) )
            pState->mnState |= SAL_FRAMESTATE_NORMAL;
        return TRUE;
    }

    return FALSE;
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetScreenNumber( unsigned int nNewScreen )
{
#if 0
    WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
    if( pSys )
    {
        const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
            pSys->getMonitors();
        size_t nMon = rMonitors.size();
        if( nNewScreen < nMon )
        {
            Point aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() );
            Point aCurPos( maGeometry.nX, maGeometry.nY );
            for( size_t i = 0; i < nMon; i++ )
            {
                if( rMonitors[i].m_aArea.IsInside( aCurPos ) )
                {
                    aOldMonPos = rMonitors[i].m_aArea.TopLeft();
                    break;
                }
            }
            mnDisplay = nNewScreen;
            maGeometry.nScreenNumber = nNewScreen;
            SetPosSize( aNewMonPos.X() + (maGeometry.nX - aOldMonPos.X()),
                        aNewMonPos.Y() + (maGeometry.nY - aOldMonPos.Y()),
                        0, 0,
                        SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
        }
    }
#endif
}

// -----------------------------------------------------------------------

// native menu implementation - currently empty
void Os2SalFrame::DrawMenuBar()
{
}

void Os2SalFrame::SetMenu( SalMenu* pSalMenu )
{
}

// -----------------------------------------------------------------------

void Os2SalFrame::ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay )
{
    if ( mbFullScreen == bFullScreen )
        return;

    mbFullScreen = bFullScreen;
    if ( bFullScreen )
    {
        // save old position
        memset( &maFullScreenRect, 0, sizeof( SWP ) );
        _WinQueryWindowPos( this, &maFullScreenRect );

        // set window to screen size
        ImplSalFrameFullScreenPos( this, TRUE );
    }
    else
    {
        _WinSetWindowPos( this,
                         0,
                         maFullScreenRect.x, maFullScreenRect.y,
                         maFullScreenRect.cx, maFullScreenRect.cy,
                         SWP_MOVE | SWP_SIZE );
    }
}

// -----------------------------------------------------------------------

void Os2SalFrame::StartPresentation( BOOL bStart )
{
    // SysSetObjectData("<WP_DESKTOP>","Autolockup=no"); oder OS2.INI: PM_Lockup
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetAlwaysOnTop( BOOL bOnTop )
{
    mbAllwayOnTop = bOnTop;
#if 0
    HWND hWnd;
    if ( bOnTop )
        hWnd = HWND_TOPMOST;
    else
        hWnd = HWND_NOTOPMOST;
    SetWindowPos( mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
#endif
}


// -----------------------------------------------------------------------

static void ImplSalToTop( HWND hWnd, ULONG nFlags )
{
    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
#if OSL_DEBUG_LEVEL>0
	debug_printf("ImplSalToTop hWnd %08x, nFlags %x\n", hWnd, nFlags);
#endif

	// if window is minimized, first restore it
	SWP aSWP;
	WinQueryWindowPos( hWnd, &aSWP );
	if ( aSWP.fl & SWP_MINIMIZE )
		WinSetWindowPos( hWnd, NULL, 0, 0, 0, 0, SWP_RESTORE );

    if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK )
		WinSetWindowPos( pFrame->mhWndFrame, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE | SWP_ZORDER);

    if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
    {
		ULONG	nStyle;
        if ( pFrame->mbRestoreMaximize )
            nStyle = SWP_MAXIMIZE;
        else
            nStyle = SWP_RESTORE;

		WinSetWindowPos( pFrame->mhWndFrame, NULL, 0, 0, 0, 0, nStyle );
	}
    WinSetFocus( HWND_DESKTOP, pFrame->mhWndClient );
}

// -----------------------------------------------------------------------

void Os2SalFrame::ToTop( USHORT nFlags )
{
	nFlags &= ~SAL_FRAME_TOTOP_GRABFOCUS;	// this flag is not needed on win32
    // Post this Message to the window, because this only works
    // in the thread of the window, which has create this window.
    // We post this message to avoid deadlocks
    if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
        WinPostMsg( mhWndFrame, SAL_MSG_TOTOP, (MPARAM)nFlags, 0 );
    else
        ImplSalToTop( mhWndFrame, nFlags );
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetPointer( PointerStyle ePointerStyle )
{
    struct ImplPtrData
    {
        HPOINTER	mhPointer;
        ULONG       mnSysId;
        ULONG       mnOwnId;
    };

    static ImplPtrData aImplPtrTab[POINTER_COUNT] =
    {
    { 0, SPTR_ARROW, 0 },                           // POINTER_ARROW
    { 0, 0, SAL_RESID_POINTER_NULL },               // POINTER_NULL
    { 0, SPTR_WAIT, 0 },                            // POINTER_WAIT
    { 0, SPTR_TEXT, 0 },                            // POINTER_BEAM
    { 0, 0, SAL_RESID_POINTER_HELP },               // POINTER_HELP
    { 0, 0, SAL_RESID_POINTER_CROSS },              // POINTER_CROSS
    { 0, 0, SAL_RESID_POINTER_MOVE },               // POINTER_MOVE
    { 0, SPTR_SIZENS, 0 },                          // POINTER_NSIZE
    { 0, SPTR_SIZENS, 0 },                          // POINTER_SSIZE
    { 0, SPTR_SIZEWE, 0 },                          // POINTER_WSIZE
    { 0, SPTR_SIZEWE, 0 },                          // POINTER_ESIZE
    { 0, SPTR_SIZENWSE, 0 },                        // POINTER_NWSIZE
    { 0, SPTR_SIZENESW, 0 },                        // POINTER_NESIZE
    { 0, SPTR_SIZENESW, 0 },                        // POINTER_SWSIZE
    { 0, SPTR_SIZENWSE, 0 },                        // POINTER_SESIZE
    { 0, SPTR_SIZENS, 0 },                          // POINTER_WINDOW_NSIZE
    { 0, SPTR_SIZENS, 0 },                          // POINTER_WINDOW_SSIZE
    { 0, SPTR_SIZEWE, 0 },                          // POINTER_WINDOW_WSIZE
    { 0, SPTR_SIZEWE, 0 },                          // POINTER_WINDOW_ESIZE
    { 0, SPTR_SIZENWSE, 0 },                        // POINTER_WINDOW_NWSIZE
    { 0, SPTR_SIZENESW, 0 },                        // POINTER_WINDOW_NESIZE
    { 0, SPTR_SIZENESW, 0 },                        // POINTER_WINDOW_SWSIZE
    { 0, SPTR_SIZENWSE, 0 },                        // POINTER_WINDOW_SESIZE
    { 0, 0, SAL_RESID_POINTER_HSPLIT },             // POINTER_HSPLIT
    { 0, 0, SAL_RESID_POINTER_VSPLIT },             // POINTER_VSPLIT
    { 0, 0, SAL_RESID_POINTER_HSIZEBAR },           // POINTER_HSIZEBAR
    { 0, 0, SAL_RESID_POINTER_VSIZEBAR },           // POINTER_VSIZEBAR
    { 0, 0, SAL_RESID_POINTER_HAND },               // POINTER_HAND
    { 0, 0, SAL_RESID_POINTER_REFHAND },            // POINTER_REFHAND
    { 0, 0, SAL_RESID_POINTER_PEN },                // POINTER_PEN
    { 0, 0, SAL_RESID_POINTER_MAGNIFY },            // POINTER_MAGNIFY
    { 0, 0, SAL_RESID_POINTER_FILL },               // POINTER_FILL
    { 0, 0, SAL_RESID_POINTER_ROTATE },             // POINTER_ROTATE
    { 0, 0, SAL_RESID_POINTER_HSHEAR },             // POINTER_HSHEAR
    { 0, 0, SAL_RESID_POINTER_VSHEAR },             // POINTER_VSHEAR
    { 0, 0, SAL_RESID_POINTER_MIRROR },             // POINTER_MIRROR
    { 0, 0, SAL_RESID_POINTER_CROOK },              // POINTER_CROOK
    { 0, 0, SAL_RESID_POINTER_CROP },               // POINTER_CROP
    { 0, 0, SAL_RESID_POINTER_MOVEPOINT },          // POINTER_MOVEPOINT
    { 0, 0, SAL_RESID_POINTER_MOVEBEZIERWEIGHT },   // POINTER_MOVEBEZIERWEIGHT
    { 0, 0, SAL_RESID_POINTER_MOVEDATA },           // POINTER_MOVEDATA
    { 0, 0, SAL_RESID_POINTER_COPYDATA },           // POINTER_COPYDATA
    { 0, 0, SAL_RESID_POINTER_LINKDATA },           // POINTER_LINKDATA
    { 0, 0, SAL_RESID_POINTER_MOVEDATALINK },       // POINTER_MOVEDATALINK
    { 0, 0, SAL_RESID_POINTER_COPYDATALINK },       // POINTER_COPYDATALINK
    { 0, 0, SAL_RESID_POINTER_MOVEFILE },           // POINTER_MOVEFILE
    { 0, 0, SAL_RESID_POINTER_COPYFILE },           // POINTER_COPYFILE
    { 0, 0, SAL_RESID_POINTER_LINKFILE },           // POINTER_LINKFILE
    { 0, 0, SAL_RESID_POINTER_MOVEFILELINK },       // POINTER_MOVEFILELINK
    { 0, 0, SAL_RESID_POINTER_COPYFILELINK },       // POINTER_COPYFILELINK
    { 0, 0, SAL_RESID_POINTER_MOVEFILES },          // POINTER_MOVEFILES
    { 0, 0, SAL_RESID_POINTER_COPYFILES },          // POINTER_COPYFILES
    { 0, SPTR_ILLEGAL, 0 },                         // POINTER_NOTALLOWED
    { 0, 0, SAL_RESID_POINTER_DRAW_LINE },          // POINTER_DRAW_LINE
    { 0, 0, SAL_RESID_POINTER_DRAW_RECT },          // POINTER_DRAW_RECT
    { 0, 0, SAL_RESID_POINTER_DRAW_POLYGON },       // POINTER_DRAW_POLYGON
    { 0, 0, SAL_RESID_POINTER_DRAW_BEZIER },        // POINTER_DRAW_BEZIER
    { 0, 0, SAL_RESID_POINTER_DRAW_ARC },           // POINTER_DRAW_ARC
    { 0, 0, SAL_RESID_POINTER_DRAW_PIE },           // POINTER_DRAW_PIE
    { 0, 0, SAL_RESID_POINTER_DRAW_CIRCLECUT },     // POINTER_DRAW_CIRCLECUT
    { 0, 0, SAL_RESID_POINTER_DRAW_ELLIPSE },       // POINTER_DRAW_ELLIPSE
    { 0, 0, SAL_RESID_POINTER_DRAW_FREEHAND },      // POINTER_DRAW_FREEHAND
    { 0, 0, SAL_RESID_POINTER_DRAW_CONNECT },       // POINTER_DRAW_CONNECT
    { 0, 0, SAL_RESID_POINTER_DRAW_TEXT },          // POINTER_DRAW_TEXT
    { 0, 0, SAL_RESID_POINTER_DRAW_CAPTION },       // POINTER_DRAW_CAPTION
    { 0, 0, SAL_RESID_POINTER_CHART },              // POINTER_CHART
    { 0, 0, SAL_RESID_POINTER_DETECTIVE },          // POINTER_DETECTIVE
    { 0, 0, SAL_RESID_POINTER_PIVOT_COL },          // POINTER_PIVOT_COL
    { 0, 0, SAL_RESID_POINTER_PIVOT_ROW },          // POINTER_PIVOT_ROW
    { 0, 0, SAL_RESID_POINTER_PIVOT_FIELD },        // POINTER_PIVOT_FIELD
    { 0, 0, SAL_RESID_POINTER_CHAIN },              // POINTER_CHAIN
    { 0, 0, SAL_RESID_POINTER_CHAIN_NOTALLOWED },   // POINTER_CHAIN_NOTALLOWED
    { 0, 0, SAL_RESID_POINTER_TIMEEVENT_MOVE },     // POINTER_TIMEEVENT_MOVE
    { 0, 0, SAL_RESID_POINTER_TIMEEVENT_SIZE },     // POINTER_TIMEEVENT_SIZE
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_N },       // POINTER_AUTOSCROLL_N
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S },       // POINTER_AUTOSCROLL_S
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W },       // POINTER_AUTOSCROLL_W
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E },       // POINTER_AUTOSCROLL_E
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW },      // POINTER_AUTOSCROLL_NW
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE },      // POINTER_AUTOSCROLL_NE
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW },      // POINTER_AUTOSCROLL_SW
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE },      // POINTER_AUTOSCROLL_SE
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS },      // POINTER_AUTOSCROLL_NS
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE },      // POINTER_AUTOSCROLL_WE
    { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE },     // POINTER_AUTOSCROLL_NSWE
    { 0, 0, SAL_RESID_POINTER_AIRBRUSH },           // POINTER_AIRBRUSH
    { 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL },      // POINTER_TEXT_VERTICAL
    { 0, 0, SAL_RESID_POINTER_PIVOT_DELETE },       // POINTER_PIVOT_DELETE

    // --> FME 2004-07-30 #i32329# Enhanced table selection
    { 0, 0, SAL_RESID_POINTER_TAB_SELECT_S },       // POINTER_TAB_SELECT_S
    { 0, 0, SAL_RESID_POINTER_TAB_SELECT_E },       // POINTER_TAB_SELECT_E
    { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SE },      // POINTER_TAB_SELECT_SE
    { 0, 0, SAL_RESID_POINTER_TAB_SELECT_W },       // POINTER_TAB_SELECT_W
    { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SW },      // POINTER_TAB_SELECT_SW
    // <--

    // --> FME 2004-08-16 #i20119# Paintbrush tool
    { 0, 0, SAL_RESID_POINTER_PAINTBRUSH }          // POINTER_PAINTBRUSH
    // <--
    };

#if POINTER_COUNT != 94
#error New Pointer must be defined!
#endif

	//debug_printf("Os2SalFrame::SetPointer\n");
	
    // Mousepointer loaded ?
    if ( !aImplPtrTab[ePointerStyle].mhPointer )
    {
        if ( aImplPtrTab[ePointerStyle].mnOwnId )
            aImplPtrTab[ePointerStyle].mhPointer = ImplLoadSalCursor( (ULONG)aImplPtrTab[ePointerStyle].mnOwnId );
        else
            aImplPtrTab[ePointerStyle].mhPointer = WinQuerySysPointer( HWND_DESKTOP, aImplPtrTab[ePointerStyle].mnSysId, FALSE );
    }
	if (aImplPtrTab[ePointerStyle].mhPointer == 0) {
		debug_printf( "SetPointer ePointerStyle %d unknown\n", ePointerStyle);
		aImplPtrTab[ePointerStyle].mhPointer = SPTR_ICONERROR;
	}

    // Unterscheidet sich der Mauspointer, dann den neuen setzen
    if ( mhPointer != aImplPtrTab[ePointerStyle].mhPointer )
    {
        mhPointer = aImplPtrTab[ePointerStyle].mhPointer;
        WinSetPointer( HWND_DESKTOP, mhPointer );
    }
}

// -----------------------------------------------------------------------

void Os2SalFrame::CaptureMouse( BOOL bCapture )
{
#if OSL_DEBUG_LEVEL>10
	_bCapture=bCapture;
	debug_printf("Os2SalFrame::CaptureMouse bCapture %d\n", bCapture);
#endif
    if ( bCapture )
        WinSetCapture( HWND_DESKTOP, mhWndClient );
    else
        WinSetCapture( HWND_DESKTOP, 0 );
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetPointerPos( long nX, long nY )
{
    POINTL aPt;
    aPt.x = nX;
    aPt.y = mnHeight - nY - 1;  // convert sal coords to sys
    WinMapWindowPoints( mhWndClient, HWND_DESKTOP, &aPt, 1 );
    WinSetPointerPos( HWND_DESKTOP, aPt.x, aPt.y );
}

// -----------------------------------------------------------------------

void Os2SalFrame::Flush()
{
}

// -----------------------------------------------------------------------

void Os2SalFrame::Sync()
{
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetInputContext( SalInputContext* pContext )
{
#ifdef ENABLE_IME
    SalIMEData* pIMEData = GetSalIMEData();
    if ( pIMEData )
    {
        HWND hWnd = mhWndClient;
        HIMI hIMI = 0;
        pIMEData->mpGetIME( hWnd, &hIMI );
        if ( hIMI )
        {
            ULONG nInputMode;
            ULONG nConversionMode;
            if ( 0 == pIMEData->mpQueryIMEMode( hIMI, &nInputMode, &nConversionMode ) )
            {
                if ( pContext->mnOptions & SAL_INPUTCONTEXT_TEXT )
                {
                    nInputMode &= ~IMI_IM_IME_DISABLE;
                    if ( pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT_OFF )
                        nInputMode &= ~IMI_IM_IME_ON;
// !!! Da derzeit ueber das OS2-IME-UI der IME-Mode nicht einschaltbar ist !!!
//                    if ( SAL_INPUTCONTEXT_EXTTEXTINPUT_ON )
                        nInputMode |= IMI_IM_IME_ON;
                }
                else
                    nInputMode |= IMI_IM_IME_DISABLE;
                pIMEData->mpSetIMEMode( hIMI, nInputMode, nConversionMode );
            }

            pIMEData->mpReleaseIME( hWnd, hIMI );
        }
    }
#endif
}

// -----------------------------------------------------------------------
#if 0
void Os2SalFrame::UpdateExtTextInputArea()
{
#ifdef ENABLE_IME
#endif
}
#endif

// -----------------------------------------------------------------------

void Os2SalFrame::EndExtTextInput( USHORT nFlags )
{
#ifdef ENABLE_IME
    SalIMEData* pIMEData = GetSalIMEData();
    if ( pIMEData )
    {
        HWND hWnd = mhWndClient;
        HIMI hIMI = 0;
        pIMEData->mpGetIME( hWnd, &hIMI );
        if ( hIMI )
        {
            ULONG nIndex;
            if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE )
                nIndex = CNV_COMPLETE;
            else
                nIndex = CNV_CANCEL;

            pIMEData->mpRequestIME( hIMI, REQ_CONVERSIONSTRING, nIndex, 0 );
            pIMEData->mpReleaseIME( hWnd, hIMI );
        }
    }
#endif
}

// -----------------------------------------------------------------------

XubString Os2SalFrame::GetKeyName( USHORT nCode )
{
    if ( eImplKeyboardLanguage == LANGUAGE_DONTKNOW )
        eImplKeyboardLanguage = MsLangId::getSystemLanguage();

    XubString        aKeyCode;
    XubString        aCode;
    const sal_Unicode**    pLangTab = ImplGetLangTab( eImplKeyboardLanguage );

    if ( nCode & KEY_SHIFT )
        aKeyCode = pLangTab[LSTR_KEY_SHIFT];

    if ( nCode & KEY_MOD1 )
    {
        if ( aKeyCode.Len() == 0 )
            aKeyCode = pLangTab[LSTR_KEY_CTRL];
        else
        {
            aKeyCode += '+';
            aKeyCode += pLangTab[LSTR_KEY_CTRL];
        }
    }

    if ( nCode & KEY_MOD2 )
    {
        if ( aKeyCode.Len() == 0 )
            aKeyCode = pLangTab[LSTR_KEY_ALT];
        else
        {
            aKeyCode += '+';
            aKeyCode += pLangTab[LSTR_KEY_ALT];
        }
    }

    USHORT nKeyCode = nCode & 0x0FFF;
    if ( (nKeyCode >= KEY_0) && (nKeyCode <= KEY_9) )
        aCode = sal::static_int_cast<sal_Char>('0' + (nKeyCode - KEY_0));
    else if ( (nKeyCode >= KEY_A) && (nKeyCode <= KEY_Z) )
        aCode = sal::static_int_cast<sal_Char>('A' + (nKeyCode - KEY_A));
    else if ( (nKeyCode >= KEY_F1) && (nKeyCode <= KEY_F26) )
    {
		aCode += 'F';
        if ( (nKeyCode >= KEY_F1) && (nKeyCode <= KEY_F9) )
        {
            aCode += sal::static_int_cast<sal_Char>('1' + (nKeyCode - KEY_F1));
        }
        else if ( (nKeyCode >= KEY_F10) && (nKeyCode <= KEY_F19) )
        {
            aCode += '1';
            aCode += sal::static_int_cast<sal_Char>('0' + (nKeyCode - KEY_F10));
        }
        else
        {
            aCode += '2';
            aCode += sal::static_int_cast<sal_Char>('0' + (nKeyCode - KEY_F20));
        }
    }
    else
    {
		switch ( nKeyCode )
		{
			case KEY_DOWN:
				aCode = pLangTab[LSTR_KEY_DOWN];
				break;
			case KEY_UP:
				aCode = pLangTab[LSTR_KEY_UP];
				break;
			case KEY_LEFT:
				aCode = pLangTab[LSTR_KEY_LEFT];
				break;
			case KEY_RIGHT:
				aCode = pLangTab[LSTR_KEY_RIGHT];
				break;
			case KEY_HOME:
				aCode = pLangTab[LSTR_KEY_HOME];
				break;
			case KEY_END:
				aCode = pLangTab[LSTR_KEY_END];
				break;
			case KEY_PAGEUP:
				aCode = pLangTab[LSTR_KEY_PAGEUP];
				break;
			case KEY_PAGEDOWN:
				aCode = pLangTab[LSTR_KEY_PAGEDOWN];
				break;
			case KEY_RETURN:
				aCode = pLangTab[LSTR_KEY_RETURN];
				break;
			case KEY_ESCAPE:
				aCode = pLangTab[LSTR_KEY_ESC];
				break;
			case KEY_TAB:
				aCode = pLangTab[LSTR_KEY_TAB];
				break;
			case KEY_BACKSPACE:
				aCode = pLangTab[LSTR_KEY_BACKSPACE];
				break;
			case KEY_SPACE:
				aCode = pLangTab[LSTR_KEY_SPACE];
				break;
			case KEY_INSERT:
				aCode = pLangTab[LSTR_KEY_INSERT];
				break;
			case KEY_DELETE:
				aCode = pLangTab[LSTR_KEY_DELETE];
				break;
	
			case KEY_ADD:
				aCode += '+';
				break;
			case KEY_SUBTRACT:
				aCode += '-';
				break;
			case KEY_MULTIPLY:
				aCode += '*';
				break;
			case KEY_DIVIDE:
				aCode += '/';
				break;
			case KEY_POINT:
				aCode += '.';
				break;
			case KEY_COMMA:
				aCode += ',';
				break;
			case KEY_LESS:
				aCode += '<';
				break;
			case KEY_GREATER:
				aCode += '>';
				break;
			case KEY_EQUAL:
				aCode += '=';
				break;
		}
	}

    if ( aCode.Len() )
    {
        if ( aKeyCode.Len() == 0 )
            aKeyCode = aCode;
        else
        {
            aKeyCode += '+';
            aKeyCode += aCode;
        }
    }

    return aKeyCode;
}

// -----------------------------------------------------------------------

XubString Os2SalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode )
{
    return GetKeyName( nKeyCode );
}

// -----------------------------------------------------------------------

inline long ImplOS2ColorToSal( long nOS2Color )
{
    return MAKE_SALCOLOR( (BYTE)( nOS2Color>>16), (BYTE)(nOS2Color>>8), (BYTE)nOS2Color );
}

// -----------------------------------------------------------------------

static USHORT ImplMouseSysValueToSAL( int iSysValue, USHORT& rCode, USHORT& rClicks, BOOL& rDown )
{
    LONG lValue = WinQuerySysValue( HWND_DESKTOP, iSysValue );

    rCode   = 0;
    rClicks = 1;
    rDown   = TRUE;

    switch ( lValue & 0xFFFF )
    {
        case WM_BUTTON1UP:
        case WM_BUTTON1CLICK:
            rCode = MOUSE_LEFT;
            rDown = FALSE;
            break;
        case WM_BUTTON1DOWN:
        case WM_BUTTON1MOTIONSTART:
            rCode = MOUSE_LEFT;
            break;
        case WM_BUTTON1DBLCLK:
            rCode = MOUSE_LEFT;
            rClicks = 2;
            break;

        case WM_BUTTON2UP:
        case WM_BUTTON2CLICK:
            rCode = MOUSE_RIGHT;
            rDown = FALSE;
            break;
        case WM_BUTTON2DOWN:
        case WM_BUTTON2MOTIONSTART:
            rCode = MOUSE_RIGHT;
            break;
        case WM_BUTTON2DBLCLK:
            rCode = MOUSE_RIGHT;
            rClicks = 2;
            break;

        case WM_BUTTON3UP:
        case WM_BUTTON3CLICK:
            rCode = MOUSE_MIDDLE;
            rDown = FALSE;
            break;
        case WM_BUTTON3DOWN:
        case WM_BUTTON3MOTIONSTART:
            rCode = MOUSE_MIDDLE;
            break;
        case WM_BUTTON3DBLCLK:
            rCode = MOUSE_MIDDLE;
            rClicks = 2;
            break;
    }

    if ( !rCode )
        return FALSE;

    lValue = (lValue & 0xFFFF0000) >> 16;
    if ( lValue != 0xFFFF )
    {
        if ( lValue & KC_SHIFT )
            rCode |= KEY_SHIFT;
        if ( lValue & KC_CTRL )
            rCode |= KEY_MOD1;
        if ( lValue & KC_ALT )
            rCode |= KEY_MOD2;
    }

    return TRUE;
}

// -----------------------------------------------------------------------

static BOOL ImplSalIsSameColor( const Color& rColor1, const Color& rColor2 )
{
    ULONG nWrong = 0;
    nWrong += Abs( (short)rColor1.GetRed()-(short)rColor2.GetRed() );
    nWrong += Abs( (short)rColor1.GetGreen()-(short)rColor2.GetGreen() );
    nWrong += Abs( (short)rColor1.GetBlue()-(short)rColor2.GetBlue() );
    return (nWrong < 30);
}

// -----------------------------------------------------------------------

static BOOL ImplOS2NameFontToVCLFont( const char* pFontName, Font& rFont )
{
    char aNumBuf[10];
    int  nNumBufLen = 0;

    while ( *pFontName && (*pFontName != '.') &&
            (nNumBufLen < sizeof(aNumBuf)-1) )
    {
        aNumBuf[nNumBufLen] = *pFontName;
        nNumBufLen++;
        pFontName++;
    }
    aNumBuf[nNumBufLen] = '\0';

    pFontName++;
    while ( *pFontName == ' ' )
        pFontName++;

    int nFontHeight = atoi( aNumBuf );
    int nFontNameLen = strlen( pFontName );
    if ( nFontHeight && nFontNameLen )
    {
        rFont.SetFamily( FAMILY_DONTKNOW );
        rFont.SetWeight( WEIGHT_NORMAL );
        rFont.SetItalic( ITALIC_NONE );
		// search for a style embedded in the name, e.g. 'WarpSans Bold'
		// because we need to split the style from the family name
		if (strstr( pFontName, " Bold") 
			|| strstr( pFontName, " Italic")
			|| strstr( pFontName, "-Normal"))
		{
			char* fontName = strdup( pFontName);
			char* style = strstr( fontName, " Bold");
			if (style)
				rFont.SetWeight( WEIGHT_BOLD );

			if (!style)
				style = strstr( fontName, " Italic");
			if (style)
				rFont.SetItalic( ITALIC_NORMAL );

			if (!style)
				style = strstr( fontName, "-Normal");
			// store style, skip whitespace char
			rFont.SetStyleName( ::rtl::OStringToOUString ( style+1, gsl_getSystemTextEncoding()) );
			// truncate name
			*style = 0;
			// store family name
			rFont.SetName( ::rtl::OStringToOUString ( fontName, gsl_getSystemTextEncoding()) );
			free( fontName);
		} 
		else
		{
			rFont.SetName( ::rtl::OStringToOUString (pFontName, gsl_getSystemTextEncoding()) );
			rFont.SetStyleName( ::rtl::OStringToOUString ("", gsl_getSystemTextEncoding()) );
		}
			
        rFont.SetSize( Size( 0, nFontHeight ) );
        return TRUE;
    }
    else
        return FALSE;
}

// -----------------------------------------------------------------------

void Os2SalFrame::UpdateSettings( AllSettings& rSettings )
{
    static char aControlPanel[] = "PM_ControlPanel";
    static char aSystemFonts[]  = "PM_SystemFonts";
    char aDummyStr[] = "";

    // --- Mouse setting ---
    USHORT  nCode;
    USHORT  nClicks;
    BOOL    bDown;
    MouseSettings aMouseSettings = rSettings.GetMouseSettings();
    aMouseSettings.SetDoubleClickTime( WinQuerySysValue( HWND_DESKTOP, SV_DBLCLKTIME ) );
    if ( ImplMouseSysValueToSAL( SV_BEGINDRAG, nCode, nClicks, bDown ) )
        aMouseSettings.SetStartDragCode( nCode );
    if ( ImplMouseSysValueToSAL( SV_CONTEXTMENU, nCode, nClicks, bDown ) )
    {
        aMouseSettings.SetContextMenuCode( nCode );
        aMouseSettings.SetContextMenuClicks( nClicks );
        aMouseSettings.SetContextMenuDown( bDown );
    }
    aMouseSettings.SetButtonStartRepeat( WinQuerySysValue( HWND_DESKTOP, SV_FIRSTSCROLLRATE ) );
    aMouseSettings.SetButtonRepeat( WinQuerySysValue( HWND_DESKTOP, SV_SCROLLRATE ) );
    rSettings.SetMouseSettings( aMouseSettings );

    // --- Style settings ---
    StyleSettings aStyleSettings = rSettings.GetStyleSettings();
    // General settings
    LONG    nDisplayTime = PrfQueryProfileInt( HINI_PROFILE, (PSZ)aControlPanel, (PSZ)"LogoDisplayTime", -1 );
    ULONG   nSalDisplayTime;
    if ( nDisplayTime < 0 )
        nSalDisplayTime = LOGO_DISPLAYTIME_STARTTIME;
    else if ( !nDisplayTime )
        nSalDisplayTime = LOGO_DISPLAYTIME_NOLOGO;
    else
        nSalDisplayTime = (ULONG)nDisplayTime;
    aStyleSettings.SetLogoDisplayTime( nSalDisplayTime );

    aStyleSettings.SetCursorBlinkTime( WinQuerySysValue( HWND_DESKTOP, SV_CURSORRATE ) );
    ULONG nDragFullOptions = aStyleSettings.GetDragFullOptions();
    if ( WinQuerySysValue( HWND_DESKTOP, SV_DYNAMICDRAG ) )
        nDragFullOptions |= DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT;
    else
        nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT);
    aStyleSettings.SetDragFullOptions( nDragFullOptions );

    // Size settings
    aStyleSettings.SetScrollBarSize( WinQuerySysValue( HWND_DESKTOP, SV_CYHSCROLL ) );
    aStyleSettings.SetTitleHeight( WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) );

    // Color settings
    aStyleSettings.SetFaceColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONMIDDLE, 0 ) ) );
    aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() );
    aStyleSettings.SetLightColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0 ) ) );
    aStyleSettings.SetLightBorderColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONMIDDLE, 0 ) ) );
    aStyleSettings.SetShadowColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_BUTTONDARK, 0 ) ) );
    aStyleSettings.SetDarkShadowColor( Color( COL_BLACK ) );
    aStyleSettings.SetDialogColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0 ) ) );
    aStyleSettings.SetButtonTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
    aStyleSettings.SetActiveColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ACTIVETITLE, 0 ) ) );
    aStyleSettings.SetActiveTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ACTIVETITLETEXT, 0 ) ) );
    aStyleSettings.SetActiveBorderColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ACTIVEBORDER, 0 ) ) );
    aStyleSettings.SetDeactiveColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_INACTIVETITLE, 0 ) ) );
    aStyleSettings.SetDeactiveTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_INACTIVETITLETEXT, 0 ) ) );
    aStyleSettings.SetDeactiveBorderColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_INACTIVEBORDER, 0 ) ) );
    aStyleSettings.SetMenuColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENU, 0 ) ) );
    aStyleSettings.SetMenuTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
    aStyleSettings.SetMenuBarTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUTEXT, 0 ) ) );
    aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() );
    aStyleSettings.SetRadioCheckTextColor( aStyleSettings.GetButtonTextColor() );
    aStyleSettings.SetGroupTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_WINDOWSTATICTEXT, 0 ) ) );
    aStyleSettings.SetLabelTextColor( aStyleSettings.GetGroupTextColor() );
    aStyleSettings.SetInfoTextColor( aStyleSettings.GetGroupTextColor() );
    aStyleSettings.SetWindowColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_WINDOW, 0 ) ) );
    aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() );
    aStyleSettings.SetWindowTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_WINDOWTEXT, 0 ) ) );
    aStyleSettings.SetFieldColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_ENTRYFIELD, 0 ) ) );
    aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() );
    aStyleSettings.SetDisableColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUDISABLEDTEXT, 0 ) ) );
    aStyleSettings.SetHighlightColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_HILITEBACKGROUND, 0 ) ) );
    aStyleSettings.SetHighlightTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_HILITEFOREGROUND, 0 ) ) );
    Color aMenuHighColor = ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUHILITEBGND, 0 ) );
    if ( ImplSalIsSameColor( aMenuHighColor, aStyleSettings.GetMenuColor() ) )
    {
        aStyleSettings.SetMenuHighlightColor( Color( COL_BLUE ) );
        aStyleSettings.SetMenuHighlightTextColor( Color( COL_WHITE ) );
    }
    else
    {
        aStyleSettings.SetMenuHighlightColor( aMenuHighColor );
        aStyleSettings.SetMenuHighlightTextColor( ImplOS2ColorToSal( WinQuerySysColor( HWND_DESKTOP, SYSCLR_MENUHILITE, 0 ) ) );
    }
    // Checked-Color berechnen
    Color   aColor1 = aStyleSettings.GetFaceColor();
    Color   aColor2 = aStyleSettings.GetLightColor();
    BYTE    nRed    = (BYTE)(((USHORT)aColor1.GetRed()   + (USHORT)aColor2.GetRed())/2);
    BYTE    nGreen  = (BYTE)(((USHORT)aColor1.GetGreen() + (USHORT)aColor2.GetGreen())/2);
    BYTE    nBlue   = (BYTE)(((USHORT)aColor1.GetBlue()  + (USHORT)aColor2.GetBlue())/2);
    aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) );

    // Fonts updaten
    Font    aFont;
    char    aFontNameBuf[255];
    aFont = aStyleSettings.GetMenuFont();
    if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"Menus", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
    {
        if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) ) {
#if 0
			// Add Workplace Sans if not already listed
            if ( aFont.GetName().Search( (sal_Unicode*)L"WorkPlace Sans" ) == STRING_NOTFOUND )
            {
                XubString aFontName = aFont.GetName();
                aFontName.Insert( (sal_Unicode*)L"WorkPlace Sans;", 0 );
                aFont.SetName( aFontName );
                aFont.SetSize( Size( 0, 9 ) );
            }
#endif
            aStyleSettings.SetMenuFont( aFont );
		}
    }
    aFont = aStyleSettings.GetIconFont();
    if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"IconText", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
    {
        if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) )
            aStyleSettings.SetIconFont( aFont );
    }
    aFont = aStyleSettings.GetTitleFont();
    if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"WindowTitles", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
    {
        if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) )
        {
            // Add Workplace Sans if not already listed
            if ( aFont.GetName().Search( (sal_Unicode*)L"WorkPlace Sans" ) == STRING_NOTFOUND )
            {
                XubString aFontName = aFont.GetName();
                aFontName.Insert( (sal_Unicode*)L"WorkPlace Sans;", 0 );
                aFont.SetName( aFontName );
                aFont.SetSize( Size( 0, 9 ) );
				aFont.SetWeight( WEIGHT_BOLD );
				aFont.SetItalic( ITALIC_NONE );
            }
            aStyleSettings.SetTitleFont( aFont );
            aStyleSettings.SetFloatTitleFont( aFont );
        }
    }
    aFont = aStyleSettings.GetAppFont();
    if ( PrfQueryProfileString( HINI_PROFILE, (PSZ)aSystemFonts, (PSZ)"WindowText", aDummyStr, aFontNameBuf, sizeof( aFontNameBuf ) ) > 5 )
    {
        if ( ImplOS2NameFontToVCLFont( aFontNameBuf, aFont ) )
        {
            Font aHelpFont = aFont;
            aHelpFont.SetName( (sal_Unicode*)L"Helv;WarpSans" );
            aHelpFont.SetSize( Size( 0, 8 ) );
            aHelpFont.SetWeight( WEIGHT_NORMAL );
            aHelpFont.SetItalic( ITALIC_NONE );
            aStyleSettings.SetHelpFont( aHelpFont );

            // Add Workplace Sans if not already listed
            if ( aFont.GetName().Search( (sal_Unicode*)L"WorkPlace Sans" ) == STRING_NOTFOUND )
            {
                XubString aFontName = aFont.GetName();
                aFontName.Insert( (sal_Unicode*)L"WorkPlace Sans;", 0 );
                aFont.SetName( aFontName );
                aFont.SetSize( Size( 0, 9 ) );
            }
            aStyleSettings.SetAppFont( aFont );
            aStyleSettings.SetToolFont( aFont );
            aStyleSettings.SetLabelFont( aFont );
            aStyleSettings.SetInfoFont( aFont );
            aStyleSettings.SetRadioCheckFont( aFont );
            aStyleSettings.SetPushButtonFont( aFont );
            aStyleSettings.SetFieldFont( aFont );
            aStyleSettings.SetGroupFont( aFont );
        }
    }

    rSettings.SetStyleSettings( aStyleSettings );
}

// -----------------------------------------------------------------------

SalBitmap* Os2SalFrame::SnapShot()
{
debug_printf("Os2SalFrame::SnapShot\n");
return NULL;
}

// -----------------------------------------------------------------------

const SystemEnvData* Os2SalFrame::GetSystemData() const
{
    return &maSysData;
}

// -----------------------------------------------------------------------

void Os2SalFrame::Beep( SoundType eSoundType )
{
    static ULONG aImplSoundTab[5] =
    {
        WA_NOTE,                        // SOUND_DEFAULT
        WA_NOTE,                        // SOUND_INFO
        WA_WARNING,                     // SOUND_WARNING
        WA_ERROR,                       // SOUND_ERROR
        WA_NOTE                         // SOUND_QUERY
    };

#if 0
#if SOUND_COUNT != 5
#error New Sound must be defined!
#endif
#endif

	debug_printf("Os2SalFrame::Beep %d\n", eSoundType);
    WinAlarm( HWND_DESKTOP, aImplSoundTab[eSoundType] );
}

// -----------------------------------------------------------------------

SalFrame::SalPointerState Os2SalFrame::GetPointerState()
{
    SalPointerState aState;
    aState.mnState = 0;

    // MausModus feststellen und setzen
    if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON1 ) & 0x8000 )
        aState.mnState |= MOUSE_LEFT;
    if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON2 ) & 0x8000 )
        aState.mnState |= MOUSE_RIGHT;
    if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON3 ) & 0x8000 )
        aState.mnState |= MOUSE_MIDDLE;
    // Modifier-Tasten setzen
    if ( WinGetKeyState( HWND_DESKTOP, VK_SHIFT ) & 0x8000 )
        aState.mnState |= KEY_SHIFT;
    if ( WinGetKeyState( HWND_DESKTOP, VK_CTRL ) & 0x8000 )
        aState.mnState |= KEY_MOD1;
    if ( WinGetKeyState( HWND_DESKTOP, VK_ALT ) & 0x8000 )
        aState.mnState |= KEY_MOD2;

    POINTL pt;
    _WinQueryPointerPos( HWND_DESKTOP, &pt );

    aState.maPos = Point( pt.x - maGeometry.nX, pt.y - maGeometry.nY );
    return aState;
}

// -----------------------------------------------------------------------

void Os2SalFrame::SetBackgroundBitmap( SalBitmap* )
{
}

// -----------------------------------------------------------------------

void SalTestMouseLeave()
{
    SalData* pSalData = GetSalData();

    if ( pSalData->mhWantLeaveMsg && !::WinQueryCapture( HWND_DESKTOP ) )
    {
        POINTL aPt;
        WinQueryPointerPos( HWND_DESKTOP, &aPt );
        if ( pSalData->mhWantLeaveMsg != WinWindowFromPoint( HWND_DESKTOP, &aPt, TRUE ) )
            WinSendMsg( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MPFROM2SHORT( aPt.x, aPt.y ) );
    }
}

// -----------------------------------------------------------------------

static long ImplHandleMouseMsg( HWND hWnd,
                                UINT nMsg, MPARAM nMP1, MPARAM nMP2 )
{
    SalMouseEvent   aMouseEvt;
    long            nRet;
    USHORT          nEvent;
    BOOL            bCall = TRUE;
    USHORT          nFlags = SHORT2FROMMP( nMP2 );
    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
    if ( !pFrame )
        return 0;

    aMouseEvt.mnX       = (short)SHORT1FROMMP( nMP1 );
    aMouseEvt.mnY       = pFrame->mnHeight - (short)SHORT2FROMMP( nMP1 ) - 1;
    aMouseEvt.mnCode    = 0;
    aMouseEvt.mnTime    = WinQueryMsgTime( pFrame->mhAB );

    // MausModus feststellen und setzen
    if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON1 ) & 0x8000 )
        aMouseEvt.mnCode |= MOUSE_LEFT;
    if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON2 ) & 0x8000 )
        aMouseEvt.mnCode |= MOUSE_RIGHT;
    if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON3 ) & 0x8000 )
        aMouseEvt.mnCode |= MOUSE_MIDDLE;
    // Modifier-Tasten setzen
    if ( WinGetKeyState( HWND_DESKTOP, VK_SHIFT ) & 0x8000 )
        aMouseEvt.mnCode |= KEY_SHIFT;
    if ( WinGetKeyState( HWND_DESKTOP, VK_CTRL ) & 0x8000 )
        aMouseEvt.mnCode |= KEY_MOD1;
    if ( WinGetKeyState( HWND_DESKTOP, VK_ALT ) & 0x8000 )
        aMouseEvt.mnCode |= KEY_MOD2;

    switch ( nMsg )
    {
        case WM_MOUSEMOVE:
            {
            SalData* pSalData = GetSalData();

            // Da bei Druecken von Modifier-Tasten die MouseEvents
            // nicht zusammengefast werden (da diese durch KeyEvents
            // unterbrochen werden), machen wir dieses hier selber
            if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) )
            {
                QMSG aTempMsg;
                if ( WinPeekMsg( pSalData->mhAB, &aTempMsg,
                                 pFrame->mhWndClient,
                                 WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE ) )
                {
                    if ( (aTempMsg.msg == WM_MOUSEMOVE) &&
                         (aTempMsg.mp2 == nMP2) )
                        return 1;
                }
            }

            // Test for MouseLeave
            if ( pSalData->mhWantLeaveMsg &&
                (pSalData->mhWantLeaveMsg != pFrame->mhWndClient) )
            {
                POINTL aMousePoint;
                WinQueryMsgPos( pFrame->mhAB, &aMousePoint );
                WinSendMsg( pSalData->mhWantLeaveMsg,
                            SAL_MSG_MOUSELEAVE,
                            0, MPFROM2SHORT( aMousePoint.x, aMousePoint.y ) );
            }
            pSalData->mhWantLeaveMsg = pFrame->mhWndClient;
            // Start MouseLeave-Timer
            if ( !pSalData->mpMouseLeaveTimer )
            {
                pSalData->mpMouseLeaveTimer = new AutoTimer;
                pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT );
                pSalData->mpMouseLeaveTimer->Start();
                // We dont need to set a timeout handler, because we test
                // for mouseleave in the timeout callback
            }
            aMouseEvt.mnButton = 0;
            nEvent = SALEVENT_MOUSEMOVE;
            }
            break;

        case SAL_MSG_MOUSELEAVE:
            {
            SalData* pSalData = GetSalData();
            if ( pSalData->mhWantLeaveMsg == pFrame->mhWndClient )
            {
                pSalData->mhWantLeaveMsg = 0;
                if ( pSalData->mpMouseLeaveTimer )
                {
                    delete pSalData->mpMouseLeaveTimer;
                    pSalData->mpMouseLeaveTimer = NULL;
                }

                // Mouse-Coordinaates are relativ to the screen
                POINTL aPt;
                aPt.x = (short)SHORT1FROMMP( nMP2 );
                aPt.y = (short)SHORT2FROMMP( nMP2 );
                WinMapWindowPoints( HWND_DESKTOP, pFrame->mhWndClient, &aPt, 1 );
                aPt.y = pFrame->mnHeight - aPt.y - 1;
                aMouseEvt.mnX = aPt.x;
                aMouseEvt.mnY = aPt.y;
                aMouseEvt.mnButton = 0;
                nEvent = SALEVENT_MOUSELEAVE;
            }
            else
                bCall = FALSE;
            }
            break;

        case WM_BUTTON1DBLCLK:
        case WM_BUTTON1DOWN:
            aMouseEvt.mnButton = MOUSE_LEFT;
            nEvent = SALEVENT_MOUSEBUTTONDOWN;
            break;

        case WM_BUTTON2DBLCLK:
        case WM_BUTTON2DOWN:
            aMouseEvt.mnButton = MOUSE_RIGHT;
            nEvent = SALEVENT_MOUSEBUTTONDOWN;
            break;

        case WM_BUTTON3DBLCLK:
        case WM_BUTTON3DOWN:
            aMouseEvt.mnButton = MOUSE_MIDDLE;
            nEvent = SALEVENT_MOUSEBUTTONDOWN;
            break;

        case WM_BUTTON1UP:
            aMouseEvt.mnButton = MOUSE_LEFT;
            nEvent = SALEVENT_MOUSEBUTTONUP;
            break;

        case WM_BUTTON2UP:
            aMouseEvt.mnButton = MOUSE_RIGHT;
            nEvent = SALEVENT_MOUSEBUTTONUP;
            break;

        case WM_BUTTON3UP:
            aMouseEvt.mnButton = MOUSE_MIDDLE;
            nEvent = SALEVENT_MOUSEBUTTONUP;
            break;
    }

	// check if this window was destroyed - this might happen if we are the help window
	// and sent a mouse leave message to the application which killed the help window, ie ourself
	if( !WinIsWindow( pFrame->mhAB, hWnd ) )
		return 0;
	
#if OSL_DEBUG_LEVEL>10
	//if (_bCapture)
		debug_printf("ImplHandleMouseMsg mouse %d,%d\n",aMouseEvt.mnX,aMouseEvt.mnY);
#endif

    if ( bCall )
    {
        if ( nEvent == SALEVENT_MOUSEBUTTONDOWN )
            WinUpdateWindow( pFrame->mhWndClient );

        // --- RTL --- (mirror mouse pos)
        //if( Application::GetSettings().GetLayoutRTL() )
        //    aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX;
		
        nRet = pFrame->CallCallback( nEvent, &aMouseEvt );
        if ( nMsg == WM_MOUSEMOVE )
        {
            WinSetPointer( HWND_DESKTOP, pFrame->mhPointer );
            nRet = TRUE;
        }
    }
    else
        nRet = 0;

    return nRet;
}

// -----------------------------------------------------------------------

static long ImplHandleWheelMsg( HWND hWnd, UINT nMsg, MPARAM nMP1, MPARAM nMP2 )
{

    ImplSalYieldMutexAcquireWithWait();

    long        nRet = 0;
    Os2SalFrame*   pFrame = GetWindowPtr( hWnd );
    if ( pFrame )
    {

		// Mouse-Coordinaates are relativ to the screen
		POINTL aPt;
		WinQueryMsgPos( pFrame->mhAB, &aPt );
		WinMapWindowPoints( HWND_DESKTOP, pFrame->mhWndClient, &aPt, 1 );
		aPt.y = pFrame->mnHeight - aPt.y - 1;

        SalWheelMouseEvent aWheelEvt;
		aWheelEvt.mnTime    		= WinQueryMsgTime( pFrame->mhAB );
        aWheelEvt.mnX           	= aPt.x;
        aWheelEvt.mnY           	= aPt.y;
        aWheelEvt.mnCode       	 	= 0;
		bool bNeg = (SHORT2FROMMP(nMP2) == SB_LINEDOWN || SHORT2FROMMP(nMP2) == SB_PAGEDOWN );
		aWheelEvt.mnDelta			= bNeg ? -120 : 120;
		aWheelEvt.mnNotchDelta		= bNeg ? -1 : 1;
		if (SHORT2FROMMP(nMP2) == SB_PAGEUP || SHORT2FROMMP(nMP2) == SB_PAGEDOWN)
			aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
		else
			aWheelEvt.mnScrollLines = 1;

        if( nMsg == WM_HSCROLL )
            aWheelEvt.mbHorz        = TRUE;

		// Modifier-Tasten setzen
		if ( WinGetKeyState( HWND_DESKTOP, VK_SHIFT ) & 0x8000 )
			aWheelEvt.mnCode |= KEY_SHIFT;
		if ( WinGetKeyState( HWND_DESKTOP, VK_CTRL ) & 0x8000 )
			aWheelEvt.mnCode |= KEY_MOD1;
		if ( WinGetKeyState( HWND_DESKTOP, VK_ALT ) & 0x8000 )
			aWheelEvt.mnCode |= KEY_MOD2;

        nRet = pFrame->CallCallback( SALEVENT_WHEELMOUSE, &aWheelEvt );
    }

    ImplSalYieldMutexRelease();

    return nRet;
}


// -----------------------------------------------------------------------

static USHORT ImplSalGetKeyCode( Os2SalFrame* pFrame, MPARAM aMP1, MPARAM aMP2 )
{
    USHORT  nKeyFlags   = SHORT1FROMMP( aMP1 );
    UCHAR   nCharCode   = (UCHAR)SHORT1FROMMP( aMP2 );
    USHORT  nKeyCode    = (UCHAR)SHORT2FROMMP( aMP2 );
    UCHAR   nScanCode   = (UCHAR)CHAR4FROMMP( aMP1 );
	USHORT	rSVCode = 0;

    // Ist virtueller KeyCode gesetzt und befindet sich der KeyCode in der
    // Tabelle, dann mappen
    if ( (nKeyFlags & KC_VIRTUALKEY) && (nKeyCode < KEY_TAB_SIZE) )
        rSVCode = aImplTranslateKeyTab[nKeyCode];

    // Wenn kein KeyCode ermittelt werden konnte, versuchen wir aus dem
    // CharCode einen zu erzeugen
    if ( !rSVCode && nCharCode )
    {
        // Bei 0-9, a-z und A-Z auch KeyCode setzen
        if ( (nCharCode >= '0') && (nCharCode <= '9') && (!rSVCode || !(nKeyFlags & KC_SHIFT)) )
            rSVCode = KEYGROUP_NUM + (nCharCode-'0');
        else if ( (nCharCode >= 'a') && (nCharCode <= 'z') )
            rSVCode = KEYGROUP_ALPHA + (nCharCode-'a');
        else if ( (nCharCode >= 'A') && (nCharCode <= 'Z') )
            rSVCode = KEYGROUP_ALPHA + (nCharCode-'A');
        else
        {
            switch ( nCharCode )
            {
                case '+':
                    rSVCode = KEY_ADD;
                    break;
                case '-':
                    rSVCode = KEY_SUBTRACT;
                    break;
                case '*':
                    rSVCode = KEY_MULTIPLY;
                    break;
                case '/':
                    rSVCode = KEY_DIVIDE;
                    break;
                case '.':
                    rSVCode = KEY_POINT;
                    break;
                case ',':
                    rSVCode = KEY_COMMA;
                    break;
                case '<':
                    rSVCode = KEY_LESS;
                    break;
                case '>':
                    rSVCode = KEY_GREATER;
                    break;
                case '=':
                    rSVCode = KEY_EQUAL;
                    break;
            }
        }
    }

    // "Numlock-Hack": we want to get correct keycodes from the numpad
    if ( (nCharCode >= '0') && (nCharCode <= '9') && !(nKeyFlags & KC_SHIFT) )
        rSVCode = KEYGROUP_NUM + (nCharCode-'0');
    if ( nCharCode == ',' )
        rSVCode = KEY_COMMA;
    if ( nCharCode == '.' )
        rSVCode = KEY_POINT;
	
    return rSVCode;
}

// -----------------------------------------------------------------------

static void ImplUpdateInputLang( Os2SalFrame* pFrame )
{
    BOOL 	bLanguageChange = FALSE;
    ULONG 	nLang = 0;
	APIRET	rc;
	UconvObject  uconv_object = NULL;
	LocaleObject locale_object = NULL;
	UniChar		*pinfo_item;

	// we do not support change of input language while working, 
	// so exit if already defined (mnInputLang is a static class field) 
	if (pFrame->mnInputLang)
		return;

	// get current locale
	rc = UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"", &locale_object);
	// get Win32 locale id and sublanguage (hex uni string)
	rc = UniQueryLocaleItem(locale_object, LOCI_xWinLocale, &pinfo_item);
	// convert uni string to integer
	rc = UniStrtoul(locale_object, pinfo_item, &pinfo_item, 16, &nLang);
	rc = UniFreeMem(pinfo_item);
#if OSL_DEBUG_LEVEL>10
	debug_printf("ImplUpdateInputLang nLang %04x\n", nLang);
	char         char_buffer[256];
	rc = UniCreateUconvObject((UniChar *)L"", &uconv_object);
	rc = UniQueryLocaleItem(locale_object, LOCI_sKeyboard, &pinfo_item);
	rc = UniStrFromUcs(uconv_object, char_buffer, pinfo_item, sizeof(char_buffer));
	debug_printf("Keyboard name is: %s\n", char_buffer );
	rc = UniFreeMem(pinfo_item);
#endif
	rc = UniFreeLocaleObject(locale_object);

	// keep input lang up-to-date
#if OSL_DEBUG_LEVEL>10
	debug_printf("ImplUpdateInputLang pFrame %08x lang changed from %d to %d\n", 
		pFrame, pFrame->mnInputLang, nLang);
#endif
	pFrame->mnInputLang = nLang;
}


static sal_Unicode ImplGetCharCode( Os2SalFrame* pFrame, USHORT nKeyFlags, 
									sal_Char nCharCode, UCHAR nScanCode )
{
    ImplUpdateInputLang( pFrame );
#if OSL_DEBUG_LEVEL>10
    debug_printf("ImplGetCharCode nCharCode %c, %04x\n", nCharCode, nCharCode);
#endif
    return OUString( &nCharCode, 1, gsl_getSystemTextEncoding()).toChar();
}

// -----------------------------------------------------------------------

LanguageType Os2SalFrame::GetInputLanguage()
{
    if( !mnInputLang )
        ImplUpdateInputLang( this );

    if( !mnInputLang )
        return LANGUAGE_DONTKNOW;
    else
        return (LanguageType) mnInputLang;
}

// -----------------------------------------------------------------------

BOOL Os2SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
{
    // not supported yet
    return FALSE;
}

// -----------------------------------------------------------------------

static sal_Unicode ImplConvertKey( Os2SalFrame* pFrame, MPARAM aMP1, MPARAM aMP2 )
{
    USHORT  nKeyFlags   = SHORT1FROMMP( aMP1 );
    UCHAR   nCharCode   = (UCHAR)SHORT1FROMMP( aMP2 );
    USHORT  nKeyCode    = (UCHAR)SHORT2FROMMP( aMP2 );
    UCHAR   nScanCode   = (UCHAR)CHAR4FROMMP( aMP1 );
	sal_Unicode	rSVCharCode = 0;

    // Ist Character-Code gesetzt
    // !!! Bei CTRL/ALT ist KC_CHAR nicht gesetzt, jedoch moechten wir
    // !!! dann auch einen CharCode und machen die Behandlung deshalb
    // !!! selber
    if ( (nKeyFlags & KC_CHAR) || (nKeyFlags & KC_CTRL) || (nKeyFlags & KC_ALT) )
        rSVCharCode = ImplGetCharCode( pFrame, nKeyFlags, nCharCode, nScanCode);

	// ret unicode
	return rSVCharCode;
}

// -----------------------------------------------------------------------

static long ImplHandleKeyMsg( HWND hWnd,
                              UINT nMsg, MPARAM nMP1, MPARAM nMP2 )
{
    static USHORT   nLastOS2KeyChar = 0;
    static sal_Unicode   nLastChar       = 0;
    USHORT          nRepeat         = CHAR3FROMMP( nMP1 ) - 1;
    SHORT           nFlags          = SHORT1FROMMP( nMP1 );
    USHORT          nModCode        = 0;
    USHORT          nSVCode         = 0;
    USHORT          nOS2KeyCode     = (UCHAR)SHORT2FROMMP( nMP2 );
    sal_Unicode		nSVCharCode     = 0;
    long            nRet            = 0;

    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
    if ( !pFrame )
        return 0;

    // determine modifiers
    if ( nFlags & KC_SHIFT )
        nModCode |= KEY_SHIFT;
    if ( nFlags & KC_CTRL )
        nModCode |= KEY_MOD1;
    if ( nFlags & KC_ALT )
        nModCode |= KEY_MOD2;

    // Bei Shift, Control und Alt schicken wir einen KeyModChange-Event
    if ( (nOS2KeyCode == VK_SHIFT) || (nOS2KeyCode == VK_CTRL) ||
         (nOS2KeyCode == VK_ALT) || (nOS2KeyCode == VK_ALTGRAF) )
    {
        SalKeyModEvent aModEvt;
        aModEvt.mnTime = WinQueryMsgTime( pFrame->mhAB );
        aModEvt.mnCode = nModCode;
#if OSL_DEBUG_LEVEL>10
		debug_printf("SALEVENT_KEYMODCHANGE\n");
#endif
        nRet = pFrame->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
    }
    else
    {
		nSVCode = ImplSalGetKeyCode( pFrame, nMP1, nMP2 );
        nSVCharCode = ImplConvertKey( pFrame, nMP1, nMP2 );
#if OSL_DEBUG_LEVEL>10
		debug_printf("nSVCode %04x nSVCharCode %04x\n",nSVCode,nSVCharCode );
#endif

        // Fuer Java muessen wir bei KeyUp einen CharCode liefern
        if ( nFlags & KC_KEYUP )
        {
            if ( !nSVCharCode )
            {
                if ( nLastOS2KeyChar == nOS2KeyCode )
                {
                    nSVCharCode     = nLastChar;
                    nLastOS2KeyChar = 0;
                    nLastChar       = 0;
                }
            }
            else
            {
                nLastOS2KeyChar = 0;
                nLastChar       = 0;
            }
        }
        else
        {
            nLastOS2KeyChar = nOS2KeyCode;
            nLastChar       = nSVCharCode;
        }

        if ( nSVCode || nSVCharCode )
        {
            SalKeyEvent aKeyEvt;
            aKeyEvt.mnCode      = nSVCode;
            aKeyEvt.mnTime      = WinQueryMsgTime( pFrame->mhAB );
            aKeyEvt.mnCode     |= nModCode;
            aKeyEvt.mnCharCode  = nSVCharCode;
            aKeyEvt.mnRepeat    = nRepeat;

#if OSL_DEBUG_LEVEL>10
			debug_printf( (nFlags & KC_KEYUP) ? "SALEVENT_KEYUP\n" : "SALEVENT_KEYINPUT\n");
#endif
            nRet = pFrame->CallCallback( (nFlags & KC_KEYUP) ? SALEVENT_KEYUP : SALEVENT_KEYINPUT,
                                               &aKeyEvt );
        }
    }

    return nRet;
}

// -----------------------------------------------------------------------

static bool ImplHandlePaintMsg( HWND hWnd )
{
    BOOL bMutex = FALSE;

    if ( ImplSalYieldMutexTryToAcquire() )
        bMutex = TRUE;

    // if we don't get the mutex, we can also change the clip region,
    // because other threads doesn't use the mutex from the main
    // thread --> see GetGraphics()

    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
    if ( pFrame )
    {
        // Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine
        // Paint-Region anliegt
        if ( WinQueryUpdateRect( hWnd, NULL ) )
        {
            // Call BeginPaint/EndPaint to query the rect and send
            // this Notofication to rect
			HPS     hPS;
			RECTL   aUpdateRect;
			hPS = WinBeginPaint( hWnd, NULLHANDLE, &aUpdateRect );
			WinEndPaint( hPS );

            // Paint
            if ( bMutex )
            {
		SalPaintEvent aPEvt( aUpdateRect.xLeft, pFrame->mnHeight - aUpdateRect.yTop, aUpdateRect.xRight- aUpdateRect.xLeft, aUpdateRect.yTop - aUpdateRect.yBottom );

                pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
            }
            else
            {
                RECTL* pRect = new RECTL;
                WinCopyRect( pFrame->mhAB, pRect, &aUpdateRect );
                WinPostMsg( hWnd, SAL_MSG_POSTPAINT, (MPARAM)pRect, 0 );
            }
		}
	}

    if ( bMutex )
        ImplSalYieldMutexRelease();

	return bMutex ? true : false;
}

// -----------------------------------------------------------------------

static void ImplHandlePaintMsg2( HWND hWnd, RECTL* pRect )
{
    // Paint
    if ( ImplSalYieldMutexTryToAcquire() )
    {
        Os2SalFrame* pFrame = GetWindowPtr( hWnd );
        if ( pFrame )
        {
            SalPaintEvent aPEvt( pRect->xLeft, pFrame->mnHeight - pRect->yTop, pRect->xRight - pRect->xLeft, pRect->yTop - pRect->yBottom );
            pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
        }
        ImplSalYieldMutexRelease();
        delete pRect;
    }
    else
        WinPostMsg( hWnd, SAL_MSG_POSTPAINT, (MPARAM)pRect, 0 );
}

// -----------------------------------------------------------------------

static void SetMaximizedFrameGeometry( HWND hWnd, Os2SalFrame* pFrame )
{
    // calculate and set frame geometry of a maximized window - useful if the window is still hidden

    RECTL aRect;
    pFrame->GetWorkArea( aRect);

    // a maximized window has no other borders than the caption
    pFrame->maGeometry.nLeftDecoration = pFrame->maGeometry.nRightDecoration = pFrame->maGeometry.nBottomDecoration = 0;
    pFrame->maGeometry.nTopDecoration = pFrame->mbCaption ? WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) : 0;

    aRect.yTop += pFrame->maGeometry.nTopDecoration;
    pFrame->maGeometry.nX = aRect.xLeft;
    pFrame->maGeometry.nY = aRect.yBottom;
    pFrame->maGeometry.nWidth = aRect.xRight - aRect.xLeft + 1;
    pFrame->maGeometry.nHeight = aRect.yBottom - aRect.yTop + 1;
}

static void UpdateFrameGeometry( HWND hWnd, Os2SalFrame* pFrame )
{
    if( !pFrame )
        return;

	//SalFrame has a 
	//maGeometry member that holds absolute screen positions (and needs to be 
	//updated if the window is moved by the way).
	
	// reset data
    memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) );

	SWP	swp;
	LONG nFrameX, nFrameY, nCaptionY;
	
	// get frame size 
	WinQueryWindowPos(pFrame->mhWndFrame, &swp);
	if (swp.fl & SWP_MINIMIZE)
      return;

	// map from client area to screen
    ImplSalCalcFrameSize( pFrame, nFrameX, nFrameY, nCaptionY);
    pFrame->maGeometry.nTopDecoration = nFrameY + nCaptionY;
    pFrame->maGeometry.nLeftDecoration = nFrameX;
    pFrame->maGeometry.nRightDecoration = nFrameX;
	pFrame->maGeometry.nBottomDecoration = nFrameY;

	// position of client area, not of frame corner!
    pFrame->maGeometry.nX = swp.x + nFrameX;
    pFrame->maGeometry.nY = nScreenHeight - (swp.y + swp.cy) + nFrameY + nCaptionY;

    int nWidth  = swp.cx - pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration;
    int nHeight = swp.cy - pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration;

    // clamp to zero
    pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight;
    pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth;
#if OSL_DEBUG_LEVEL>0
	debug_printf( "UpdateFrameGeometry: hwnd %x, frame %x at %d,%d (%dx%d)\n",
		hWnd, pFrame->mhWndFrame,
		pFrame->maGeometry.nX, pFrame->maGeometry.nY,
		pFrame->maGeometry.nWidth,pFrame->maGeometry.nHeight);
#endif
}

// -----------------------------------------------------------------------

static void ImplHandleMoveMsg( HWND hWnd)
{
    if ( ImplSalYieldMutexTryToAcquire() )
    {
        Os2SalFrame* pFrame = GetWindowPtr( hWnd );
        if ( pFrame )
        {
            UpdateFrameGeometry( hWnd, pFrame );

            if ( WinIsWindowVisible( hWnd ))
				pFrame->mbDefPos = FALSE;

			// Gegen moegliche Rekursionen sichern
			if ( !pFrame->mbInMoveMsg )
			{
				// Fenster im FullScreenModus wieder einpassen
				pFrame->mbInMoveMsg = TRUE;
				if ( pFrame->mbFullScreen )
					ImplSalFrameFullScreenPos( pFrame );
				pFrame->mbInMoveMsg = FALSE;
			}
		
			// Status merken
			ImplSaveFrameState( pFrame );
			
            // Call Hdl
            //#93851 if we call this handler, VCL floating windows are not updated correctly
            //ImplCallMoveHdl( hWnd );

        }
			
        ImplSalYieldMutexRelease();
    }
    else
		WinPostMsg( hWnd, SAL_MSG_POSTMOVE, 0, 0 );
}

// -----------------------------------------------------------------------

static void ImplHandleSizeMsg( HWND hWnd, MPARAM nMP2 )
{
        Os2SalFrame* pFrame = GetWindowPtr( hWnd );
        if ( pFrame )
        {
            UpdateFrameGeometry( hWnd, pFrame );
			pFrame->mbDefPos = FALSE;
			pFrame->mnWidth  = (short)SHORT1FROMMP( nMP2 );
			pFrame->mnHeight = (short)SHORT2FROMMP( nMP2 );
			if ( pFrame->mpGraphics )
				pFrame->mpGraphics->mnHeight = (int)SHORT2FROMMP(nMP2);
			// Status merken
			ImplSaveFrameState( pFrame );
			pFrame->CallCallback( SALEVENT_RESIZE, 0 );
			if ( WinIsWindowVisible( pFrame->mhWndFrame ) && !pFrame->mbInShow )
				WinUpdateWindow( pFrame->mhWndClient );
		}
}

// -----------------------------------------------------------------------

static long ImplHandleFocusMsg( Os2SalFrame* pFrame, MPARAM nMP2 )
{
if ( pFrame && !Os2SalFrame::mbInReparent )
{
    if ( SHORT1FROMMP( nMP2 ) )
    {
        if ( WinIsWindowVisible( pFrame->mhWndFrame ) && !pFrame->mbInShow )
            WinUpdateWindow( pFrame->mhWndClient );
        return pFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
    }
    else
    {
        return pFrame->CallCallback( SALEVENT_LOSEFOCUS, 0 );
    }
}
}

// -----------------------------------------------------------------------

static void ImplHandleCloseMsg( HWND hWnd )
{
    if ( ImplSalYieldMutexTryToAcquire() )
    {
        Os2SalFrame* pFrame = GetWindowPtr( hWnd );
        if ( pFrame )
        {
            pFrame->CallCallback( SALEVENT_CLOSE, 0 );
        }

        ImplSalYieldMutexRelease();
    }
    else
        WinPostMsg( hWnd, WM_CLOSE, 0, 0 );
}

// -----------------------------------------------------------------------

inline void ImplHandleUserEvent( HWND hWnd, MPARAM nMP2 )
{
    ImplSalYieldMutexAcquireWithWait();
    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
    if ( pFrame )
    {
        pFrame->CallCallback( SALEVENT_USEREVENT, (void*)nMP2 );
    }
    ImplSalYieldMutexRelease();
}

// -----------------------------------------------------------------------

static int SalImplHandleProcessMenu( Os2SalFrame* pFrame, ULONG nMsg, MPARAM nMP1, MPARAM nMP2)
{
    long nRet = 0;
debug_printf("SalImplHandleProcessMenu\n");
#if 0
    DWORD err=0;
    if( !HIWORD(wParam) )
    {
        // Menu command
        WORD nId = LOWORD(wParam);
        if( nId )   // zero for separators
        {
            SalMenuEvent aMenuEvt;
            aMenuEvt.mnId   = nId;
            WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, FALSE );
            if( pSalMenuItem )
                aMenuEvt.mpMenu = pSalMenuItem->mpMenu;
            else
                aMenuEvt.mpMenu = NULL;

            nRet = pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt );
        }
    }
#endif
    //return (nRet != 0);
    return (nRet == 0);
}

// -----------------------------------------------------------------------

static void ImplHandleInputLangChange( HWND hWnd )
{
    ImplSalYieldMutexAcquireWithWait();

    // Feststellen, ob wir IME unterstuetzen
    Os2SalFrame* pFrame = GetWindowPtr( hWnd );
#if 0
    if ( pFrame && pFrame->mbIME && pFrame->mhDefIMEContext )
    {
        HWND    hWnd = pFrame->mhWnd;
        HKL     hKL = (HKL)lParam;
        UINT    nImeProps = ImmGetProperty( hKL, IGP_PROPERTY );

        pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0;
        pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0;
        pFrame->mbHandleIME = !pFrame->mbSpezIME;
    }
#endif

    // trigger input language and codepage update
    UINT nLang = pFrame->mnInputLang;
    ImplUpdateInputLang( pFrame );
	debug_printf("ImplHandleInputLangChange new language 0x%04x\n",pFrame->mnInputLang);

    // notify change
    if( nLang != pFrame->mnInputLang )
        pFrame->CallCallback( SALEVENT_INPUTLANGUAGECHANGE, 0 );

    ImplSalYieldMutexRelease();
}

// -----------------------------------------------------------------------

#ifdef ENABLE_IME

static long ImplHandleIMEStartConversion( Os2SalFrame* pFrame )
{
    long        nRet = FALSE;
    SalIMEData* pIMEData = GetSalIMEData();
    if ( pIMEData )
    {
        HWND hWnd = pFrame->mhWndClient;
        HIMI hIMI = 0;
        pIMEData->mpGetIME( hWnd, &hIMI );
        if ( hIMI )
        {
            ULONG nProp;
            if ( 0 != pIMEData->mpQueryIMEProperty( hIMI, QIP_PROPERTY, &nProp ) )
                pFrame->mbHandleIME = FALSE;
            else
            {
                pFrame->mbHandleIME = !(nProp & PRP_SPECIALUI);

            }
            if ( pFrame->mbHandleIME )
            {
/* Windows-Code, der noch nicht angepasst wurde !!!
                // Cursor-Position ermitteln und aus der die Default-Position fuer
                // das Composition-Fenster berechnen
                SalCursorPosEvent aCursorPosEvt;
                pFrame->CallCallback( pFrame->mpInst, pFrame,
                                            SALEVENT_CURSORPOS, (void*)&aCursorPosEvt );
                COMPOSITIONFORM aForm;
                memset( &aForm, 0, sizeof( aForm ) );
                if ( !aCursorPosEvt.mnWidth || !aCursorPosEvt.mnHeight )
                    aForm.dwStyle |= CFS_DEFAULT;
                else
                {
                    aForm.dwStyle          |= CFS_POINT;
                    aForm.ptCurrentPos.x    = aCursorPosEvt.mnX;
                    aForm.ptCurrentPos.y    = aCursorPosEvt.mnY;
                }
                ImmSetCompositionWindow( hIMC, &aForm );

                // Den InputContect-Font ermitteln und diesem dem Composition-Fenster
                // bekannt machen
*/

                pFrame->mbConversionMode = TRUE;
                pFrame->CallCallback( SALEVENT_STARTEXTTEXTINPUT, (void*)NULL );
                nRet = TRUE;
            }

            pIMEData->mpReleaseIME( hWnd, hIMI );
        }
    }

    return nRet;
}

// -----------------------------------------------------------------------

static long ImplHandleIMEConversion( Os2SalFrame* pFrame, MPARAM nMP2Param )
{
    long        nRet = FALSE;
    SalIMEData* pIMEData = GetSalIMEData();
    if ( pIMEData )
    {
        HWND        hWnd = pFrame->mhWndClient;
        HIMI        hIMI = 0;
        ULONG    nMP2 = (ULONG)nMP2Param;
        pIMEData->mpGetIME( hWnd, &hIMI );
        if ( hIMI )
        {
            if ( nMP2 & (IMR_RESULT_RESULTSTRING |
                         IMR_CONV_CONVERSIONSTRING | IMR_CONV_CONVERSIONATTR |
                         IMR_CONV_CURSORPOS | IMR_CONV_CURSORATTR) )
            {
                SalExtTextInputEvent aEvt;
                aEvt.mnTime             = WinQueryMsgTime( pFrame->mhAB );
                aEvt.mpTextAttr         = NULL;
                aEvt.mnCursorPos        = 0;
                aEvt.mnDeltaStart       = 0;
                aEvt.mbOnlyCursor       = FALSE;
                aEvt.mbCursorVisible    = TRUE;

                ULONG    nBufLen = 0;
                xub_Unicode*     pBuf = NULL;
                ULONG    nAttrBufLen = 0;
                PM_BYTE*    pAttrBuf = NULL;
                BOOL        bLastCursor = FALSE;
                if ( nMP2 & IMR_RESULT_RESULTSTRING )
                {
                    pIMEData->mpGetResultString( hIMI, IMR_RESULT_RESULTSTRING, 0, &nBufLen );
                    if ( nBufLen > 0 )
                    {
                        pBuf = new xub_Unicode[nBufLen];
                        pIMEData->mpGetResultString( hIMI, IMR_RESULT_RESULTSTRING, pBuf, &nBufLen );
                    }

                    bLastCursor = TRUE;
                    aEvt.mbCursorVisible = TRUE;
                }
                else if ( nMP2 & (IMR_CONV_CONVERSIONSTRING | IMR_CONV_CONVERSIONATTR |
                                  IMR_CONV_CURSORPOS | IMR_CONV_CURSORATTR) )
                {
                    pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONSTRING, 0, &nBufLen );
                    if ( nBufLen > 0 )
                    {
                        pBuf = new xub_Unicode[nBufLen];
                        pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONSTRING, pBuf, &nBufLen );
                    }

                    pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONATTR, 0, &nAttrBufLen );
                    if ( nAttrBufLen > 0 )
                    {
                        pAttrBuf = new PM_BYTE[nAttrBufLen];
                        pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONATTR, pAttrBuf, &nAttrBufLen );
                    }

/* !!! Wir bekommen derzeit nur falsche Daten, deshalb zeigen wir derzeit
   !!! auch keine Cursor an
                    ULONG nTempBufLen;
                    ULONG nCursorPos = 0;
                    ULONG nCursorAttr = 0;
                    ULONG nChangePos = 0;
                    nTempBufLen = sizeof( ULONG );
                    pIMEData->mpGetConversionString( hIMI, IMR_CONV_CURSORPOS, &nCursorPos, &nTempBufLen );
                    nTempBufLen = sizeof( ULONG );
                    pIMEData->mpGetConversionString( hIMI, IMR_CONV_CURSORATTR, &nCursorAttr, &nTempBufLen );
                    nTempBufLen = sizeof( ULONG );
                    pIMEData->mpGetConversionString( hIMI, IMR_CONV_CHANGESTART, &nChangePos, &nTempBufLen );

                    aEvt.mnCursorPos = nCursorPos;
                    aEvt.mnDeltaStart = nChangePos;
                    if ( nCursorAttr & CP_CURSORATTR_INVISIBLE )
                        aEvt.mbCursorVisible = FALSE;
*/
                    aEvt.mnCursorPos = 0;
                    aEvt.mnDeltaStart = 0;
                    aEvt.mbCursorVisible = FALSE;

                    if ( (nMP2 == IMR_CONV_CURSORPOS) ||
                         (nMP2 == IMR_CONV_CURSORATTR) )
                        aEvt.mbOnlyCursor = TRUE;
                }

                USHORT* pSalAttrAry = NULL;
                if ( pBuf )
                {
                    aEvt.maText = XubString( pBuf, (USHORT)nBufLen );
                    delete [] pBuf;
                    if ( pAttrBuf )
                    {
                        USHORT nTextLen = aEvt.maText.Len();
                        if ( nTextLen )
                        {
                            pSalAttrAry = new USHORT[nTextLen];
                            memset( pSalAttrAry, 0, nTextLen*sizeof( USHORT ) );
                            for ( USHORT i = 0; (i < nTextLen) && (i < nAttrBufLen); i++ )
                            {
                                PM_BYTE nOS2Attr = pAttrBuf[i];
                                USHORT  nSalAttr;
                                if ( nOS2Attr == CP_ATTR_TARGET_CONVERTED )
                                    nSalAttr = SAL_EXTTEXTINPUT_ATTR_TARGETCONVERTED | SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
                                else if ( nOS2Attr == CP_ATTR_CONVERTED )
                                    nSalAttr = SAL_EXTTEXTINPUT_ATTR_CONVERTED | SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE;
                                else if ( nOS2Attr == CP_ATTR_TARGET_NOTCONVERTED )
                                    nSalAttr = SAL_EXTTEXTINPUT_ATTR_TARGETNOTCONVERTED | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
                                else if ( nOS2Attr == CP_ATTR_INPUT_ERROR )
                                    nSalAttr = SAL_EXTTEXTINPUT_ATTR_INPUTERROR | SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
                                else /* ( nOS2Attr == CP_ATTR_INPUT ) */
                                    nSalAttr = SAL_EXTTEXTINPUT_ATTR_INPUT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE;
                                pSalAttrAry[i] = nSalAttr;
                            }
                            aEvt.mpTextAttr = pSalAttrAry;
                        }
                        delete [] pAttrBuf;
                    }
                    if ( bLastCursor )
                        aEvt.mnCursorPos = aEvt.maText.Len();
                }

                pIMEData->mpReleaseIME( hWnd, hIMI );

                // Handler rufen und wenn wir ein Attribute-Array haben, danach
                // wieder zerstoeren
                pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt );
                if ( pSalAttrAry )
                    delete [] pSalAttrAry;
            }
            else
                pIMEData->mpReleaseIME( hWnd, hIMI );
        }

        nRet = TRUE;
    }

    return nRet;
}

// -----------------------------------------------------------------------

inline long ImplHandleIMEEndConversion( Os2SalFrame* pFrame )
{
    pFrame->mbConversionMode = FALSE;
    pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL );
    return TRUE;
}

// -----------------------------------------------------------------------

static void ImplHandleIMEOpenCandidate( Os2SalFrame* pFrame )
{
    pFrame->mbCandidateMode = TRUE;

    long        nRet = FALSE;
    SalIMEData* pIMEData = GetSalIMEData();
    if ( pIMEData )
    {
        HWND        hWnd = pFrame->mhWndClient;
        HIMI        hIMI = 0;
        pIMEData->mpGetIME( hWnd, &hIMI );
        if ( hIMI )
        {
            ULONG nBufLen = 0;
            pIMEData->mpGetConversionString( hIMI, IMR_CONV_CONVERSIONSTRING, 0, &nBufLen );
            if ( nBufLen > 0 )
            {
/* !!! Wir bekommen derzeit nur falsche Daten steht der Cursor immer bei 0
                ULONG nTempBufLen = sizeof( ULONG );
                ULONG nCursorPos = 0;
                pIMEData->mpGetConversionString( hIMI, IMR_CONV_CURSORPOS, &nCursorPos, &nTempBufLen );
*/
                ULONG nCursorPos = 0;

                SalExtTextInputPosEvent aEvt;
                aEvt.mnTime         = WinQueryMsgTime( pFrame->mhAB );
                aEvt.mnFirstPos     = nCursorPos;
                aEvt.mnChars        = nBufLen-nCursorPos;
                aEvt.mpPosAry       = new SalExtCharPos[aEvt.mnChars];
                memset( aEvt.mpPosAry, 0, aEvt.mnChars*sizeof(SalExtCharPos) );

                pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aEvt );

                long nMinLeft   = aEvt.mpPosAry[0].mnX;
                long nMinTop    = aEvt.mpPosAry[0].mnY;
                long nMaxBottom = aEvt.mpPosAry[0].mnY+aEvt.mpPosAry[0].mnHeight;
                long nMaxRight  = nMinLeft;
                USHORT i = 0;
                while ( i < aEvt.mnChars )
                {
                    // Solange wir uns auf der gleichen Zeile bewegen,
                    // ermitteln wir die Rechteck-Grenzen
                    if ( !aEvt.mpPosAry[i].mnHeight ||
                         (aEvt.mpPosAry[i].mnY < nMaxBottom-1) )
                    {
                        if ( aEvt.mpPosAry[i].mnX < nMinLeft )
                            nMinLeft = aEvt.mpPosAry[i].mnX;
                        if ( aEvt.mpPosAry[i].mnX+aEvt.mpPosAry[0].mnWidth > nMaxRight )
                            nMaxRight = aEvt.mpPosAry[i].mnX+aEvt.mpPosAry[0].mnWidth;
                        if ( aEvt.mpPosAry[i].mnY < nMinTop )
                            nMinTop = aEvt.mpPosAry[i].mnY;
                        i++;
                    }
                    else
                        break;
                }

                CANDIDATEPOS aForm;
                aForm.ulIndex           = 0;
                aForm.ulStyle           = CPS_EXCLUDE;
                aForm.ptCurrentPos.x    = aEvt.mpPosAry[0].mnX;
                aForm.ptCurrentPos.y    = pFrame->mnHeight - (nMaxBottom+1) - 1;
                aForm.rcArea.xLeft      = nMinLeft;
                aForm.rcArea.yBottom    = pFrame->mnHeight - nMaxBottom - 1;
                aForm.rcArea.xRight     = nMaxRight+1;
                aForm.rcArea.yTop       = pFrame->mnHeight - nMinTop - 1;
                pIMEData->mpSetCandidateWin( hIMI, &aForm );

                delete aEvt.mpPosAry;
            }

            pIMEData->mpReleaseIME( hWnd, hIMI );
        }
    }
}

// -----------------------------------------------------------------------

inline void ImplHandleIMECloseCandidate( Os2SalFrame* pFrame )
{
    pFrame->mbCandidateMode = FALSE;
}

#endif

// -----------------------------------------------------------------------

MRESULT EXPENTRY SalFrameWndProc( HWND hWnd, ULONG nMsg,
                                  MPARAM nMP1, MPARAM nMP2 )
{
    Os2SalFrame*   	pFrame      = (Os2SalFrame*)GetWindowPtr( hWnd );
    MRESULT     	nRet        = (MRESULT)0;
    BOOL        	bDef     	= TRUE;
	bool 			bCheckTimers= false;

#if OSL_DEBUG_LEVEL>10
    if (nMsg!=WM_TIMER && nMsg!=WM_MOUSEMOVE)
        debug_printf( "SalFrameWndProc hWnd 0x%x nMsg 0x%x\n", hWnd, nMsg);
#endif

    switch( nMsg )
    {
        case WM_MOUSEMOVE:
        case WM_BUTTON1DOWN:
        case WM_BUTTON2DOWN:
        case WM_BUTTON3DOWN:
        case WM_BUTTON1DBLCLK:
        case WM_BUTTON2DBLCLK:
        case WM_BUTTON3DBLCLK:
        case WM_BUTTON1UP:
        case WM_BUTTON2UP:
        case WM_BUTTON3UP:
        case SAL_MSG_MOUSELEAVE:
            // ButtonUp/Down nie an die WinDefWindowProc weiterleiten, weil sonst
            // die Message an den Owner weitergeleitet wird
            ImplSalYieldMutexAcquireWithWait();
            bDef = !ImplHandleMouseMsg( hWnd, nMsg, nMP1, nMP2 );
            ImplSalYieldMutexRelease();
            break;

        case WM_CHAR:
            if ( pFrame->mbConversionMode )
                bDef = FALSE;
            else
                bDef = !ImplHandleKeyMsg( hWnd, nMsg, nMP1, nMP2 );
            break;

        case WM_ERASEBACKGROUND:
            nRet = (MRESULT)FALSE;
            bDef = FALSE;
            break;

        case WM_PAINT:
            bCheckTimers = ImplHandlePaintMsg( hWnd );
            bDef = FALSE;
            break;
        case SAL_MSG_POSTPAINT:
        	ImplHandlePaintMsg2( hWnd, (RECTL*)nMP1 );
			bCheckTimers = true;
        	bDef = FALSE;
			break;

        case WM_MOVE:
        case SAL_MSG_POSTMOVE:
            ImplHandleMoveMsg( hWnd );
            bDef = FALSE;
            break;

        case WM_SIZE:
            if ( ImplSalYieldMutexTryToAcquire() )
            {
                ImplHandleSizeMsg( hWnd, nMP2 );
                ImplSalYieldMutexRelease();
            }
            else
                WinPostMsg( hWnd, SAL_MSG_POSTSIZE, nMP1, nMP2 );
            break;
        case SAL_MSG_POSTSIZE:
            ImplHandleSizeMsg( hWnd, nMP2 );
            break;
		case WM_MINMAXFRAME:
            if ( ImplSalYieldMutexTryToAcquire() )
            {
				PSWP pswp = (PSWP) nMP1;
                ImplHandleSizeMsg( hWnd, MPFROM2SHORT( pswp->cx, pswp->cy) );
                ImplSalYieldMutexRelease();
            }
            else
                WinPostMsg( hWnd, SAL_MSG_POSTSIZE, 0, nMP2 );
			break;

        case WM_CALCVALIDRECTS:
            return (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);

        case WM_SETFOCUS:
            if ( ImplSalYieldMutexTryToAcquire() )
            {
                ImplHandleFocusMsg( pFrame, nMP2 );
                ImplSalYieldMutexRelease();
            }
            else
                WinPostMsg( hWnd, SAL_MSG_POSTFOCUS, 0, nMP2 );
            break;
        case SAL_MSG_POSTFOCUS:
            ImplHandleFocusMsg( pFrame, nMP2 );
            break;

        case WM_TRANSLATEACCEL:
            {
            // Da uns OS/2 zu viele Tasten abfaegnt, unternehmen wir etwas,
            // damit wir Shift+F1, Shift+F10 und Shift+Enter bekommen
            PQMSG   pMsg        = (PQMSG)nMP1;
            USHORT  nKeyFlags   = SHORT1FROMMP( pMsg->mp1 );
            USHORT  nKeyCode    = (UCHAR)SHORT2FROMMP( pMsg->mp2 );

            if ( !(nKeyFlags & KC_KEYUP) && (nKeyFlags & KC_VIRTUALKEY) &&
                 (nKeyFlags & KC_SHIFT) && (nKeyCode != VK_ESC) )
                return (MRESULT)FALSE;

            if ( nKeyCode == VK_F1 )
                return (MRESULT)FALSE;
            }
            break;

        case WM_CREATE:
            {
				HWND hWndFrame = WinQueryWindow(hWnd, QW_PARENT);
				if (hWndFrame == 0)
					debug_printf(" WARNING NULL FRAME!!\n");
				SalData* pSalData = GetSalData();
				// Window-Instanz am Windowhandle speichern
				pFrame = pSalData->mpCreateFrame;
				pSalData->mpCreateFrame = NULL;
				SetWindowPtr( hWnd, pFrame );
				SetWindowPtr( hWndFrame, pFrame);
				// HWND schon hier setzen, da schon auf den Instanzdaten
				// gearbeitet werden kann, wenn Messages waehrend
				// CreateWindow() gesendet werden
				pFrame->mhWndClient = hWnd;
				pFrame->mhWndFrame = hWndFrame;
				pFrame->maSysData.hWnd = hWnd;
            }
            break;

        case WM_CLOSE:
            ImplHandleCloseMsg( hWnd );
            bDef = FALSE;
            break;

        case WM_SYSVALUECHANGED:
            if ( pFrame->mbFullScreen )
                ImplSalFrameFullScreenPos( pFrame );
            // kein break, da der Rest auch noch verarbeitet werden soll
        case PL_ALTERED:
        case WM_SYSCOLORCHANGE:
            ImplSalYieldMutexAcquire();
            pFrame->CallCallback( SALEVENT_SETTINGSCHANGED, 0 );
            ImplSalYieldMutexRelease();
            break;

        case SAL_MSG_USEREVENT:
            ImplHandleUserEvent( hWnd, nMP2 );
            bDef = FALSE;
            break;
        case SAL_MSG_TOTOP:
            ImplSalToTop( hWnd, (ULONG)nMP1 );
            bDef = FALSE;
            break;
        case SAL_MSG_SHOW:
            ImplSalShow( hWnd, (ULONG)nMP1, (ULONG)nMP2 );
            bDef = FALSE;
            break;

		case WM_KBDLAYERCHANGED:
			debug_printf("hWnd 0x%08x WM_KBDLAYERCHANGED\n", hWnd);
            ImplHandleInputLangChange( hWnd );
            break;

		case WM_HSCROLL:
		case WM_VSCROLL:
			ImplHandleWheelMsg( hWnd, nMsg, nMP1, nMP2 );
            bDef = FALSE;
			break;

        case WM_COMMAND:
        case SAL_MSG_SYSPROCESSMENU:
            if ( SalImplHandleProcessMenu( pFrame, nMsg, nMP1, nMP2 ) )
            {
                bDef = FALSE;
                nRet = (MRESULT)1;
            }
            break;

#ifdef ENABLE_IME
        case WM_IMEREQUEST:
            if ( (ULONG)nMP1 == IMR_CONVRESULT )
            {
                if ( pFrame->mbHandleIME )
                {
                    // Nur im Conversionmodus akzeptieren wir den IME-Input
                    if ( pFrame->mbConversionMode )
                    {
                        ImplSalYieldMutexAcquire();
                        if ( ImplHandleIMEConversion( pFrame, nMP2 ) )
                        {
                            bDef = FALSE;
                            nRet = (MRESULT)TRUE;
                        }
                        ImplSalYieldMutexRelease();
                    }
                }
            }
            else if ( (ULONG)nMP1 == IMR_CANDIDATE )
            {
                if ( pFrame->mbHandleIME )
                {
                    ImplSalYieldMutexAcquire();
                    if ( (ULONG)nMP2 & IMR_CANDIDATE_SHOW )
                        ImplHandleIMEOpenCandidate( pFrame );
                    else if ( (ULONG)nMP2 & IMR_CANDIDATE_HIDE )
                        ImplHandleIMECloseCandidate( pFrame );
                    ImplSalYieldMutexRelease();
                }
            }
            break;

        case WM_IMENOTIFY:
            if ( (ULONG)nMP1 == IMN_STARTCONVERSION )
            {
                ImplSalYieldMutexAcquire();
                if ( ImplHandleIMEStartConversion( pFrame ) )
                {
                    bDef = FALSE;
                    nRet = (MRESULT)TRUE;
                }
                ImplSalYieldMutexRelease();
            }
            else if ( (ULONG)nMP1 == IMN_ENDCONVERSION )
            {
                if ( pFrame->mbHandleIME )
                {
                    ImplSalYieldMutexAcquire();
                    if ( ImplHandleIMEEndConversion( pFrame ) )
                    {
                        bDef = FALSE;
                        nRet = (MRESULT)TRUE;
                    }
                    ImplSalYieldMutexRelease();
                }
            }
            break;
#endif
    }

	if( bCheckTimers )
	{
		SalData* pSalData = GetSalData();
		if( pSalData->mnNextTimerTime )
		{
			ULONG nCurTime;
			DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, (PVOID)&nCurTime, sizeof(ULONG));
			if( pSalData->mnNextTimerTime < nCurTime )
			{
				QMSG aMsg;
				if (!WinPeekMsg( pFrame->mhAB, &aMsg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE ) )
					WinPostMsg( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, (MPARAM)nCurTime );
			}
		}
	}

    if ( bDef )
        nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );

    return nRet;
}

// -----------------------------------------------------------------------

void Os2SalFrame::ResetClipRegion()
{
}

void Os2SalFrame::BeginSetClipRegion( ULONG )
{
}

void Os2SalFrame::UnionClipRegion( long, long, long, long )
{
}

void Os2SalFrame::EndSetClipRegion()
{
}

// -----------------------------------------------------------------------

MRESULT EXPENTRY SalFrameSubClassWndProc( HWND hWnd, ULONG nMsg,
                                  MPARAM nMP1, MPARAM nMP2 )
{
    MRESULT mReturn = 0L;

    // ticket#124 min size of 132 px is too much
    if (nMsg == WM_QUERYTRACKINFO) {
	PTRACKINFO pti;
	// first, let PM initialize TRACKINFO
	mReturn = aSalShlData.mpFrameProc( hWnd, nMsg, nMP1, nMP2 );
	// now change default min size
	pti = (PTRACKINFO) nMP2;
	pti->ptlMinTrackSize.x = 64L;
	// now return to PM
	return mReturn;
    }

    return aSalShlData.mpFrameProc( hWnd, nMsg, nMP1, nMP2 );
}

// -----------------------------------------------------------------------