diff options
Diffstat (limited to 'vcl/os2')
118 files changed, 16818 insertions, 0 deletions
diff --git a/vcl/os2/howto.txt b/vcl/os2/howto.txt new file mode 100644 index 000000000000..8711e8ea3b09 --- /dev/null +++ b/vcl/os2/howto.txt @@ -0,0 +1,13 @@ + +VCL positioning + +Window coordinates are parent relative, with exception of maState fields, they +have screen coordinates. + +Every window has a parent window, usually the client area of an existing window, +otherwise the desktop window. + +When a window is to be sized/moved, SetPosSize is called. +Since coordinates are the position/size of client area, we need to calculate +current window frame size/position and map to screen coordinates using the +owner window position as offset. diff --git a/vcl/os2/inc/salbmp.h b/vcl/os2/inc/salbmp.h new file mode 100644 index 000000000000..ab372b486ae2 --- /dev/null +++ b/vcl/os2/inc/salbmp.h @@ -0,0 +1,112 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salbmp.h,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALBMP_H +#define _SV_SALBMP_H + +#include <tools/gen.hxx> +#include <vcl/sv.h> +#include <vcl/salbmp.hxx> + +// -------------- +// - SalBitmap - +// -------------- + +struct BitmapBuffer; +class BitmapColor; +class BitmapPalette; +class SalGraphics; + +#define HANDLE ULONG +#define HBITMAP ULONG + +class Os2SalBitmap : public SalBitmap +{ +private: + + Size maSize; + HANDLE mhDIB; + HANDLE mhDIB1Subst; + HBITMAP mhDDB; + USHORT mnBitCount; + +public: + + HANDLE ImplGethDIB() const { return mhDIB; } + HBITMAP ImplGethDDB() const { return mhDDB; } + HANDLE ImplGethDIB1Subst() const { return mhDIB1Subst; } + + void ImplReplacehDIB1Subst( HANDLE hDIB1Subst ); + + static HANDLE ImplCreateDIB( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal ); + static HANDLE ImplCreateDIB4FromDIB1( HANDLE hDIB1 ); + static HANDLE ImplCopyDIBOrDDB( HANDLE hHdl, BOOL bDIB ); + static USHORT ImplGetDIBColorCount( HANDLE hDIB ); + static void ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf, + const Size& rSizePixel, BOOL bRLE4 ); + + //BOOL Create( HANDLE hBitmap, BOOL bDIB, BOOL bCopyHandle ); + +public: + + Os2SalBitmap(); + ~Os2SalBitmap(); + +public: + + //BOOL Create( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal ); + //BOOL Create( const SalBitmap& rSalBmpImpl ); + //BOOL Create( const SalBitmap& rSalBmpImpl, SalGraphics* pGraphics ); + //BOOL Create( const SalBitmap& rSalBmpImpl, USHORT nNewBitCount ); + + //void Destroy(); + + //Size GetSize() const { return maSize; } + //USHORT GetBitCount() const { return mnBitCount; } + + //BitmapBuffer* AcquireBuffer( bool bReadOnly ); + //void ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ); + bool Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle ); + virtual bool Create( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal ); + virtual bool Create( const SalBitmap& rSalBmpImpl ); + virtual bool Create( const SalBitmap& rSalBmpImpl, SalGraphics* pGraphics ); + virtual bool Create( const SalBitmap& rSalBmpImpl, USHORT nNewBitCount ); + + virtual void Destroy(); + + virtual Size GetSize() const { return maSize; } + virtual USHORT GetBitCount() const { return mnBitCount; } + + virtual BitmapBuffer* AcquireBuffer( bool bReadOnly ); + virtual void ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ); + virtual bool GetSystemData( BitmapSystemData& rData ); +}; + +#endif // _SV_SALBMP_H diff --git a/vcl/os2/inc/saldata.hxx b/vcl/os2/inc/saldata.hxx new file mode 100644 index 000000000000..3ea194330672 --- /dev/null +++ b/vcl/os2/inc/saldata.hxx @@ -0,0 +1,310 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: saldata.hxx,v $ + * $Revision: 1.7 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALDATA_HXX +#define _SV_SALDATA_HXX + +#include <vcl/sv.h> +#include <vcl/svdata.hxx> +#include <vcl/salwtype.hxx> + +class Os2SalInstance; +class Os2SalFrame; +class Os2SalObject; + +extern "C" int debug_printf(const char *f, ...); + +// -------------- +// - SalIMEData - +// -------------- + +// YD FIXME #define ENABLE_IME + +#ifdef ENABLE_IME + +struct SalIMEData; + +#ifdef OS2IM_INCLUDED + +typedef APIRET (APIENTRY ImAssociateInstanceFunc)( HWND hwnd, HIMI himi, PHIMI phimiPrev ); +typedef APIRET (APIENTRY ImGetInstanceFunc)( HWND hwnd, PHIMI phimi ); +typedef APIRET (APIENTRY ImReleaseInstanceFunc)( HWND hwnd, HIMI himi ); +typedef APIRET (APIENTRY ImSetConversionFontFunc)( HIMI himi, PFATTRS pFontAttrs ); +typedef APIRET (APIENTRY ImSetConversionFontSizeFunc)( HIMI himi, PSIZEF psizfxBox ); +typedef APIRET (APIENTRY ImGetConversionStringFunc)( HIMI himi, ULONG ulIndex, PVOID pBuf, PULONG pulBufLen ); +typedef APIRET (APIENTRY ImGetResultStringFunc)( HIMI himi, ULONG ulIndex, PVOID pBuf, PULONG pulBufLen ); +typedef APIRET (APIENTRY ImSetCandidateWindowPosFunc)( HIMI himi, PCANDIDATEPOS pCandidatePos ); +typedef APIRET (APIENTRY ImQueryIMEPropertyFunc)( HIMI himi, ULONG ulIndex, PULONG pulProp ); +typedef APIRET (APIENTRY ImRequestIMEFunc)( HIMI himi, ULONG ulAction, ULONG ulIndex, ULONG ulValue ); +typedef APIRET (APIENTRY ImSetIMModeFunc)( HIMI himi, ULONG ulInputMode, ULONG ulConversionMode ); +typedef APIRET (APIENTRY ImQueryIMModeFunc)( HIMI himi, PULONG pulInputMode, PULONG pulConversionMode ); + +struct SalIMEData +{ + HMODULE mhModIME; + ImAssociateInstanceFunc* mpAssocIME; + ImGetInstanceFunc* mpGetIME; + ImReleaseInstanceFunc* mpReleaseIME; + ImSetConversionFontFunc* mpSetConversionFont; + ImSetConversionFontSizeFunc* mpSetConversionFontSize; + ImGetConversionStringFunc* mpGetConversionString; + ImGetResultStringFunc* mpGetResultString; + ImSetCandidateWindowPosFunc* mpSetCandidateWin; + ImQueryIMEPropertyFunc* mpQueryIMEProperty; + ImRequestIMEFunc* mpRequestIME; + ImSetIMModeFunc* mpSetIMEMode; + ImQueryIMModeFunc* mpQueryIMEMode; +}; + +#endif + +#endif + +// -------------------- +// - Icon cache - +// -------------------- + +struct SalIcon +{ + int nId; + HPOINTER hIcon; + SalIcon *pNext; +}; + +// ----------- +// - SalData - +// ----------- + +struct SalData +{ + HAB mhAB; // anchor block handle + HMQ mhMQ; // handle of os2 message queue + int mnArgc; // commandline param count + char** mpArgv; // commandline + ULONG mnNewTimerMS; // Neue Zeit, mit dem der Timer gestartet werden soll + ULONG mnTimerMS; // Current Time (in MS) of the Timer + ULONG mnTimerOrgMS; // Current Original Time (in MS) + ULONG mnNextTimerTime; + ULONG mnLastEventTime; + ULONG mnTimerId; // os2 timer id + BOOL mbInTimerProc; // timer event is currently being dispatched + //SALTIMERPROC mpTimerProc; // timer callback proc + HWND mhWantLeaveMsg; // window handle, that want a MOUSELEAVE message + AutoTimer* mpMouseLeaveTimer; // Timer for MouseLeave Test + Os2SalInstance* mpFirstInstance; // pointer of first instance + Os2SalFrame* mpFirstFrame; // pointer of first frame + Os2SalFrame* mpCreateFrame; // Create-Frame for WM_CREATE + Os2SalObject* mpFirstObject; // pointer of first object window + ULONG mnAppThreadId; // Id from Applikation-Thread + ULONG mnFontMetricCount; // number of entries in the font list + PFONTMETRICS mpFontMetrics; // cached font list + BOOL mbObjClassInit; // Ist SALOBJECTCLASS initialised +#ifdef ENABLE_IME + SalIMEData* mpIMEData; // SalIME-Data + BOOL mbIMEInit; // SalIME-Data-Init +#endif + + SalIcon* mpFirstIcon; // icon cache, points to first icon, NULL if none + +}; + +inline void SetSalData( SalData* pData ) { ImplGetSVData()->mpSalData = (void*)pData; } +inline SalData* GetSalData() { return (SalData*)ImplGetSVData()->mpSalData; } +inline SalData* GetAppSalData() { return (SalData*)ImplGetAppSVData()->mpSalData; } + +// -------------- +// - SalShlData - +// -------------- + +#define OS2_VER_211 211 +#define OS2_VER_WARP3 230 +#define OS2_VER_WARP4 240 + +struct SalShlData +{ + HMODULE mhMod; // Module handle of SAL-DLL + USHORT mnVersion; // 211 = OS2 2.11; 230 = OS2 3.0; 240 = OS2 4.0 + PFNWP mpFrameProc; // old frame proc +}; + +extern SalShlData aSalShlData; + +BOOL SalImplHandleProcessMenu( HWND hWnd, ULONG nMsg, MPARAM nMP1, MPARAM nMP2 ); + +// -------------------------------------------- +// - SALSHL.CXX - for accessing DLL resources - +// -------------------------------------------- + +HPOINTER ImplLoadSalCursor( int nId ); +HBITMAP ImplLoadSalBitmap( int nId ); +BOOL ImplLoadSalIcon( int nId, HPOINTER& rIcon); + +// SALGDI.CXX +void ImplInitSalGDI(); +void ImplFreeSalGDI(); + +// -------------- +// - Prototypes - +// -------------- + +// \\OS2\SOURCE\APP\SALINST.CXX +void ImplSalYieldMutexAcquireWithWait(); +ULONG ImplSalReleaseYieldMutex(); +void ImplSalAcquireYieldMutex( ULONG nCount ); +ULONG GetCurrentThreadId(); +BOOL ImplSalYieldMutexTryToAcquire(); +void ImplSalYieldMutexAcquire(); +void ImplSalYieldMutexRelease(); + +// \\OS2\SOURCE\WINDOW\SALFRAME.CXX +MRESULT EXPENTRY SalFrameWndProc( HWND hWnd, ULONG nMsg, MPARAM nMP1, MPARAM nMP2 ); +MRESULT EXPENTRY SalFrameFrameProc( HWND hWnd, ULONG nMsg, MPARAM nMP1, MPARAM nMP2 ); +// \SV\WIN\SOURCE\APP\SALTIMER.CXX +#define SALTIMERPROC_RECURSIVE 0xffffffff +void SalTimerProc( HWND hWnd, UINT nMsg, UINT nId, ULONG nTime ); + +// \WIN\SOURCE\WINDOW\SALFRAME.CXX +void SalTestMouseLeave(); + +// \\OS2\SOURCE\WINDOW\SALFRAME.CXX +// return Frame for Message-Handling +Os2SalFrame* GetSalDefaultFrame(); + +// \\OS2\SOURCE\WINDOW\SALFRAME.CXX +// IME-Daten wieder freigeben +#ifdef ENABLE_IME +void ImplReleaseSALIMEData(); +#endif + +// ----------- +// - Defines - +// ----------- + +#define SAL_PROFILE_APPNAME ((PSZ)"StarOffice") +#define SAL_PROFILE_USEDJP ((PSZ)"UseDJP") +#define SAL_PROFILE_PRINTDJP ((PSZ)"PrintDJP") +#define SAL_PROFILE_PRINTRAW ((PSZ)"PrintRAW") + +#define SAL_FRAME_WNDEXTRA sizeof(ULONG) +#define SAL_FRAME_THIS 0 +#define SAL_FRAME_CLASSNAME "SALFRAME" +#define SAL_SUBFRAME_CLASSNAME "SALSUBFRAME" +#define SAL_OBJECT_WNDEXTRA sizeof(ULONG) +#define SAL_OBJECT_THIS 0 +#define SAL_OBJECT_CLASSNAME "SALOBJECT" +#define SAL_OBJECT_CHILDCLASSNAME "SALOBJECTCHILD" +#define SAL_OBJECT_CLIPCLASSNAME "SALOBJECTCLIP" +#define SAL_COM_CLASSNAME "SALCOMWND" + +#define SAL_MOUSELEAVE_TIMEOUT 300 + +// MP1 == 0; MP2 == pData +#define SAL_MSG_USEREVENT (WM_USER+111) +// MP1 == 0; MP2 == MousePosition relativ to upper left of screen +#define SAL_MSG_MOUSELEAVE (WM_USER+112) +// MP1 == hDC; MP2 == 0 +#define SAL_MSG_PRINTABORTJOB (WM_USER+113) +// MP1 == 0; MP2 == 0 +#define SAL_MSG_STARTTIMER (WM_USER+114) +// MP1 == nFrameStyle; MP2 == pParent; lResult pFrame +#define SAL_MSG_CREATEFRAME (WM_USER+115) +// MP1 == 0; MP2 == pParent; lResult pObject +#define SAL_MSG_CREATEOBJECT (WM_USER+116) +// MP1 == bWait; MP2 == pMutex +#define SAL_MSG_THREADYIELD (WM_USER+117) +// MP1 == 0; MP2 == 0 +#define SAL_MSG_RELEASEWAITYIELD (WM_USER+118) +// MP1 == 0; MP2 == pData +#define SAL_MSG_SYSPROCESSMENU (WM_USER+119) +// POSTFOCUS-Message; MP1 == nMP1; MP2 == nMP2 (SHORT1( bFocus ), 0) +#define SAL_MSG_POSTFOCUS (WM_USER+120) +// POSTSIZE-Message; MP1 == nMP1; MP2 == nMP2 +#define SAL_MSG_POSTSIZE (WM_USER+121) + +// wParam == wParam; lParam == lParam +#define SAL_MSG_POSTMOVE (WM_USER+136) +// wParam == pRECT; lParam == 0 +#define SAL_MSG_POSTPAINT (WM_USER+137) +// wParam == nFlags; lParam == 0 +#define SAL_MSG_TOTOP (WM_USER+142) +// wParam == bVisible; lParam == 0 +#define SAL_MSG_SHOW (WM_USER+143) + +// SysChild-ToTop; nMP1 = 0; nMP2 = 0 +#define SALOBJ_MSG_TOTOP (WM_USER+150) +// POSTFOCUS-Message; MP1 == nMP1; MP2 == nMP2 (SHORT1( bFocus ), 0) +#define SALOBJ_MSG_POSTFOCUS (WM_USER+151) + +// wParam == 0; lParam == 0 +#define SAL_MSG_DESTROYFRAME (WM_USER+160) +// wParam == 0; lParam == pObject; +#define SAL_MSG_DESTROYOBJECT (WM_USER+161) +// wParam == 0; lParam == this; lResult == bRet +#define SAL_MSG_CREATESOUND (WM_USER+162) +// wParam == 0; lParam == this +#define SAL_MSG_DESTROYSOUND (WM_USER+163) +// wParam == hWnd; lParam == 0; lResult == hDC +#define SAL_MSG_GETDC (WM_USER+164) +// wParam == hWnd; lParam == 0 +#define SAL_MSG_RELEASEDC (WM_USER+165) +// wParam == newParentHwnd; lParam == oldHwnd; lResult == newhWnd +#define SAL_MSG_RECREATEHWND (WM_USER+166) +// wParam == newParentHwnd; lParam == oldHwnd; lResult == newhWnd +#define SAL_MSG_RECREATECHILDHWND (WM_USER+167) +// wParam == 0; lParam == HWND; +#define SAL_MSG_DESTROYHWND (WM_USER+168) +// POSTTIMER-Message; wparam = 0, lParam == time +#define SAL_MSG_POSTTIMER (WM_USER+169) + +// ----------------- +// - Helpfunctions - +// ----------------- + +inline void SetWindowPtr( HWND hWnd, SalFrame* pThis ) +{ + WinSetWindowULong( hWnd, SAL_FRAME_THIS, (ULONG)pThis ); +} + +inline Os2SalFrame* GetWindowPtr( HWND hWnd ) +{ + return (Os2SalFrame*)WinQueryWindowULong( hWnd, SAL_FRAME_THIS ); +} + +inline void SetSalObjWindowPtr( HWND hWnd, SalObject* pThis ) +{ + WinSetWindowULong( hWnd, SAL_OBJECT_THIS, (ULONG)pThis ); +} + +inline Os2SalObject* GetSalObjWindowPtr( HWND hWnd ) +{ + return (Os2SalObject*)WinQueryWindowULong( hWnd, SAL_OBJECT_THIS ); +} + +#endif // _SV_SALDATA_HXX diff --git a/vcl/os2/inc/salframe.h b/vcl/os2/inc/salframe.h new file mode 100644 index 000000000000..dd8c441ca255 --- /dev/null +++ b/vcl/os2/inc/salframe.h @@ -0,0 +1,169 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salframe.h,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALFRAME_H +#define _SV_SALFRAME_H + +#include <vcl/sv.h> +#include <vcl/sysdata.hxx> +#include <vcl/salframe.hxx> + + +#ifndef PM_BIDI_INCLUDED +#include <pmbidi.h> +#endif + +#ifndef __UCONV_H__ +#include <uconv.h> +#endif + +#ifndef __UNIDEF_H__ +#include <unidef.h> +#endif + +#ifndef __UNIKBD_H__ +#include <unikbd.h> +#endif + +//class SalFrame; +class Os2SalGraphics; + +// ---------------- +// - SalFrameData - +// ---------------- + +//class SalFrameData +class Os2SalFrame : public SalFrame +{ +public: + HWND mhWndFrame; // HWND-Frame + HWND mhWndClient; // HWND-Client + HAB mhAB; // HAB + HPOINTER mhPointer; // Current MousePointer + void* mpInst; // VCL-Instance + //SALFRAMEPROC mpProc; // VCL-Proc + Os2SalGraphics* mpGraphics; // current frame graphics + Os2SalFrame* mpNextFrame; // pointer to next frame + SystemEnvData maSysData; // system data + SalFrameState maState; // frame state + int mnShowState; // show state + ULONG mnStyle; // SalFrameStyle + long mnWidth; // Window-Witdth + long mnHeight; // Window-Height + SWP maFullScreenRect; // WindowRect befor FullScreenMode + BOOL mbGraphics; // is Graphics used + BOOL mbAllwayOnTop; // Allways on top modus + BOOL mbVisible; // Visible Show/Hide-Status + BOOL mbMinHide; // hide called from OS2 + BOOL mbHandleIME; // TRUE: Wir handeln die IME-Messages + BOOL mbConversionMode; // TRUE: Wir befinden uns im Conversion-Modus + BOOL mbCandidateMode; // TRUE: Wir befinden uns im Candidate-Modus + BOOL mbCaption; // has window a caption + BOOL mbBorder; // has window a border + BOOL mbFixBorder; // has window a fixed border + BOOL mbSizeBorder; // has window a sizeable border + BOOL mbNoIcon; // is an window without an icon + BOOL mbFloatWin; // is a FloatingWindow + BOOL mbFullScreen; // TRUE: in full screen mode + BOOL mbPresentation; // TRUE: Presentation Mode running + BOOL mbInShow; // innerhalb eines Show-Aufrufs + BOOL mbRestoreMaximize; // Restore-Maximize + BOOL mbInMoveMsg; // Move-Message wird verarbeitet + BOOL mbInSizeMsg; // Size-Message wird verarbeitet + BOOL mbFullScreenToolWin; // WS_EX_TOOLWINDOW reset in FullScreenMode + BOOL mbDefPos; // default-position + BOOL mbOverwriteState; // TRUE: WindowState darf umgesetzt werden + + int mnMinWidth; // min. client width in pixeln + int mnMinHeight; // min. client height in pixeln + int mnMaxWidth; // max. client width in pixeln + int mnMaxHeight; // max. client height in pixeln + static ULONG mnInputLang; // current Input Language + KHAND mnKeyboardHandle; // current unicode keyboard + static BOOL mbInReparent; // TRUE: ignore focus lost and gain due to reparenting + +private: + Os2SalFrame* mpParentFrame; // parent frame pointer + +public: + Os2SalFrame(); + virtual ~Os2SalFrame(); + + virtual SalGraphics* GetGraphics(); + virtual void ReleaseGraphics( SalGraphics* pGraphics ); + virtual BOOL PostEvent( void* pData ); + virtual void SetTitle( const XubString& rTitle ); + virtual void SetIcon( USHORT nIcon ); + virtual void SetMenu( SalMenu* pSalMenu ); + virtual void DrawMenuBar(); + virtual void SetExtendedFrameStyle( SalExtStyle nExtStyle ); + virtual void Show( BOOL bVisible, BOOL bNoActivate = FALSE ); + virtual void Enable( BOOL bEnable ); + virtual void SetMinClientSize( long nWidth, long nHeight ); + virtual void SetMaxClientSize( long nWidth, long nHeight ); + virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight, USHORT nFlags ); + virtual void GetClientSize( long& rWidth, long& rHeight ); + virtual void GetWorkArea( RECTL& rRect ); + virtual void GetWorkArea( Rectangle& rRect ); + virtual SalFrame* GetParent() const; + virtual void SetWindowState( const SalFrameState* pState ); + virtual BOOL GetWindowState( SalFrameState* pState ); + virtual void ShowFullScreen( BOOL bFullScreen, sal_Int32 nDisplay ); + virtual void StartPresentation( BOOL bStart ); + virtual void SetAlwaysOnTop( BOOL bOnTop ); + virtual void ToTop( USHORT nFlags ); + virtual void SetPointer( PointerStyle ePointerStyle ); + virtual void CaptureMouse( BOOL bMouse ); + virtual void SetPointerPos( long nX, long nY ); + virtual void Flush(); + virtual void Sync(); + virtual void SetInputContext( SalInputContext* pContext ); + virtual void EndExtTextInput( USHORT nFlags ); + virtual String GetKeyName( USHORT nKeyCode ); + virtual String GetSymbolKeyName( const XubString& rFontName, USHORT nKeyCode ); + virtual BOOL MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode ); + virtual LanguageType GetInputLanguage(); + virtual SalBitmap* SnapShot(); + virtual void UpdateSettings( AllSettings& rSettings ); + virtual void Beep( SoundType eSoundType ); + virtual const SystemEnvData* GetSystemData() const; + virtual SalPointerState GetPointerState(); + virtual void SetParent( SalFrame* pNewParent ); + virtual bool SetPluginParent( SystemParentData* pNewParent ); + virtual void SetBackgroundBitmap( SalBitmap* ); + virtual void SetScreenNumber( unsigned int ); + virtual void ResetClipRegion(); + virtual void BeginSetClipRegion( ULONG nRects ); + virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ); + virtual void EndSetClipRegion(); + +}; + +#endif // _SV_SALFRAME_H diff --git a/vcl/os2/inc/salgdi.h b/vcl/os2/inc/salgdi.h new file mode 100644 index 000000000000..1fb51f089100 --- /dev/null +++ b/vcl/os2/inc/salgdi.h @@ -0,0 +1,376 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salgdi.h,v $ + * $Revision: 1.9.6.2 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALGDI_H +#define _SV_SALGDI_H + +#include <vcl/sv.h> +#include <vcl/sallayout.hxx> +#include <vcl/salgdi.hxx> +#include <vcl/outfont.hxx> +#include <vcl/impfont.hxx> + +#include <hash_set> + +class ImplOs2FontEntry; + +// ----------- +// - Defines - +// ----------- + +// win32 platform specific options. Move them to the PMK file? +#define GCP_USEKERNING 0x0008 +#define USE_UNISCRIBE +#define GCP_KERN_HACK +#define GNG_VERT_HACK + +// os2 specific physically available font face +class ImplOs2FontData : public ImplFontData +{ +public: + ImplOs2FontData( PFONTMETRICS, + int nFontHeight, + BYTE nPitchAndFamily ); + ~ImplOs2FontData(); + + virtual ImplFontData* Clone() const; + virtual ImplFontEntry* CreateFontInstance( ImplFontSelectData& ) const; + virtual sal_IntPtr GetFontId() const; + void SetFontId( sal_IntPtr nId ) { mnId = nId; } + void UpdateFromHPS( HPS ) const; + + bool HasChar( sal_uInt32 cChar ) const; + + PFONTMETRICS GetFontMetrics() const { return pFontMetric; } + USHORT GetCharSet() const { return meOs2CharSet; } + BYTE GetPitchAndFamily() const { return mnPitchAndFamily; } + bool IsGlyphApiDisabled() const { return mbDisableGlyphApi; } + bool SupportsKorean() const { return mbHasKoreanRange; } + bool SupportsCJK() const { return mbHasCJKSupport; } + bool AliasSymbolsHigh() const { return mbAliasSymbolsHigh; } + bool AliasSymbolsLow() const { return mbAliasSymbolsLow; } + + ImplFontCharMap* GetImplFontCharMap() const; + +private: + sal_IntPtr mnId; + mutable bool mbDisableGlyphApi; + mutable bool mbHasKoreanRange; + mutable bool mbHasCJKSupport; + + mutable ImplFontCharMap* mpUnicodeMap; + + // TODO: get rid of the members below needed to work with the Win9x non-unicode API + BYTE* mpFontCharSets; // all Charsets for the current font (used on W98 for kerning) + BYTE mnFontCharSetCount; // Number of Charsets of the current font; 0 - if not queried + USHORT meOs2CharSet; + BYTE mnPitchAndFamily; + bool mbAliasSymbolsHigh; + bool mbAliasSymbolsLow; + PFONTMETRICS pFontMetric; + +private: + void ReadCmapTable( HDC ) const; + void ReadOs2Table( HDC ) const; + +#ifdef GNG_VERT_HACK + void ReadGsubTable( HDC ) const; + + typedef std::hash_set<int> IntHashSet; + mutable IntHashSet maGsubTable; + mutable bool mbGsubRead; +public: + bool HasGSUBstitutions( HDC ) const; + bool IsGSUBstituted( sal_Unicode ) const; +#endif // GNG_VERT_HACK + +}; + + +// ------------------- +// - SalGraphicsData - +// ------------------- + +class Os2SalGraphics : public SalGraphics +{ +public: + HPS mhPS; // HPS + HDC mhDC; // HDC + HWND mhWnd; // HWND + LONG mnHeight; // Height of frame Window + ULONG mnClipElementCount; // number of clip rects in clip rect array + RECTL* mpClipRectlAry; // clip rect array + ULONG mnFontMetricCount; // number of entries in the font list + PFONTMETRICS mpFontMetrics; // cached font list + LONG mnOrientationX; // X-Font orientation + LONG mnOrientationY; // Y-Font orientation + BOOL mbLine; // draw lines + BOOL mbFill; // fill areas + BOOL mbPrinter; // is Printer + BOOL mbVirDev; // is VirDev + BOOL mbWindow; // is Window + BOOL mbScreen; // is Screen compatible + bool mbXORMode; // _every_ output with RasterOp XOR + ULONG mhFonts[ MAX_FALLBACK ]; // Font + Fallbacks + const ImplOs2FontData* mpOs2FontData[ MAX_FALLBACK ]; // pointer to the most recent font face + ImplOs2FontEntry* mpOs2FontEntry[ MAX_FALLBACK ]; // pointer to the most recent font instance + ULONG mhDefFont; // DefaultFont + float mfFontScale; // allows metrics emulation of huge font sizes + BOOL mbFontKernInit; // FALSE: FontKerns must be queried + KERNINGPAIRS* mpFontKernPairs; // Kerning Pairs of the current Font + ULONG mnFontKernPairCount;// Number of Kerning Pairs of the current Font + + USHORT ImplDoSetFont( ImplFontSelectData* i_pFont, float& o_rFontScale, int ); + +public: + Os2SalGraphics(); + virtual ~Os2SalGraphics(); + +protected: + virtual BOOL unionClipRegion( long nX, long nY, long nWidth, long nHeight ); + virtual bool unionClipRegion( const ::basegfx::B2DPolyPolygon& ); + // draw --> LineColor and FillColor and RasterOp and ClipRegion + virtual void drawPixel( long nX, long nY ); + virtual void drawPixel( long nX, long nY, SalColor nSalColor ); + virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ); + virtual void drawRect( long nX, long nY, long nWidth, long nHeight ); + virtual void drawPolyLine( ULONG nPoints, const SalPoint* pPtAry ); + virtual void drawPolygon( ULONG nPoints, const SalPoint* pPtAry ); + virtual void drawPolyPolygon( ULONG nPoly, const ULONG* pPoints, PCONSTSALPOINT* pPtAry ); + virtual bool drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency ); + virtual bool drawPolyLine( const ::basegfx::B2DPolygon&, const ::basegfx::B2DVector& rLineWidth, basegfx::B2DLineJoin); + virtual sal_Bool drawPolyLineBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ); + virtual sal_Bool drawPolygonBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ); + virtual sal_Bool drawPolyPolygonBezier( ULONG nPoly, const ULONG* pPoints, const SalPoint* const* pPtAry, const BYTE* const* pFlgAry ); + + // CopyArea --> No RasterOp, but ClipRegion + virtual void copyArea( long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, + long nSrcHeight, USHORT nFlags ); + + // CopyBits and DrawBitmap --> RasterOp and ClipRegion + // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics + virtual void copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics ); + virtual void drawBitmap( const SalTwoRect* pPosAry, const SalBitmap& rSalBitmap ); + virtual void drawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + SalColor nTransparentColor ); + virtual void drawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + const SalBitmap& rTransparentBitmap ); + virtual void drawMask( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + SalColor nMaskColor ); + + virtual SalBitmap* getBitmap( long nX, long nY, long nWidth, long nHeight ); + virtual SalColor getPixel( long nX, long nY ); + + // invert --> ClipRegion (only Windows or VirDevs) + virtual void invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags); + virtual void invert( ULONG nPoints, const SalPoint* pPtAry, SalInvert nFlags ); + + virtual BOOL drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize ); + +#if 0 + // native widget rendering methods that require mirroring + virtual BOOL hitTestNativeControl( ControlType nType, ControlPart nPart, const Region& rControlRegion, + const Point& aPos, SalControlHandle& rControlHandle, BOOL& rIsInside ); + virtual BOOL drawNativeControl( ControlType nType, ControlPart nPart, const Region& rControlRegion, + ControlState nState, const ImplControlValue& aValue, SalControlHandle& rControlHandle, + rtl::OUString aCaption ); + virtual BOOL drawNativeControlText( ControlType nType, ControlPart nPart, const Region& rControlRegion, + ControlState nState, const ImplControlValue& aValue, + SalControlHandle& rControlHandle, rtl::OUString aCaption ); + virtual BOOL getNativeControlRegion( ControlType nType, ControlPart nPart, const Region& rControlRegion, ControlState nState, + const ImplControlValue& aValue, SalControlHandle& rControlHandle, rtl::OUString aCaption, + Region &rNativeBoundingRegion, Region &rNativeContentRegion ); +#endif + + virtual bool drawAlphaBitmap( const SalTwoRect&, + const SalBitmap& rSourceBitmap, + const SalBitmap& rAlphaBitmap ); + virtual bool drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ); + +public: + // public SalGraphics methods, the interface to teh independent vcl part + + // get device resolution + virtual void GetResolution( long& rDPIX, long& rDPIY ); + // get the depth of the device + virtual USHORT GetBitCount(); + // get the width of the device + virtual long GetGraphicsWidth() const; + + // set the clip region to empty + virtual void ResetClipRegion(); + // begin setting the clip region, add rectangles to the + // region with the UnionClipRegion call + virtual void BeginSetClipRegion( ULONG nCount ); + // all rectangles were added and the clip region should be set now + virtual void EndSetClipRegion(); + + // set the line color to transparent (= don't draw lines) + virtual void SetLineColor(); + // set the line color to a specific color + virtual void SetLineColor( SalColor nSalColor ); + // set the fill color to transparent (= don't fill) + virtual void SetFillColor(); + // set the fill color to a specific color, shapes will be + // filled accordingly + virtual void SetFillColor( SalColor nSalColor ); + // enable/disable XOR drawing + virtual void SetXORMode( bool bSet, bool ); + // set line color for raster operations + virtual void SetROPLineColor( SalROPColor nROPColor ); + // set fill color for raster operations + virtual void SetROPFillColor( SalROPColor nROPColor ); + // set the text color to a specific color + virtual void SetTextColor( SalColor nSalColor ); + // set the font + virtual USHORT SetFont( ImplFontSelectData*, int nFallbackLevel ); + // get the current font's etrics + virtual void GetFontMetric( ImplFontMetricData* ); + // get kernign pairs of the current font + // return only PairCount if (pKernPairs == NULL) + virtual ULONG GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs ); + // get the repertoire of the current font + virtual ImplFontCharMap* GetImplFontCharMap() const; + // graphics must fill supplied font list + virtual void GetDevFontList( ImplDevFontList* ); + // graphics should call ImplAddDevFontSubstitute on supplied + // OutputDevice for all its device specific preferred font substitutions + virtual void GetDevFontSubstList( OutputDevice* ); + virtual bool AddTempDevFont( ImplDevFontList*, const String& rFileURL, const String& rFontName ); + // CreateFontSubset: a method to get a subset of glyhps of a font + // inside a new valid font file + // returns TRUE if creation of subset was successfull + // parameters: rToFile: contains a osl file URL to write the subset to + // pFont: describes from which font to create a subset + // pGlyphIDs: the glyph ids to be extracted + // pEncoding: the character code corresponding to each glyph + // pWidths: the advance widths of the correspoding glyphs (in PS font units) + // nGlyphs: the number of glyphs + // rInfo: additional outgoing information + // implementation note: encoding 0 with glyph id 0 should be added implicitly + // as "undefined character" + virtual BOOL CreateFontSubset( const rtl::OUString& rToFile, + const ImplFontData* pFont, + long* pGlyphIDs, + sal_uInt8* pEncoding, + sal_Int32* pWidths, + int nGlyphs, + FontSubsetInfo& rInfo // out parameter + ); + + // GetFontEncodingVector: a method to get the encoding map Unicode + // to font encoded character; this is only used for type1 fonts and + // may return NULL in case of unknown encoding vector + // if ppNonEncoded is set and non encoded characters (that is type1 + // glyphs with only a name) exist it is set to the corresponding + // map for non encoded glyphs; the encoding vector contains -1 + // as encoding for these cases + virtual const Ucs2SIntMap* GetFontEncodingVector( const ImplFontData*, const Ucs2OStrMap** ppNonEncoded ); + + // GetEmbedFontData: gets the font data for a font marked + // embeddable by GetDevFontList or NULL in case of error + // parameters: pFont: describes the font in question + // pWidths: the widths of all glyphs from char code 0 to 255 + // pWidths MUST support at least 256 members; + // rInfo: additional outgoing information + // pDataLen: out parameter, contains the byte length of the returned buffer + virtual const void* GetEmbedFontData( const ImplFontData*, + const sal_Ucs* pUnicodes, + sal_Int32* pWidths, + FontSubsetInfo& rInfo, + long* pDataLen ); + // frees the font data again + virtual void FreeEmbedFontData( const void* pData, long nDataLen ); + + virtual void GetGlyphWidths( const ImplFontData* pFont, + bool bVertical, + Int32Vector& rWidths, + Ucs2UIntMap& rUnicodeEnc ); + + virtual BOOL GetGlyphBoundRect( long nIndex, Rectangle& ); + virtual BOOL GetGlyphOutline( long nIndex, ::basegfx::B2DPolyPolygon& ); + + virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ); + virtual void DrawServerFontLayout( const ServerFontLayout& ); + virtual bool supportsOperation( OutDevSupportType ) const; + + // Query the platform layer for control support + virtual BOOL IsNativeControlSupported( ControlType nType, ControlPart nPart ); + + virtual SystemGraphicsData GetGraphicsData() const; + virtual SystemFontData GetSysFontData( int nFallbacklevel ) const; +}; + +// Init/Deinit Graphics +void ImplSalInitGraphics( Os2SalGraphics* mpData ); +void ImplSalDeInitGraphics( Os2SalGraphics* mpData ); + +// ----------- +// - Defines - +// ----------- + +#define RGBCOLOR(r,g,b) ((ULONG)(((BYTE)(b)|((USHORT)(g)<<8))|(((ULONG)(BYTE)(r))<<16))) +#define TY( y ) (mnHeight-(y)-1) + +// offset for lcid field, used for fallback font selection +#define LCID_BASE 100 + +// ----------- +// - Inlines - +// ----------- + +// #102411# Win's GCP mishandles kerning => we need to do it ourselves +// SalGraphicsData::mpFontKernPairs is sorted by +inline bool ImplCmpKernData( const KERNINGPAIRS& a, const KERNINGPAIRS& b ) +{ + if( a.sFirstChar < b.sFirstChar ) + return true; + if( a.sFirstChar > b.sFirstChar ) + return false; + return (a.sSecondChar < b.sSecondChar); +} + +// called extremely often from just one spot => inline +inline bool ImplOs2FontData::HasChar( sal_uInt32 cChar ) const +{ + if( mpUnicodeMap->HasChar( cChar ) ) + return true; + // second chance to allow symbol aliasing + if( mbAliasSymbolsLow && ((cChar-0xF000) <= 0xFF) ) + cChar -= 0xF000; + else if( mbAliasSymbolsHigh && (cChar <= 0xFF) ) + cChar += 0xF000; + return mpUnicodeMap->HasChar( cChar ); +} + +#endif // _SV_SALGDI_H diff --git a/vcl/os2/inc/salids.hrc b/vcl/os2/inc/salids.hrc new file mode 100644 index 000000000000..3f7c343231d4 --- /dev/null +++ b/vcl/os2/inc/salids.hrc @@ -0,0 +1,112 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salids.hrc,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALIDS_HRC +#define _SV_SALIDS_HRC + +// Pointer +#define SAL_RESID_POINTER_NULL 10000 +#define SAL_RESID_POINTER_HELP 10001 +#define SAL_RESID_POINTER_CROSS 10002 +#define SAL_RESID_POINTER_MOVE 10003 +#define SAL_RESID_POINTER_HSPLIT 10004 +#define SAL_RESID_POINTER_VSPLIT 10005 +#define SAL_RESID_POINTER_HSIZEBAR 10006 +#define SAL_RESID_POINTER_VSIZEBAR 10007 +#define SAL_RESID_POINTER_HAND 10008 +#define SAL_RESID_POINTER_REFHAND 10009 +#define SAL_RESID_POINTER_PEN 10010 +#define SAL_RESID_POINTER_MAGNIFY 10011 +#define SAL_RESID_POINTER_FILL 10012 +#define SAL_RESID_POINTER_ROTATE 10013 +#define SAL_RESID_POINTER_HSHEAR 10014 +#define SAL_RESID_POINTER_VSHEAR 10015 +#define SAL_RESID_POINTER_MIRROR 10016 +#define SAL_RESID_POINTER_CROOK 10017 +#define SAL_RESID_POINTER_CROP 10018 +#define SAL_RESID_POINTER_MOVEPOINT 10019 +#define SAL_RESID_POINTER_MOVEBEZIERWEIGHT 10020 +#define SAL_RESID_POINTER_MOVEDATA 10021 +#define SAL_RESID_POINTER_COPYDATA 10022 +#define SAL_RESID_POINTER_LINKDATA 10023 +#define SAL_RESID_POINTER_MOVEDATALINK 10024 +#define SAL_RESID_POINTER_COPYDATALINK 10025 +#define SAL_RESID_POINTER_MOVEFILE 10026 +#define SAL_RESID_POINTER_COPYFILE 10027 +#define SAL_RESID_POINTER_LINKFILE 10028 +#define SAL_RESID_POINTER_MOVEFILELINK 10029 +#define SAL_RESID_POINTER_COPYFILELINK 10030 +#define SAL_RESID_POINTER_MOVEFILES 10031 +#define SAL_RESID_POINTER_COPYFILES 10032 +#define SAL_RESID_POINTER_DRAW_LINE 10033 +#define SAL_RESID_POINTER_DRAW_RECT 10034 +#define SAL_RESID_POINTER_DRAW_POLYGON 10035 +#define SAL_RESID_POINTER_DRAW_BEZIER 10036 +#define SAL_RESID_POINTER_DRAW_ARC 10037 +#define SAL_RESID_POINTER_DRAW_PIE 10038 +#define SAL_RESID_POINTER_DRAW_CIRCLECUT 10039 +#define SAL_RESID_POINTER_DRAW_ELLIPSE 10040 +#define SAL_RESID_POINTER_DRAW_FREEHAND 10041 +#define SAL_RESID_POINTER_DRAW_CONNECT 10042 +#define SAL_RESID_POINTER_DRAW_TEXT 10043 +#define SAL_RESID_POINTER_DRAW_CAPTION 10044 +#define SAL_RESID_POINTER_CHART 10045 +#define SAL_RESID_POINTER_DETECTIVE 10046 +#define SAL_RESID_POINTER_PIVOT_COL 10047 +#define SAL_RESID_POINTER_PIVOT_ROW 10048 +#define SAL_RESID_POINTER_PIVOT_FIELD 10049 +#define SAL_RESID_POINTER_CHAIN 10050 +#define SAL_RESID_POINTER_CHAIN_NOTALLOWED 10051 +#define SAL_RESID_POINTER_TIMEEVENT_MOVE 10052 +#define SAL_RESID_POINTER_TIMEEVENT_SIZE 10053 +#define SAL_RESID_POINTER_AUTOSCROLL_N 10054 +#define SAL_RESID_POINTER_AUTOSCROLL_S 10055 +#define SAL_RESID_POINTER_AUTOSCROLL_W 10056 +#define SAL_RESID_POINTER_AUTOSCROLL_E 10057 +#define SAL_RESID_POINTER_AUTOSCROLL_NW 10058 +#define SAL_RESID_POINTER_AUTOSCROLL_NE 10059 +#define SAL_RESID_POINTER_AUTOSCROLL_SW 10060 +#define SAL_RESID_POINTER_AUTOSCROLL_SE 10061 +#define SAL_RESID_POINTER_AUTOSCROLL_NS 10062 +#define SAL_RESID_POINTER_AUTOSCROLL_WE 10063 +#define SAL_RESID_POINTER_AUTOSCROLL_NSWE 10064 +#define SAL_RESID_POINTER_AIRBRUSH 10070 +#define SAL_RESID_POINTER_TEXT_VERTICAL 10071 +#define SAL_RESID_POINTER_PIVOT_DELETE 10072 +#define SAL_RESID_POINTER_TAB_SELECT_S 10073 +#define SAL_RESID_POINTER_TAB_SELECT_E 10074 +#define SAL_RESID_POINTER_TAB_SELECT_SE 10075 +#define SAL_RESID_POINTER_TAB_SELECT_W 10076 +#define SAL_RESID_POINTER_TAB_SELECT_SW 10077 +#define SAL_RESID_POINTER_PAINTBRUSH 10078 + +#define SAL_RESID_ICON_DEFAULT 1 + +#endif // _SV_SALIDS_HRC diff --git a/vcl/os2/inc/salinst.h b/vcl/os2/inc/salinst.h new file mode 100644 index 000000000000..ba8dc7ddc43f --- /dev/null +++ b/vcl/os2/inc/salinst.h @@ -0,0 +1,106 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salinst.h,v $ + * $Revision: 1.7.74.1 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALINST_H +#define _SV_SALINST_H + +#include <vcl/sv.h> +#include <vcl/salinst.hxx> + +namespace vos { class OMutex; } + +// ------------------- +// - SalInstanceData - +// ------------------- + +class SalYieldMutex; + +#define SAL_COMMANDLINENOINIT ((USHORT)0xFFFF) +#define SAL_MAXPARAM 40 + +class Os2SalInstance : public SalInstance +{ +public: + HAB mhAB; // anchor block handle + HMQ mhMQ; // handle of os2 message queue + HPOINTER mhAppIcon; // app icon + int mnArgc; // commandline param count + char** mpArgv; // commandline + HWND mhComWnd; // window, for communication (between threads and the main thread) + SalYieldMutex* mpSalYieldMutex; // Sal-Yield-Mutex + vos::OMutex* mpSalWaitMutex; // Sal-Wait-Mutex + USHORT mnYieldWaitCount; // Wait-Count + +public: + Os2SalInstance(); + virtual ~Os2SalInstance(); + + virtual SalFrame* CreateChildFrame( SystemParentData* pParent, ULONG nStyle ); + virtual SalFrame* CreateFrame( SalFrame* pParent, ULONG nStyle ); + virtual void DestroyFrame( SalFrame* pFrame ); + virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, BOOL bShow = TRUE ); + virtual void DestroyObject( SalObject* pObject ); + virtual SalVirtualDevice* CreateVirtualDevice( SalGraphics* pGraphics, + long nDX, long nDY, + USHORT nBitCount, const SystemGraphicsData *pData ); + virtual void DestroyVirtualDevice( SalVirtualDevice* pDevice ); + + virtual SalInfoPrinter* CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, + ImplJobSetup* pSetupData ); + virtual void DestroyInfoPrinter( SalInfoPrinter* pPrinter ); + virtual SalPrinter* CreatePrinter( SalInfoPrinter* pInfoPrinter ); + virtual void DestroyPrinter( SalPrinter* pPrinter ); + virtual void GetPrinterQueueInfo( ImplPrnQueueList* pList ); + virtual void GetPrinterQueueState( SalPrinterQueueInfo* pInfo ); + virtual void DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ); + virtual String GetDefaultPrinter(); + virtual SalTimer* CreateSalTimer(); + virtual SalI18NImeStatus* CreateI18NImeStatus(); + virtual SalSystem* CreateSalSystem(); + virtual SalBitmap* CreateSalBitmap(); + virtual vos::IMutex* GetYieldMutex(); + virtual ULONG ReleaseYieldMutex(); + virtual void AcquireYieldMutex( ULONG nCount ); + virtual void Yield( bool, bool ); + virtual bool AnyInput( USHORT nType ); + virtual SalMenu* CreateMenu( BOOL bMenuBar ); + virtual void DestroyMenu( SalMenu* ); + virtual SalMenuItem* CreateMenuItem( const SalItemParams* pItemData ); + virtual void DestroyMenuItem( SalMenuItem* ); + virtual SalSession* CreateSalSession(); + virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ); + virtual void AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& rMimeType); +}; + +SalFrame* ImplSalCreateFrame( Os2SalInstance* pInst, HWND hWndParent, ULONG nSalFrameStyle ); +SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent ); +void ImplSalStartTimer( ULONG nMS, BOOL bMutex = FALSE ); + +#endif // _SV_SALINST_H diff --git a/vcl/os2/inc/sallang.hxx b/vcl/os2/inc/sallang.hxx new file mode 100644 index 000000000000..b93989190c0e --- /dev/null +++ b/vcl/os2/inc/sallang.hxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sallang.hxx,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SALLANG_HXX +#define _SALLANG_HXX + +//#ifndef _TOOLS_LANG_HXX +//#include <tools/lang.hxx> +//#endif +#include <i18npool/mslangid.hxx> + +// -------------------- +// - Language Strings - +// -------------------- + +// --- Key-Namen --- +#define LSTR_KEY_SHIFT 0 +#define LSTR_KEY_CTRL 1 +#define LSTR_KEY_ALT 2 +#define LSTR_KEY_UP 3 +#define LSTR_KEY_DOWN 4 +#define LSTR_KEY_LEFT 5 +#define LSTR_KEY_RIGHT 6 +#define LSTR_KEY_HOME 7 +#define LSTR_KEY_END 8 +#define LSTR_KEY_PAGEUP 9 +#define LSTR_KEY_PAGEDOWN 10 +#define LSTR_KEY_RETURN 11 +#define LSTR_KEY_ESC 12 +#define LSTR_KEY_TAB 13 +#define LSTR_KEY_BACKSPACE 14 +#define LSTR_KEY_SPACE 15 +#define LSTR_KEY_INSERT 16 +#define LSTR_KEY_DELETE 17 + +// --- Anzahl der Texte --- + +#define LSTR_COUNT 18 + +// -------------------------------------------- +// - Methoden zum Abfragen der Sprach-Strings - +// -------------------------------------------- + +const sal_Unicode** ImplGetLangTab( LanguageType eLang ); + +#endif // _SALLANG_HXX diff --git a/vcl/os2/inc/sallayout.h b/vcl/os2/inc/sallayout.h new file mode 100644 index 000000000000..43d516f2b30b --- /dev/null +++ b/vcl/os2/inc/sallayout.h @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sallayout.h,v $ + * $Revision: 1.4 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALLAYOUT_H +#define _SV_SALLAYOUT_H + +#if 0 +#include <sv.h> +#include <sallayout.hxx> + +class ImplOs2FontEntry; + +class Os2SalLayout : public GenericSalLayout +{ +public: + Os2SalLayout( HPS); + virtual bool LayoutText( ImplLayoutArgs& ); + virtual void AdjustLayout( ImplLayoutArgs& ); + virtual void DrawText( SalGraphics& ) const; + +protected: + HPS mhPS; + FONTMETRICS FontMetrics; + int mnBaseAdv; + +private: + int mnGlyphCount; + int mnCharCount; + sal_Unicode* mpOutGlyphs; + int* mpGlyphAdvances; // if possible this is shared with mpGlyphAdvances[] + int* mpGlyphOrigAdvs; + int* mpCharWidths; // map rel char pos to char width + int* mpChars2Glyphs; // map rel char pos to abs glyph pos + int* mpGlyphs2Chars; // map abs glyph pos to abs char pos + bool* mpGlyphRTLFlags; // BiDi status for glyphs: true=>RTL + mutable long mnWidth; + bool mbDisableGlyphs; + + int mnNotdefWidth; + BYTE mnCharSet; + +}; +#endif + +#endif // _SV_SALLAYOUT_H diff --git a/vcl/os2/inc/salmenu.h b/vcl/os2/inc/salmenu.h new file mode 100644 index 000000000000..cdb731ebd034 --- /dev/null +++ b/vcl/os2/inc/salmenu.h @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salmenu.h,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALMENU_H +#define _SV_SALMENU_H + +#include <vcl/sv.h> +#include <vcl/bitmap.hxx> +#include <vcl/salmenu.hxx> + + +class Os2SalMenu : public SalMenu +{ +public: + Os2SalMenu() {} + virtual ~Os2SalMenu(); + + virtual BOOL VisibleMenuBar(); // must return TRUE to actually DISPLAY native menu bars + // otherwise only menu messages are processed (eg, OLE on Windows) + + virtual void InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ); + virtual void RemoveItem( unsigned nPos ); + virtual void SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos ); + virtual void SetFrame( const SalFrame* pFrame ); + virtual void CheckItem( unsigned nPos, BOOL bCheck ); + virtual void EnableItem( unsigned nPos, BOOL bEnable ); + virtual void SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const XubString& rText ); + virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage); + virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const XubString& rKeyName ); + virtual void GetSystemMenuData( SystemMenuData* pData ); +}; + +class Os2SalMenuItem : public SalMenuItem +{ +public: + Os2SalMenuItem() {} + virtual ~Os2SalMenuItem(); +}; + +#endif // _SV_SALMENU_H + diff --git a/vcl/os2/inc/salobj.h b/vcl/os2/inc/salobj.h new file mode 100644 index 000000000000..aa566808a41f --- /dev/null +++ b/vcl/os2/inc/salobj.h @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salobj.h,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALOBJ_H +#define _SV_SALOBJ_H + +#include <vcl/sv.h> +#include <vcl/salobj.hxx> + +// ----------------- +// - SalObjectData - +// ----------------- + +class Os2SalObject : public SalObject +{ +public: + HWND mhWnd; // Window handle + HWND mhWndChild; // Child Window handle + HWND mhLastFocusWnd; // Child-Window, welches als letztes den Focus hatte + SystemChildData maSysData; // SystemEnvData + HWND mhLastClipWnd; // LastClip-Window + HWND mhOldLastClipWnd; // LastClip-Window befor BeginSetClipRegion + long mnHeight; // Fenster-Hoehe fuer Positionsumrechnung + Os2SalObject* mpNextObject; // pointer to next object + void* mpInst; // instance handle for callback + SALOBJECTPROC mpProc; // callback proc + + Os2SalObject(); + virtual ~Os2SalObject(); + + virtual void ResetClipRegion(); + virtual USHORT GetClipRegionType(); + virtual void BeginSetClipRegion( ULONG nRects ); + virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ); + virtual void EndSetClipRegion(); + virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight ); + virtual void Show( BOOL bVisible ); + virtual void Enable( BOOL nEnable ); + virtual void GrabFocus(); + virtual void SetBackground(); + virtual void SetBackground( SalColor nSalColor ); + virtual const SystemEnvData* GetSystemData() const; +}; + +#endif // _SV_SALOBJ_H diff --git a/vcl/os2/inc/salprn.h b/vcl/os2/inc/salprn.h new file mode 100644 index 000000000000..2c95965bc609 --- /dev/null +++ b/vcl/os2/inc/salprn.h @@ -0,0 +1,149 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salprn.h,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALPRN_H +#define _SV_SALPRN_H + +#include <vcl/sv.h> +#include <vcl/salprn.hxx> + +class SalGraphics; +class SalInfoPrinter; + +struct ImplFormInfo; +typedef ImplFormInfo* PIMPLFORMINFO; +struct ImplTrayInfo; +typedef ImplTrayInfo* PIMPLTRAYINFO; + +// ---------------------- +// - SalInfoPrinterData - +// ---------------------- + +//class SalInfoPrinterData +class Os2SalInfoPrinter : public SalInfoPrinter +{ +public: + Os2SalGraphics* mpGraphics; // Graphics + HDC mhDC; // printer hdc + HPS mhPS; // printer hps + ByteString maPrinterName; // pszPrinters + ByteString maName; // pszName bzw. LogAdress + ByteString maDriverName; // pszDriverName nach . + ByteString maDeviceName; // pszDriverName bis . + ByteString maJobSetupDeviceName; // DeviceName aus pDriverData + PIMPLFORMINFO* mpFormArray; // PaperForm-Names + USHORT mnFormCount; // PaperForm-Count + PIMPLTRAYINFO* mpTrayArray; // PaperTray-Names + USHORT mnTrayCount; // PaperTray-Count + BOOL mbDJPSupported; // is driver DJP enabled + BOOL mbGraphics; // is Graphics used + +public: + Os2SalInfoPrinter(); + virtual ~Os2SalInfoPrinter(); + + virtual SalGraphics* GetGraphics(); + virtual void ReleaseGraphics( SalGraphics* pGraphics ); + virtual BOOL Setup( SalFrame* pFrame, ImplJobSetup* pSetupData ); + virtual BOOL SetPrinterData( ImplJobSetup* pSetupData ); + virtual BOOL SetData( ULONG nFlags, ImplJobSetup* pSetupData ); + virtual void GetPageInfo( const ImplJobSetup* pSetupData, + long& rOutWidth, long& rOutHeight, + long& rPageOffX, long& rPageOffY, + long& rPageWidth, long& rPageHeight ); + virtual ULONG GetCapabilities( const ImplJobSetup* pSetupData, USHORT nType ); + virtual ULONG GetPaperBinCount( const ImplJobSetup* pSetupData ); + virtual String GetPaperBinName( const ImplJobSetup* pSetupData, ULONG nPaperBin ); + virtual void InitPaperFormats( const ImplJobSetup* pSetupData ); + virtual int GetLandscapeAngle( const ImplJobSetup* pSetupData ); +}; + +// ------------------ +// - SalPrinterData - +// ------------------ + +class SalPrinterData00 +{ +public: + Os2SalGraphics* mpGraphics; // current Printer graphics + SalInfoPrinter* mpInfoPrinter; // pointer to the compatible InfoPrinter + HDC mhDC; // printer hdc + HPS mhPS; // printer hps + ULONG mnError; // Error Code + BOOL mbFirstPage; // IsFirstPage + BOOL mbAbort; // JobAborted + BOOL mbPrintDJPSupported; // is driver PrintDJP enabled (DEVESC_NEWFRAME_WPROP) + char maCommentBuf[33]; // Comment + char maCopyBuf[10]; // Kopien +}; + +// ----------------- +// - Os2SalPrinter - +// ----------------- + +class Os2SalPrinter : public SalPrinter +{ +public: + Os2SalGraphics* mpGraphics; // current Printer graphics + Os2SalInfoPrinter* mpInfoPrinter; // pointer to the compatible InfoPrinter + Os2SalPrinter* mpNextPrinter; // next printing printer + HDC mhDC; // printer hdc + HPS mhPS; // printer hps + ULONG mnError; // Error Code + BOOL mbFirstPage; // IsFirstPage + BOOL mbAbort; // JobAborted + BOOL mbPrintDJPSupported; // is driver PrintDJP enabled (DEVESC_NEWFRAME_WPROP) + char maCommentBuf[33]; // Comment + char maCopyBuf[16]; // Kopien + //HDC mhDC; // printer hdc + //ULONG mnError; // Error Code + //ULONG mnCopies; // Kopien + //BOOL mbCollate; // Sortierte Kopien + //BOOL mbAbort; // Job Aborted + +public: + Os2SalPrinter(); + virtual ~Os2SalPrinter(); + + virtual BOOL StartJob( const XubString* pFileName, + const XubString& rJobName, + const XubString& rAppName, + ULONG nCopies, + bool bCollate, + bool bDirect, + ImplJobSetup* pSetupData ); + virtual BOOL EndJob(); + virtual BOOL AbortJob(); + virtual SalGraphics* StartPage( ImplJobSetup* pSetupData, BOOL bNewJobData ); + virtual BOOL EndPage(); + virtual ULONG GetErrorCode(); +}; + +#endif // _SV_SALPRN_H diff --git a/vcl/os2/inc/salsound.h b/vcl/os2/inc/salsound.h new file mode 100644 index 000000000000..7ee3ac1e8d35 --- /dev/null +++ b/vcl/os2/inc/salsound.h @@ -0,0 +1,97 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salsound.h,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALSOUND_H +#define _SV_SALSOUND_H + +#include <tools/gen.hxx> +#include <sv.h> +#include <tools/string.hxx> +#include <vcl/salframe.hxx> +#ifndef _SV_SALSTYPE_HXX +#include <vcl/salstype.hxx> +#endif +#include <vcl/salsound.hxx> + +// ------------ +// - SalSound - +// ------------ + +//class SalSound +class Os2SalSound : public SalSound +{ +private: + + static HMODULE mhMCILib; + static ULONG mnSoundState; + static void* mpMCIFnc; + SALSOUNDPROC mpProc; + void* mpInst; + ULONG mnStartTime; + ULONG mnPlayLen; + HWND mhSoundWnd; + USHORT mnDeviceId; + BOOL mbLoop; + BOOL mbPaused; + +public: + + void ImplSetError( ULONG nMciErr ); + void ImplNotify( SoundNotification eNotification, ULONG nError ); + +public: + + BOOL Create(); + //static BOOL IsValid() { return( SOUND_STATE_VALID == Os2SalSound::mnSoundState ); } + //BOOL Init( SalFrame* pFrame, const String& rSoundName, ULONG& rSoundLen ); + //BOOL Init( SalFrame* pFrame, const BYTE* pSound, ULONG nDataLen, ULONG& rSoundLen ); + + void SetNotifyProc( void* pInst, SALSOUNDPROC pProc ) + { mpInst = pInst; mpProc = pProc; } +public: + Os2SalSound(); + virtual ~Os2SalSound(); + + virtual bool IsValid(); + virtual bool Init( const String& rSoundName, ULONG& rSoundLen ); + virtual void Play( ULONG nStartTime, ULONG nPlayTime, bool bLoop ); + virtual void Stop(); + virtual void Pause(); + virtual void Continue(); + virtual bool IsLoopMode() const; + virtual bool IsPlaying() const; + virtual bool IsPaused() const; + + bool ImplCreate(); + void ImplDestroy(); + static void Release(); +}; + +#endif // _SV_SALSOUND_H diff --git a/vcl/os2/inc/salsound.hxx b/vcl/os2/inc/salsound.hxx new file mode 100644 index 000000000000..49d0d2a88194 --- /dev/null +++ b/vcl/os2/inc/salsound.hxx @@ -0,0 +1,87 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salsound.hxx,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALSOUND_HXX +#define _SV_SALSOUND_HXX + +#include <tools/gen.hxx> +#include <sv.h> +#include <tools/string.hxx> +#include <salframe.hxx> +#ifndef _SV_SALSTYPE_HXX +#include <salstype.hxx> +#endif +#include <salsound.hxx> + +// ------------ +// - SalSound - +// ------------ + +class SalSound +{ +private: + + static HMODULE mhMCILib; + static ULONG mnSoundState; + static void* mpMCIFnc; + SALSOUNDPROC mpProc; + void* mpInst; + ULONG mnStartTime; + ULONG mnPlayLen; + HWND mhSoundWnd; + USHORT mnDeviceId; + BOOL mbLoop; + BOOL mbPaused; + +public: + + void ImplSetError( ULONG nMciErr ); + void ImplNotify( SoundNotification eNotification, ULONG nError ); + +public: + + SalSound(); + ~SalSound(); + + BOOL Create(); + static void Release(); + static BOOL IsValid() { return( SOUND_STATE_VALID == SalSound::mnSoundState ); } + + BOOL Init( SalFrame* pFrame, const String& rSoundName, ULONG& rSoundLen ); + BOOL Init( SalFrame* pFrame, const BYTE* pSound, ULONG nDataLen, ULONG& rSoundLen ); + void Play( ULONG nStartTime, ULONG nPlayTime, BOOL bLoop ); + void Stop(); + void Pause(); + + void SetNotifyProc( void* pInst, SALSOUNDPROC pProc ) + { mpInst = pInst; mpProc = pProc; } +}; + +#endif // _SV_SALSOUND_HXX diff --git a/vcl/os2/inc/salsys.h b/vcl/os2/inc/salsys.h new file mode 100644 index 000000000000..6424aeccaa3c --- /dev/null +++ b/vcl/os2/inc/salsys.h @@ -0,0 +1,47 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salsys.h,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALSYS_H +#define _SV_SALSYS_H + +#include <vcl/salsys.hxx> +#include <vcl/sv.h> + +class SalFrame; + +// ----------------- +// - SalSystemData - +// ----------------- + +class SalSystemData +{ +}; + +#endif // _SV_SALSYS_H diff --git a/vcl/os2/inc/saltimer.h b/vcl/os2/inc/saltimer.h new file mode 100644 index 000000000000..9b411a34fd06 --- /dev/null +++ b/vcl/os2/inc/saltimer.h @@ -0,0 +1,47 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: saltimer.h,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALTIMER_H +#define _SV_SALTIMER_H + +#include <vcl/saltimer.hxx> + +class Os2SalTimer : public SalTimer +{ +public: + Os2SalTimer() {} + virtual ~Os2SalTimer(); + + // overload all pure virtual methods + void Start( ULONG nMS ); + void Stop(); +}; + +#endif diff --git a/vcl/os2/inc/salvd.h b/vcl/os2/inc/salvd.h new file mode 100644 index 000000000000..26dc631e1529 --- /dev/null +++ b/vcl/os2/inc/salvd.h @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salvd.h,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALVD_H +#define _SV_SALVD_H + +#include <vcl/sv.h> +#include <vcl/salvd.hxx> + +class Os2SalGraphics; + +// ----------------- +// - SalVirDevData - +// ----------------- + +//class SalVirDevData +class Os2SalVirtualDevice : public SalVirtualDevice +{ +public: + HPS mhPS; // HPS + HDC mhDC; // HDC + HBITMAP mhBmp; // Memory Bitmap + HBITMAP mhDefBmp; // Default Bitmap + Os2SalGraphics* mpGraphics; // current VirDev graphics + USHORT mnBitCount; // BitCount (0 or 1) + BOOL mbGraphics; // is Graphics used + + Os2SalVirtualDevice(); + virtual ~Os2SalVirtualDevice(); + + virtual SalGraphics* GetGraphics(); + virtual void ReleaseGraphics( SalGraphics* pGraphics ); + virtual BOOL SetSize( long nNewDX, long nNewDY ); + virtual void GetSize( long& rWidth, long& rHeight ); +}; + +// Help-Functions +HBITMAP ImplCreateVirDevBitmap( HDC hDC, HPS hPS, long nDX, long nDY, + USHORT nBitCount ); + +#endif // _SV_SALVD_H diff --git a/vcl/os2/inc/svsys.h b/vcl/os2/inc/svsys.h new file mode 100644 index 000000000000..a322d6d22cfb --- /dev/null +++ b/vcl/os2/inc/svsys.h @@ -0,0 +1,38 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: svsys.h,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SVSYS_H +#define _SV_SVSYS_H + +#ifndef _SVPM_H +#include <svpm.h> +#endif + +#endif // _SV_SVSYS_H diff --git a/vcl/os2/inc/wingdi.h b/vcl/os2/inc/wingdi.h new file mode 100644 index 000000000000..d6085abbd262 --- /dev/null +++ b/vcl/os2/inc/wingdi.h @@ -0,0 +1,70 @@ +#ifndef _WINGDI_ +#define _WINGDI_ + +typedef struct tagPOINT +{ + LONG x; + LONG y; +} POINT, *PPOINT, *LPPOINT; + + +typedef unsigned long DWORD; +typedef unsigned short WORD; +typedef struct +{ + WORD fract; + SHORT value; +} W32FIXED; + +typedef struct tagPOINTFX +{ + W32FIXED x; + W32FIXED y; +} POINTFX, *LPPOINTFX; + +typedef struct tagTTPOLYCURVE +{ + WORD wType; + WORD cpfx; + POINTFX apfx[1]; +} TTPOLYCURVE, *LPTTPOLYCURVE; + +typedef struct tagTTPOLYGONHEADER +{ + DWORD cb; + DWORD dwType; + POINTFX pfxStart; +} TTPOLYGONHEADER, *LPTTPOLYGONHEADER; + +typedef struct +{ + UINT gmBlackBoxX; + UINT gmBlackBoxY; + POINT gmptGlyphOrigin; + SHORT gmCellIncX; + SHORT gmCellIncY; +} GLYPHMETRICS, *LPGLYPHMETRICS; + +#define GGO_METRICS 0 +#define GGO_BITMAP 1 +#define GGO_NATIVE 2 +#define GGO_BEZIER 3 +#define GGO_GRAY2_BITMAP 4 +#define GGO_GRAY4_BITMAP 5 +#define GGO_GRAY8_BITMAP 6 +#define GGO_GLYPH_INDEX 0x80 + +#define TT_PRIM_LINE 1 +#define TT_PRIM_QSPLINE 2 +#define TT_PRIM_CSPLINE 3 +#define TT_POLYGON_TYPE 24 + +typedef struct +{ + W32FIXED eM11; + W32FIXED eM12; + W32FIXED eM21; + W32FIXED eM22; +} MAT2, *LPMAT2; + +#endif // _WINGDI_ diff --git a/vcl/os2/inc/xwphook.h b/vcl/os2/inc/xwphook.h new file mode 100644 index 000000000000..07e00bd4c4c1 --- /dev/null +++ b/vcl/os2/inc/xwphook.h @@ -0,0 +1,620 @@ + +/* + * xwphook.h: + * header for both xwphook.c and xwpdaemon.c. This is also + * included from a number of sources for XFLDR.DLL which need + * to interface (configure) the daemon. + */ + +/* + * Copyright (C) 1999-2002 Ulrich Mller. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, in version 2 as it comes in the COPYING + * file of the XWorkplace main distribution. + * This program 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 General Public License for more details. + */ + +#ifndef XWPHOOK_HEADER_INCLUDED + #define XWPHOOK_HEADER_INCLUDED + + /* ****************************************************************** + * + * OS2.INI applications and keys + * + ********************************************************************/ + + #define INIAPP_XWPHOOK "XWorkplace:Hook" // added V0.9.0 + #define INIKEY_HOOK_HOTKEYS "Hotkeys" // added V0.9.0 + #define INIKEY_HOOK_CONFIG "Config" // added V0.9.0 + #define INIKEY_HOOK_PAGERCONFIG "PagerConfig" // V0.9.2 (2000-02-25) [umoeller] + // changed V0.9.19 (2002-05-07) [umoeller] + #define INIKEY_HOOK_PAGERWINPOS "PagerWinPos" + // changed V0.9.19 (2002-05-07) [umoeller] + #define INIKEY_HOOK_FUNCTIONKEYS "FuncKeys" // added V0.9.3 (2000-04-19) [umoeller] + #define INIKEY_HOOK_MOUSEMAPPINGS "MouseMappings" // added V0.9.19 (2002-04-20) [lafaix] + + /* ****************************************************************** + * + * Structures + * + ********************************************************************/ + + // do not change the following, or this will break + // binary compatibility of the XPager OS2.INI data + #define MAX_STICKIES 64 + #define STICKYLEN 50 + +#ifndef __NOPAGER__ + + // flags for PAGERCONFIG.aulStickyFlags + #define SF_CONTAINS 0x00000000L // default + #define SF_BEGINSWITH 0x00000001L + #define SF_ENDSWITH 0x00000002L + #define SF_EQUALS 0x00000004L + #define SF_MATCHES 0x00000008L // V0.9.19 (2002-04-17) [umoeller] + #define SF_OPERATOR_MASK 0x0000FFFFL + + #define SF_INCLUDE 0x00000000L // default + #define SF_EXCLUDE 0x00010000L + #define SF_CRITERIA_MASK 0x00010000L + + #define SF_TITLE 0x00000000L // default + #define SF_ATTRIBUTE_MASK 0xFFFE0000L + + #pragma pack(1) + + /* + *@@ PAGERCONFIG: + * XPager configuration data. + * This is stored within the HOOKDATA structure + * (statically in the hook DLL) so that both + * the daemon and the hook have access to this. + * + *@@added V0.9.2 (2000-02-25) [umoeller] + */ + + typedef struct _PAGERCONFIG + { + BYTE cDesktopsX, + cDesktopsY, + // no. of virtual Desktops (x and y) + bStartX, + bStartY; + // initial desktop at startup + + ULONG flPager; + // flags for "XPager" settings page 1 + #define PGRFL_WRAPAROUND 0x0001 + #define PGRFL_HOTKEYS 0x0002 + #define PGRFL_NOFOLLOWFOCUS 0x0004 + + #define PGRMASK_PAGE1 (PGRFL_WRAPAROUND | PGRFL_HOTKEYS) + #define PGRFL_PAGE1_DEFAULTS 0 + + // flags for "XPager" settings page 2 + #define PGRFL_PRESERVEPROPS 0x0010 + // preserve proportions of XPager win when resizing? + #define PGRFL_STAYONTOP 0x0020 + // stay on top? + #define PGRFL_FLASHTOTOP 0x0040 + #define PGRFL_MINIWINDOWS 0x0080 + // show mini windows in XPager? + #define PGRFL_MINIWIN_TITLES 0x0100 + // show mini window titles? + #define PGRFL_MINIWIN_MOUSE 0x0200 + // allow activate/lower by mouse clicks? + #define PGRFL_INCLUDESECONDARY 0x0400 + #define PGRFL_INCLUDESTICKY 0x0800 + #define PGRFL_MINIWIN_ICONS 0x1000 + // show mini window icons? + // V0.9.19 (2002-06-13) [umoeller] + + #define PGRMASK_PAGE2 ( PGRFL_PRESERVEPROPS \ + | PGRFL_STAYONTOP \ + | PGRFL_FLASHTOTOP \ + | PGRFL_MINIWINDOWS \ + | PGRFL_MINIWIN_TITLES \ + | PGRFL_MINIWIN_MOUSE \ + | PGRFL_INCLUDESECONDARY \ + | PGRFL_INCLUDESTICKY \ + | PGRFL_MINIWIN_ICONS ) + #define PGRFL_PAGE2_DEFAULTS ( PGRFL_PRESERVEPROPS \ + | PGRFL_MINIWINDOWS \ + | PGRFL_MINIWIN_TITLES \ + | PGRFL_MINIWIN_MOUSE) + + // flags for "XPager" settings page 3 + #define PGRFL_ADDSTICKYTOGGLE 0x2000 + // add "sticky" option to system menu? + // V1.0.0 (2002-09-14) [lafaix] + + #define PGRMASK_PAGE3 ( PGRFL_ADDSTICKYTOGGLE ) + #define PGRFL_PAGE3_DEFAULTS 0 + #define PGRFL_WINDOWS_KEYS 0x00010000 + // V1.0.3 (2004-10-14) [bird]: Use windows keys for left / right + + ULONG ulFlashDelay; + // "flash" delay in milliseconds, if PGRFL_FLASHTOTOP + ULONG flKeyShift; // KC_* values + + // paint settings + ULONG flPaintMode; // as in BKGNDINFO (gpih.h) + LONG lcolDesktop1, // as in BKGNDINFO (gpih.h) + lcolDesktop2; // as in BKGNDINFO (gpih.h) + + LONG lcolActiveDesktop; // color of hatching for active desktop + + LONG lcolGrid; // grid color (separators between desktops) + + LONG lcolInactiveWindow, + lcolActiveWindow, + lcolWindowFrame, + lcolInactiveText, + lcolActiveText; + + // sticky windows + ULONG cStickies; + ULONG aulStickyFlags[MAX_STICKIES]; // SF_* flags per sticky + CHAR aszStickies[MAX_STICKIES][STICKYLEN]; + + } PAGERCONFIG, *PPAGERCONFIG; + + #pragma pack() + +#endif + + // flags for HOOKCONFIG.usScrollMode + #define SM_LINEWISE 0 + #define SM_AMPLIFIED 1 + + // flags for HOOKCONFIG.ulAutoHideFlags + #define AHF_IGNOREMENUS 0x00000001L + #define AHF_IGNOREBUTTONS 0x00000002L + + // flags for HOOKCONFIG.ulAutoMoveFlags + #define AMF_ALWAYSMOVE 0x00000001L + #define AMF_IGNORENOBUTTON 0x00000002L + #define AMF_ANIMATE 0x00000004L + + /* + *@@ HOOKCONFIG: + * configuration data for the hook and the daemon. + * + * This is stored within the HOOKDATA structure + * (statically in the hook DLL) so that both + * the daemon and the hook have access to this. + * + * A mirror of this structure is put into OS2.INI + * which gets loaded by the XWorkplace settings + * objects in XFLDR.DLL to configure the hook. + * This gets (re)loaded by the daemon when XFLDR.DLL + * posts XDM_HOOKCONFIG to fnwpDaemonObject. + * + * So this is seen by the hook and the daemon; + * XFLDR.DLL only writes this back to OS2.INI and + * notifies the daemon to reload this. + * + * For every item, the safe default value is null + * so the structure can be zeroed to disable + * everything. + * + * If settings are added to this structure, they + * must be added to the bottom in order not to + * break binary compatibility between XWP versions. + * + * Note that the object hotkey _definitions_ are + * not part of this structure. Those are set using + * XDM_HOTKEYSCHANGED instead. However, object + * hotkeys are globally enabled in here (fGlobalHotkeys). + */ +#pragma pack(4) + typedef struct _HOOKCONFIG + { + // Sliding focus: + + PM_BOOL __fSlidingFocus; + // enabled? + ULONG __ulSlidingFocusDelay; + // delay in ms; 0 = off + + PM_BOOL __fSlidingBring2Top; + // bring windows to top or preserve Z-order + PM_BOOL __fSlidingIgnoreDesktop; + // ignore Desktop windows + PM_BOOL __fSlidingIgnoreSeamless; + // TRUE: ignore seamless Win-OS/2 windows + // FALSE: always bring them to top + + // Screen corner objects: + HOBJECT ahobjDummy[4]; // was four screen corner objects; + // we extended the array to 8 items + // so the array had to be moved to the + // bottom in order not to break binary + // compatibility + + BYTE bMonitorDrives[30]; // array of 1-byte BOOLs; if any of these + // is "1", the corresponding drive letter + // will be monitored for media change + // (index 1 = A, index 2 = B, index 3 = C, ...). + // Index 0 is unused to match logical drive numbers. + + // More mouse mappings: V0.9.1 (99-12-03) + + PM_BOOL fChordWinList; // deprecated V0.9.19 (2002-04-20) [lafaix] + // show window list on mb1+2 chord + PM_BOOL fSysMenuMB2TitleBar; // deprecated V0.9.19 (2002-04-20) [lafaix] + // show system menu on mb2 title-bar click + + // Mouse-button-3 scrolling: V0.9.1 (99-12-03) + + PM_BOOL fMB3Scroll; // deprecated V0.9.19 (2002-04-20) [lafaix] + // scroll window contents on MB3Drag + PM_BOOL fMB3ScrollReverse; // deprecated V0.9.19 (2002-04-20) [lafaix] + // reverse scrolling + USHORT usScrollMode; // deprecated V0.9.19 (2002-04-20) [lafaix] + // one of the following: + // -- SM_LINEWISE (0): scroll fixed, line-wise + // -- SM_AMPLIFIED (1): scroll amplified, relative to window size + USHORT usMB3ScrollMin; + // minimum pixels that mouse must be moved; + // 0 means 1, 1 means 2, ... + SHORT sAmplification; + // amplification (-9 thru +10) + // the amplification in percent is calculated like this: + // percent = 100 + (sAmplification * 10) + // so we get: + // 0 --> 100% + // 2 --> 120% + // 10 --> 200% + // -2 --> 80% + // -9 --> 10% + + // Auto-hide mouse pointer: V0.9.1 (99-12-03) + PM_BOOL __fAutoHideMouse; + ULONG __ulAutoHideDelay; + // delay in seconds; 0 means 1 second, 2 means 3, ... + + // Global object hotkeys enabled: + // this can be disabled even if any hotkeys are defined + // because the hotkeys themselves are stored separately + // in shared memory + PM_BOOL __fGlobalHotkeys; + + // XPager configuration + PM_BOOL fRemoved1, // _fXPagerStayOnTop, + fRemoved2; //__fSlidingIgnoreXPager; + // removed V0.9.19 (2002-05-07) [umoeller] + + // Sliding menus + PM_BOOL fSlidingMenus; + // enabled? + ULONG ulSubmenuDelay; + // delay in ms; 0 = off + PM_BOOL fMenuImmediateHilite; + + // Mouse-button-3 single-clicks to MB1 double-clicks + // V0.9.4 (2000-06-12) [umoeller] + PM_BOOL fMB3Click2MB1DblClk; // deprecated V0.9.19 (2002-04-20) [lafaix] + + // Screen corner objects: + // moved the array down here (there's a dummy above) + // V0.9.4 (2000-06-12) [umoeller] + HOBJECT ahobjHotCornerObjects[8]; + // Indices: + // 0 = lower left corner, + // 1 = top left corner, + // 2 = lower right corner, + // 3 = top right corner; + // borders added V0.9.4 (2000-06-12) [umoeller]: + // 4 = top border, + // 5 = left border, + // 6 = right border, + // 7 = bottom border. + // V0.9.18 (2002-02-12) [pr] + #define SCREENCORNER_MIN 0 + #define SCREENCORNER_BOTTOMLEFT 0 + #define SCREENCORNER_TOPLEFT 1 + #define SCREENCORNER_BOTTOMRIGHT 2 + #define SCREENCORNER_TOPRIGHT 3 + #define SCREENCORNER_TOP 4 + #define SCREENCORNER_LEFT 5 + #define SCREENCORNER_RIGHT 6 + #define SCREENCORNER_BOTTOM 7 + #define SCREENCORNER_MAX 7 + // If any item is NULLHANDLE, it means the + // corner is inactive (no function defined). + // If the hiword of the item is 0xFFFF, this + // means a special function has been defined: + // (#define's added V0.9.19 (2002-04-17) [umoeller]): + #define SPECIALOBJ_FIRST 0xFFFF0000 + #define SPECIALOBJ_SHOWWINDOWLIST 0xFFFF0000 + #define SPECIALOBJ_DESKTOPCONTEXTMENU 0xFFFF0001 + #define SPECIALOBJ_PAGER_SHOW 0xFFFF0002 + // the following added (2001-01-26) [lafaix] + #define SPECIALOBJ_PAGER_UP 0xFFFF0003 + #define SPECIALOBJ_PAGER_RIGHT 0xFFFF0004 + #define SPECIALOBJ_PAGER_DOWN 0xFFFF0005 + #define SPECIALOBJ_PAGER_LEFT 0xFFFF0006 + // the following added V0.9.18 [pr] + #define SPECIALOBJ_SCREENWRAP 0xFFFF0007 + // Otherwise (> 0 and < 0xFFFF0000), we have + // a "real" object handle, and a regular WPS + // object is to be opened. + + // special treatment for conditional-cascade submenus when + // using sliding menus (V0.9.6 (2000-10-27) [umoeller]) + PM_BOOL fConditionalCascadeSensitive; + + // more XPager configuration V0.9.7 (2000-12-08) [umoeller] + PM_BOOL fRemoved3; // __fSlidingIgnoreXCenter; + // removed V0.9.19 (2002-05-07) [umoeller] + + // screen corner objects sensitivity; in percent of the + // adjacents borders. 0 = off, 50 = borders objects disabled + // V0.9.9 (2001-03-15) [lafaix] + ULONG ulCornerSensitivity; + + // Mouse-button-3 autoscroll and push to bottom features + PM_BOOL fMB3AutoScroll; // deprecated V0.9.19 (2002-04-20) [lafaix] + PM_BOOL fMB3Push2Bottom; // deprecated V0.9.19 (2002-04-20) [lafaix] + + // Auto hide and automatic pointer movement options + // V0.9.14 (2001-08-02) [lafaix] + ULONG __ulAutoHideFlags; + PM_BOOL __fAutoMoveMouse; + ULONG __ulAutoMoveFlags; + ULONG __ulAutoMoveDelay; // V0.9.14 (2001-08-21) [umoeller] + ULONG __ulMouseMappingsCount; // V0.9.19 (2002-04-20) [lafaix] + } HOOKCONFIG, *PHOOKCONFIG; +#pragma pack() + + /* + *@@ GLOBALHOTKEY: + * single XWorkplace object hotkey definition. + * Arrays of this are allocated in shared memory and + * used by xwphook.c, xwpdaemn.c, and also XFldObject + * for hotkey manipulation and detection. + */ + + typedef struct _GLOBALHOTKEY + { + USHORT usFlags; + // Keyboard control codes: + // SHORT1FROMMP(mp1) of WM_CHAR, filtered. + // Only the following flags will be set: + // -- KC_CTRL + // -- KC_ALT + // -- KC_SHIFT + // -- KC_VIRTUALKEY + // -- KC_INVALIDCOMP: special flag used if the + // scan code represents one of the user-defined + // function keys in the XWPKeyboard object. + // KC_CTRL, KC_ALT, KC_SHIFT work always, + // no matter if we're in a PM or VIO session. + // However, for some reason, KC_VIRTUALKEY is + // never set in VIO sessions. We still store it + // in this structure though to be able to display + // the hotkey in the configuration pages. + // The hook will filter that out since the scan + // code is good enough to identify the key. + UCHAR ucScanCode; + // Hardware scan code: + // CHAR4FROMMP(mp1) of WM_CHAR. + // As opposed to what we do with folder hotkeys, + // this must be stored also, because we must use + // the scan code for WM_CHAR processing in the hook + // to identify hotkeys. We cannot use usKeyCode + // because that's different in VIO sessions, while + // this one is always the same. + // Even if any of Ctrl, Alt, Shift are pressed, this + // has the scan code of the additional key which was + // pressed. + USHORT usKeyCode; + // key code: + // if KC_VIRTUALKEY is set in usFlags, this has usvk, + // otherwise usch from WM_CHAR. + // This is only used to be able to display the hotkey + // in the hotkey configuration dialogs; we do _not_ use + // this to check WM_CHAR messages in the hook, because + // this is different between PM and VIO sessions. + ULONG ulHandle; + // handle to post to thread-1 object window (kernel.c); + // this is normally the HOBJECT of the object to be + // opened. + } GLOBALHOTKEY, *PGLOBALHOTKEY; + + /* + *@@ MOUSEMAPPING: + * single XWorkplace mouse mapping definition. + * Arrays of this are allocated in shared memory and + * used by xwphook.c, xwpdaemn.c, and also XWPMouse + * for mouse mappings manipulation and detection. + * + *@@added V0.9.19 (2002-04-20) [lafaix] + */ + + typedef struct _MOUSEMAPPING + { + USHORT usEvent; + // One of the MME_* values (or MME_XBUTTON_FIRST+n + // to denote extra button n, 0 <= n < 32). + // standard mouse events + #define MME_BUTTON1CLICK 0x0001 + #define MME_BUTTON2CLICK 0x0002 + #define MME_BUTTON3CLICK 0x0003 + #define MME_BUTTON1DRAG 0x0004 + #define MME_BUTTON2DRAG 0x0005 + #define MME_BUTTON3DRAG 0x0006 + #define MME_CHORD 0x0007 + // wheel/stick events + #define MME_UP 0x1001 + #define MME_DOWN 0x1002 + #define MME_LEFT 0x1003 + #define MME_RIGHT 0x1004 + // the 2X and 3X variants are handy when mapping an action + // to a wheel/stick movement. They map at least 2 (or 3) + // consecutive events, and hence disambiguate an unexpected + // wheel/stick event. + #define MME_UP2X 0x2001 + #define MME_DOWN2X 0x2002 + #define MME_LEFT2X 0x2003 + #define MME_RIGHT2X 0x2004 + #define MME_UP3X 0x3001 + #define MME_DOWN3X 0x3002 + #define MME_LEFT3X 0x3003 + #define MME_RIGHT3X 0x3004 + // extra buttons + #define MME_XBUTTON_FIRST 0x4000 + // type helpers + #define MME_TYPE_MASK 0xF000 + #define MME_TYPE_STANDARD 0x0000 + #define MME_TYPE_WHEEL 0x1000 + #define MME_TYPE_WHEEL2X 0x2000 + #define MME_TYPE_WHEEL3X 0x3000 + #define MME_TYPE_XBUTTON 0x4000 + #define MME_TYPE_DISABLED 0x8000 + + USHORT usModifiers; + // A possibly empty combination of KC_SHIFT, KC_CTRL, + // and KC_ALT. + CHAR achLocation[32]; + // The class name upon which this mapping applies. + // An empty location (i.e., achLocation[0] = 0) means + // a global mapping. + CHAR achPluginName[8]; + // The plugin library providing the action defined for + // this mapping. An empty location (i.e., + // achPluginName[0] = 0) means a buildin action. + USHORT usAction; + // The action (relative to the plugin) defined for + // this event. + BYTE abSetup[16]; + // A private area possibly refining the action. + } MOUSEMAPPING, *PMOUSEMAPPING; + + /* + *@@ FUNCTIONKEY: + * XWorkplace function key description. + * An array of these is returned by + * hifQueryFunctionKeys(). + * + *@@added V0.9.3 (2000-04-19) [umoeller] + */ + + typedef struct _FUNCTIONKEY + { + UCHAR ucScanCode; // hardware scan code; + // CHAR4FROMMP(mp1) of WM_CHAR + CHAR szDescription[30]; // key description (e.g. "Win left") + PM_BOOL fModifier; // TRUE if the scan code represents + // a modifier key which can be pressed + // together with another key, similar + // to Ctrl or Alt or Del; this will + // allow us to do things like "WinLeft + C" + } FUNCTIONKEY, *PFUNCTIONKEY; + + /* ****************************************************************** + * + * Messages + * + ********************************************************************/ + + #define XDM_HOOKINSTALL (WM_USER + 400) + + #define XDM_DESKTOPREADY (WM_USER + 401) + + #define XDM_HOOKCONFIG (WM_USER + 402) + +#ifndef __NOPAGER__ + #define XDM_STARTSTOPPAGER (WM_USER + 403) + + #define XDM_PAGERCONFIG (WM_USER + 404) + // flags for XDM_PAGERCONFIG: + #define PGRCFG_REPAINT 0x0001 // invalidates mini windows + #define PGRCFG_REFORMAT 0x0004 // causes PGRM_POSITIONFRAME, + // repaints background too + #define PGRCFG_STICKIES 0x0008 // sticky windows have changed +#endif + + #define XDM_HOTKEYPRESSED (WM_USER + 405) + + #define XDM_HOTKEYSCHANGED (WM_USER + 406) + + #define XDM_FUNCTIONKEYSCHANGED (WM_USER + 407) + +#ifndef __NOSLIDINGFOCUS__ + #define XDM_SLIDINGFOCUS (WM_USER + 408) +#endif + + #define XDM_SLIDINGMENU (WM_USER + 409) + + #define XDM_HOTCORNER (WM_USER + 410) + + #define XDM_WMCHORDWINLIST (WM_USER + 411) + + // added V0.9.9 (2001-03-18) [lafaix] + #define XDM_BEGINSCROLL (WM_USER + 413) + #define XDM_SETPOINTER (WM_USER + 414) + #define XDM_ENDSCROLL (WM_USER + 415) + + // added V0.9.12 (2001-05-12) [umoeller] + #define XDM_RECOVERWINDOWS (WM_USER + 416) + + #define XDM_ADDDISKWATCH (WM_USER + 417) + + /* + *@@ ADDDISKWATCH: + * struct used with XDM_ADDDISKWATCH. + * + *@@added V0.9.14 (2001-08-01) [umoeller] + */ + + typedef struct _ADDDISKWATCH + { + ULONG ulLogicalDrive; // disk to be monitored + HWND hwndNotify; // window to be notified on change + ULONG ulMessage; // message to be posted to window + } ADDDISKWATCH, *PADDDISKWATCH; + + #define XDM_REMOVEDISKWATCH (WM_USER + 418) + + #define XDM_QUERYDISKS (WM_USER + 419) + + #define XDM_ADDCLICKWATCH (WM_USER + 420) + + #define XDM_MOUSECLICKED (WM_USER + 421) + +#ifndef __NOMOVEMENT2FEATURES__ + #define XDM_MOVEPTRTOBUTTON (WM_USER + 422) +#endif + + #define XDM_DISABLEHOTKEYSTEMP (WM_USER + 423) + + #define XDM_STARTAPP (WM_USER + 424) + + #define XDM_ADDWINLISTWATCH (WM_USER + 425) + + #define XDM_WINDOWCHANGE (WM_USER + 426) + + #define XDM_ICONCHANGE (WM_USER + 427) + + #define XDM_QUERYWINLIST (WM_USER + 428) + + #define XDM_REMOVEWINLISTWATCH (WM_USER + 429) // V0.9.19 (2002-06-14) [lafaix] + + #define XDM_REMOVECLICKWATCH (WM_USER + 430) // V0.9.19 (2002-06-14) [lafaix] + +#ifndef __NOPAGER__ + #define XDM_TOGGLETRANSIENTSTICKY (WM_USER + 431) // V1.0.0 (2002-07-26) [lafaix] + #define XDM_ISTRANSIENTSTICKY (WM_USER + 432) +#endif + + #define XDM_NLSCHANGED (WM_USER + 433) // V1.0.0 (2002-09-15) [lafaix] +#endif + + + diff --git a/vcl/os2/source/app/makefile.mk b/vcl/os2/source/app/makefile.mk new file mode 100644 index 000000000000..e2c14fb1744a --- /dev/null +++ b/vcl/os2/source/app/makefile.mk @@ -0,0 +1,63 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=SV +TARGET=salapp + +# --- Settings ----------------------------------------------------- + +#.INCLUDE : svpre.mk +.INCLUDE : settings.mk +#.INCLUDE : sv.mk +.INCLUDE : $(PRJ)$/util$/makefile2.pmk + + +# --- Files -------------------------------------------------------- + +YD00_CXXFILES=\ + salshl.cxx \ + salinst.cxx \ + sallang.cxx \ + saltimer.cxx \ + salsys.cxx + +SLOFILES= $(SLO)$/salshl.obj \ + $(SLO)$/printf.obj \ + $(SLO)$/salinfo.obj \ + $(SLO)$/salinst.obj \ + $(SLO)$/sallang.obj \ + $(SLO)$/saltimer.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/os2/source/app/printf.c b/vcl/os2/source/app/printf.c new file mode 100644 index 000000000000..7cfcf4efc559 --- /dev/null +++ b/vcl/os2/source/app/printf.c @@ -0,0 +1,284 @@ +/* ----------------------------------------------------------------- */ +/* PRINTF: diverts PRINTF calls to an OS/2 Named Queue */ +/* Copyright (c) IBM Corporation, 1991, 1992 */ +/* ----------------------------------------------------------------- */ +/* This version for OS/2 2.x, 32-bit programs. Mike Cowlishaw */ +/* */ +/* This routine, when linked into an .EXE instead of the usual C */ +/* runtime, sends the edited result string to a named queue (if */ +/* it exists). If the queue does not exist, then all printf data */ +/* are discarded (ignored). */ +/* */ +/* The result string is accumulated until a line feed (LF) character */ +/* is received; the whole line is then sent to the queue. Lines are */ +/* automatically broken at a set (tailorable) length, if necessary. */ +/* */ +/* This routine may be tailored by altering the #defines at the */ +/* top: */ +/* */ +/* PRINTFID - An ID string that is prefixed to each line of */ +/* data before being sent to the queue. This */ +/* can be any string, or the null string. */ +/* PRINTFMAXLEN - Maximum length of string that can be formatted */ +/* in a single call. */ +/* Results are unpredictable if this length is */ +/* exceeded. Default is 250. */ +/* PRINTFLINELEN - Maximum length of a line that will be sent. */ +/* This excludes the prefix and its blank. If the */ +/* calls to printf cause a line to be generated */ +/* that is longer than this, the line will be */ +/* broken at this point. */ +/* PRINTFTHREADS - Maximum number of threads expected. This may */ +/* need to be increased if the process limitation */ +/* is removed, or you can save a little storage */ +/* by decreasing it. PRINTFs from threads larger */ +/* than this number are ignored. */ +/* PRINTFQNAME - The name of the public queue that the result */ +/* is to be sent to. Normally '\QUEUES\PRINTF32'. */ +/* Note that the \QUEUES\ part is required. */ +/* */ +/* Returns: */ +/* n: Count of data characters, if successfully received */ +/* 0: If no queue existed (i.e., no server) */ +/* <0: An error occurred (e.g., out of memory) */ +/* */ +/* Restrictions: */ +/* 1. Total length of data (length of PRINTFID, + PRINTFMAXLEN) */ +/* must be less than 32K-1. */ +/* 2. This has only been tested under IBM C Set/2 compiler. It */ +/* may need modification for other compilers. */ +/* 3. This version uses a static array to point to the per-thread */ +/* data. The code could be made read-only by hanging this */ +/* array (and the other static information) off a system-owned */ +/* anchor of some kind. */ +/* 4. To use PRINTF within other than the main thread in a */ +/* program, that thread must be started with _beginthread */ +/* (not DosCreateThread). This restriction is a consequence of */ +/* the use of C library routines (sprintf) in PRINTF, and may */ +/* not apply to all compilers. */ +/* 5. If the last PRINTF done by a thread does not end in '\n' */ +/* then the final part-line may be lost, or appear later. */ +/* */ +/* Protocol: */ +/* PRINTF writes its data to the named queue using the following */ +/* protocol: */ +/* Address -- Holds the address of the string to be sent. This */ +/* is a 0-terminated string) starting at offset 0. */ +/* Length -- The length of the data, including terminator. */ +/* A negative length indicates a BELL in the data. */ +/* Request -- Timestamp (when queue was written) in C long */ +/* integer format (as returned by time()). */ +/* This may be 0L if not required. */ +/* */ +/* Notes: */ +/* 1. PMPRINTF uses a queue and shared memory messages because: */ +/* (a) It makes collection at the receiving end very easy. */ +/* (b) I wanted to experiment with queues and shared memory. */ +/* This make not be the most cost-effective method. */ +/* 2. Typical IBM C Set/2 compiler invocation: */ +/* icc /c /Gm /O+ /Q /J /Kabgop */ +/* If you get linking errors (duplicate symbols, etc.), try */ +/* recompiling PRINTF.C with the same options as you use for */ +/* your main program. */ +/* 3. PRINTF sends the timestamp across the queue as a GMT long */ +/* integer, the result from a call to the C function time(). */ +/* This will only be correct if the environment variable TZ has */ +/* been set (e.g., TZ=EST5EDT), or you are in the same time */ +/* zone as the default for your compiler. */ +/* For more information, see the tzset() function description */ +/* in your C compiler manual. */ + +/* ----- Customization variables ----- */ +#define PRINTFID "" +#define PRINTFMAXLEN 300 +#define PRINTFLINELEN 100 +#define PRINTFTHREADS 54 +#define PRINTFQNAME "\\QUEUES\\PRINTF32" + +/* ----- Includes and externals ----- */ +#include <stdlib.h> /* standard C functions */ +#include <stddef.h> /* .. */ +#include <string.h> /* .. */ +#include <time.h> /* .. */ +#include <stdarg.h> /* .. */ +#include <stdio.h> /* (needed to pick up real name) */ +#define INCL_DOS /* Operating system definitions */ +#include <os2.h> /* For OS/2 functions */ + +#define max(a,b) (a>b ? a : b) + +/* ----- Local defines ----- */ +#define PRINTFIDSIZE sizeof(PRINTFID) +#define PRINTFMAXBUF PRINTFIDSIZE+PRINTFLINELEN + +/* ----- Per-thread output buffer and current indices into line ---- */ +struct perthread { + LONG lineindex; /* where next char */ + LONG tidemark; /* rightmost char */ + int bell; /* TRUE if line has bell */ + UCHAR line[PRINTFMAXBUF]; /* accumulator */ + }; + +/* ----- Local static variables ----- */ +static ULONG ourpid=0; /* our process ID */ +static ULONG servepid=0; /* process IDs of the server */ +static HQUEUE qhandle=0; /* handle for the queue */ +static struct perthread *tps[PRINTFTHREADS+1]; /* -> per-thread data */ + +/* ----- Local subroutine ----- */ +static int printf_(struct perthread *); + +/* ----------------------------------------------------------------- */ +/* The "printf" function. Note this has a variable number of */ +/* arguments. */ +/* ----------------------------------------------------------------- */ +int debug_printf(const char *f, ...) + { + TIB *ptib; /* process/thread id structures */ + PIB *ppib; /* .. */ + TID ourtid; /* thread ID */ + struct perthread *tp; /* pointer to per-thread data */ + int rc; /* returncode */ + ULONG urc; /* returncode */ + + urc=DosOpenQueue(&servepid, &qhandle, PRINTFQNAME); /* Open the Q */ + /* Non-0 RC means Q does not exist or cannot be opened */ + if (urc==343) return 0; /* queue does not exist, so quit */ + if (urc!=0) return -1; /* report any other error */ + + /* First determine our thread ID (and hence get access to the */ + /* correct per-thread data. If the per-thread data has not been */ + /* allocated, then allocate it now. It is never freed, once */ + /* allocated, as PRINTF is not notified of end-of-thread. */ + DosGetInfoBlocks(&ptib,&ppib); /* get process/thread info */ + ourtid=ptib->tib_ptib2->tib2_ultid; /* .. and copy TID */ + if (ourtid>PRINTFTHREADS) /* too many threads .. */ + return 0; /* .. so quit, quietly */ + tp=tps[ourtid]; /* copy to local pointer */ + if (tp==NULL) { /* uninitialized (NULL=0) */ + /* allocate a per-thread structure */ + tp=(struct perthread *)malloc(sizeof(struct perthread)); + if (tp==NULL) return -1; /* out of memory -- return error */ + tps[ourtid]=tp; /* save for future calls */ + strcpy(tp->line,PRINTFID); /* initialize: line.. */ + tp->lineindex=PRINTFIDSIZE-1; /* ..where next char */ + tp->tidemark =PRINTFIDSIZE-2; /* ..rightmost char */ + tp->bell=FALSE; /* ..if line has bell */ + if (ourpid==0) ourpid=ppib->pib_ulpid; /* save PID for all to use */ + } + + { /* Block for declarations -- only needed if queue exists, etc. */ + LONG count; /* count of characters formatted */ + UCHAR buffer[PRINTFMAXLEN+1]; /* formatting area */ + LONG i, newind; /* work */ + UCHAR ch; /* .. */ + va_list argptr; /* -> variable argument list */ + + va_start(argptr, f); /* get pointer to argument list */ + count=vsprintf(buffer, f, argptr); + va_end(argptr); /* done with variable arguments */ + + if (count<0) return count-1000;/* bad start */ + + if (count>PRINTFMAXLEN) { + /* Disaster -- we are probably "dead", but just in case we */ + /* are not, carry on with truncated data. */ + count=PRINTFMAXLEN; + } + buffer[count]='\0'; /* ensure terminated */ + /* OK, ready to go with the data now in BUFFER */ + /* We copy from the formatted string to the output (line) buffer, */ + /* taking note of certain control characters and sending a line */ + /* the queue whenever we see a LF control, or when the line */ + /* fills (causing a forced break). */ + for (i=0; ; i++) { + ch=buffer[i]; if (!ch) break; + switch(ch) { + case '\r': /* carriage return */ + tp->lineindex=PRINTFIDSIZE-1; /* back to start of line */ + break; + case '\n': /* new line */ + case '\f': /* form feed */ + rc=printf_(tp); /* print a line */ + if (rc!=0) return rc; /* error */ + break; + case '\t': /* tab */ + newind=tp->lineindex-PRINTFIDSIZE+1; /* offset into data */ + newind=tp->lineindex+5-newind%5; /* new index requested */ + if (newind>=PRINTFMAXBUF) newind=PRINTFMAXBUF; /* clamp */ + for (; tp->lineindex<newind; tp->lineindex++) { + if (tp->lineindex>tp->tidemark) { /* beyond current end */ + tp->line[tp->lineindex]=' '; /* add space */ + tp->tidemark=tp->lineindex; + } + } + break; + case '\v': /* vertical tab */ + /* ignore it */ + break; + case '\b': /* backspace */ + tp->lineindex=max(tp->lineindex-1,PRINTFIDSIZE); + break; + case '\a': /* alert (bell) */ + tp->bell=TRUE; + break; + default: /* ordinary character */ + tp->line[tp->lineindex]=ch; + if (tp->lineindex>tp->tidemark) /* is rightmost.. */ + tp->tidemark=tp->lineindex; + tp->lineindex++; /* step for next */ + } /* switch */ + if (tp->lineindex>=PRINTFMAXBUF) { + rc=printf_(tp); /* print a line */ + if (rc!=0) return rc; /* error */ + } + + } /* copy loop */ + return count; /* all formatted data processed */ + } /* block */ + } /* printf */ + +/* ----- printf_(tp) -- Local subroutine to send a line ------------ */ +/* A line has been completed (or overflowed): write it to the queue. */ +int printf_(struct perthread *tp) /* pointer to per-thread data */ + { + ULONG urc; /* unsigned returncode */ + PSZ pszTo, pszFrom; /* character pointers */ + PVOID addr; /* address of output data */ + long size; /* total size of output data */ + time_t timenow; /* holds current time */ + + tp->line[tp->tidemark+1]='\0'; /* add terminator */ + size=tp->tidemark+2; /* total length of data */ + + /* Get some shared memory that can be given away */ + urc=DosAllocSharedMem(&addr, NULL, (unsigned)size, + OBJ_GIVEABLE|PAG_WRITE|PAG_COMMIT); + if (urc!=0) return -2; /* error */ + + pszTo=addr; /* copy for clarity */ + pszFrom=&(tp->line[0]); /* pointer to source */ + strcpy(pszTo,pszFrom); /* copy the string to shared memory */ + + if (ourpid!=servepid) { /* (no giveaway needed if to self) */ + urc=DosGiveSharedMem(addr, servepid, PAG_READ); /* give access */ + if (urc!=0) return -3;} /* error */ + + /* Write the selector, size, and timestamp to the queue */ + if (tp->bell) size=-size; /* BELL passed by negation */ + time(&timenow); /* optional - else use 0 */ + urc=DosWriteQueue(qhandle, /* handle */ + (unsigned)timenow, /* 'request' (timestamp) */ + (unsigned)size, /* 'length' (length/bell) */ + addr, /* 'address' (address) */ + 0); /* priority (FIFO if enabled) */ + if (urc!=0) return -4; /* error */ + if (ourpid!=servepid) { /* if given away.. */ + urc=DosFreeMem(addr); /* .. *we* are done with it */ + if (urc!=0) return -5;} /* error */ + /* Reset the line buffer and indices */ + tp->lineindex=PRINTFIDSIZE-1; /* where next char */ + tp->tidemark =PRINTFIDSIZE-2; /* rightmost char */ + tp->bell =FALSE; /* true if line has bell */ + return 0; /* success! */ + } /* printf_ */ diff --git a/vcl/os2/source/app/salinfo.cxx b/vcl/os2/source/app/salinfo.cxx new file mode 100644 index 000000000000..39700fc26a75 --- /dev/null +++ b/vcl/os2/source/app/salinfo.cxx @@ -0,0 +1,185 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salinfo.cxx,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#define INCL_PM +#define INCL_DOS +#define INCL_GPI +#include <svpm.h> + +#include <tools/string.hxx> +#include <salsys.h> +#include <salframe.h> +#include <salinst.h> +#include "saldata.hxx" +#include <tools/debug.hxx> +#include <vcl/svdata.hxx> +#include <rtl/ustrbuf.hxx> +#include "vcl/window.hxx" + +#ifndef _SV_SALGTYPE_HXX +//#include <salgtype.hxx> +#endif + +#define CHAR_POINTER(THE_OUSTRING) ::rtl::OUStringToOString (THE_OUSTRING, RTL_TEXTENCODING_UTF8).pData->buffer + +class Os2SalSystem : public SalSystem +{ +public: + Os2SalSystem() {} + virtual ~Os2SalSystem(); + + virtual unsigned int GetDisplayScreenCount(); + virtual Rectangle GetDisplayScreenPosSizePixel( unsigned int nScreen ); + //virtual bool GetSalSystemDisplayInfo( DisplayInfo& rInfo ); + + virtual bool IsMultiDisplay(); + virtual unsigned int GetDefaultDisplayNumber(); + virtual Rectangle GetDisplayWorkAreaPosSizePixel( unsigned int nScreen ); + virtual rtl::OUString GetScreenName( unsigned int nScreen ); + + virtual int ShowNativeMessageBox( const String& rTitle, + const String& rMessage, + int nButtonCombination, + int nDefaultButton); +}; + +SalSystem* Os2SalInstance::CreateSalSystem() +{ + return new Os2SalSystem(); +} + +Os2SalSystem::~Os2SalSystem() +{ +} + +// ----------------------------------------------------------------------- +#if 0 +bool Os2SalSystem::GetSalSystemDisplayInfo( DisplayInfo& rInfo ) +{ + HDC hDC; + if( hDC = WinQueryWindowDC(HWND_DESKTOP) ) + { + LONG bitCount; + DevQueryCaps(hDC, CAPS_COLOR_BITCOUNT, CAPS_COLOR_BITCOUNT, &bitCount); + rInfo.nWidth = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ); + rInfo.nHeight = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ); + rInfo.nDepth = bitCount; + return true; + } + else + return false; +} +#endif + +unsigned int Os2SalSystem::GetDisplayScreenCount() +{ + return 1; +} + +Rectangle Os2SalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen ) +{ + Rectangle aRet; + aRet = Rectangle( Point(), Point( WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ), + WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) ) ); + return aRet; +} + +// ----------------------------------------------------------------------- +/* We have to map the button identifier to the identifier used by the Os232 + Platform SDK to specify the default button for the MessageBox API. + The first dimension is the button combination, the second dimension + is the button identifier. +*/ +static int DEFAULT_BTN_MAPPING_TABLE[][8] = +{ + // Undefined OK CANCEL ABORT RETRY IGNORE YES NO + { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK + { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK_CANCEL + { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //ABORT_RETRY_IGNO + { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO_CANCEL + { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO + { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 } //RETRY_CANCEL +}; + +static int COMBI_BTN_MAPPING_TABLE[] = +{ + MB_OK, MB_OKCANCEL, MB_ABORTRETRYIGNORE, MB_YESNO, MB_YESNOCANCEL, MB_RETRYCANCEL +}; + +int Os2SalSystem::ShowNativeMessageBox(const String& rTitle, const String& rMessage, int nButtonCombination, int nDefaultButton) +{ + DBG_ASSERT( nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK && + nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL && + nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK && + nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, "Invalid arguments!" ); + + int nFlags = MB_APPLMODAL | MB_WARNING | COMBI_BTN_MAPPING_TABLE[nButtonCombination]; + + if (nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK && + nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL && + nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK && + nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO) + nFlags |= DEFAULT_BTN_MAPPING_TABLE[nButtonCombination][nDefaultButton]; + + //#107209 hide the splash screen if active + ImplSVData* pSVData = ImplGetSVData(); + if (pSVData->mpIntroWindow) + pSVData->mpIntroWindow->Hide(); + + return WinMessageBox( + HWND_DESKTOP, HWND_DESKTOP, + (PSZ)CHAR_POINTER(rMessage), + (PSZ)CHAR_POINTER(rTitle), + 0, nFlags); +} + + +unsigned int Os2SalSystem::GetDefaultDisplayNumber() +{ + return 0; +} + +bool Os2SalSystem::IsMultiDisplay() +{ + return false; +} + +Rectangle Os2SalSystem::GetDisplayWorkAreaPosSizePixel( unsigned int nScreen ) +{ + return GetDisplayScreenPosSizePixel( nScreen ); +} + +rtl::OUString Os2SalSystem::GetScreenName( unsigned int nScreen ) +{ + rtl::OUStringBuffer aBuf( 32 ); + aBuf.appendAscii( "VirtualScreen " ); + aBuf.append( sal_Int32(nScreen) ); + return aBuf.makeStringAndClear(); +} diff --git a/vcl/os2/source/app/salinst.cxx b/vcl/os2/source/app/salinst.cxx new file mode 100644 index 000000000000..633ad4137aff --- /dev/null +++ b/vcl/os2/source/app/salinst.cxx @@ -0,0 +1,866 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salinst.cxx,v $ + * $Revision: 1.8.74.1 $ + * + * 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. + * + ************************************************************************/ + +#define INCL_DOSMISC +#define INCL_DOSMODULEMGR +#define INCL_DOSPROCESS + +#include <string.h> +#include <svpm.h> +#include <process.h> + +#define _SV_SALINST_CXX + +#ifndef _VOS_MUTEX_HXX +#include <vos/mutex.hxx> +#endif +#include <tools/debug.hxx> + +#ifndef _SV_SALIDS_HRC +#include <salids.hrc> +#endif +#include <vcl/salatype.hxx> +#include <saldata.hxx> +#include <salinst.h> +#include <salframe.h> +#include <salobj.h> +#include <saltimer.h> +#include <salbmp.h> +#include <vcl/salimestatus.hxx> +#include <vcl/timer.hxx> +#include <tools/solarmutex.hxx> + +// ======================================================================= + +void SalAbort( const XubString& rErrorText ) +{ + ImplFreeSalGDI(); + + if( !rErrorText.Len() ) + fprintf( stderr, "Application Error " ); + else + fprintf( stderr, "%s ", + ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() ); + abort(); +} + +// ======================================================================= + +ULONG GetCurrentThreadId() +{ + PTIB pptib = NULL; + PPIB pppib = NULL; + + DosGetInfoBlocks( &pptib, &pppib ); + return pptib->tib_ptib2->tib2_ultid; +} + +// ======================================================================= + +MRESULT EXPENTRY SalComWndProc( HWND hWnd, ULONG nMsg, MPARAM nMP1, MPARAM nMP2 ); + +// ======================================================================= + +class SalYieldMutex : public vos::OMutex +{ +public: + Os2SalInstance* mpInstData; + ULONG mnCount; + ULONG mnThreadId; + +public: + SalYieldMutex( Os2SalInstance* pInstData ); + + virtual void SAL_CALL acquire(); + virtual void SAL_CALL release(); + virtual sal_Bool SAL_CALL tryToAcquire(); + + ULONG GetAcquireCount( ULONG nThreadId ); +}; + +// ----------------------------------------------------------------------- + +SalYieldMutex::SalYieldMutex( Os2SalInstance* pInstData ) +{ + mpInstData = pInstData; + mnCount = 0; + mnThreadId = 0; +} + +// ----------------------------------------------------------------------- + +void SalYieldMutex::acquire() +{ + OMutex::acquire(); + mnCount++; + mnThreadId = GetCurrentThreadId(); +} + +// ----------------------------------------------------------------------- + +void SalYieldMutex::release() +{ + ULONG nThreadId = GetCurrentThreadId(); + if ( mnThreadId != nThreadId ) + OMutex::release(); + else + { + SalData* pSalData = GetSalData(); + if ( pSalData->mnAppThreadId != nThreadId ) + { + if ( mnCount == 1 ) + { + mpInstData->mpSalWaitMutex->acquire(); + if ( mpInstData->mnYieldWaitCount ) + WinPostMsg( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 ); + mnThreadId = 0; + mnCount--; + OMutex::release(); + mpInstData->mpSalWaitMutex->release(); + } + else + { + mnCount--; + OMutex::release(); + } + } + else + { + if ( mnCount == 1 ) + mnThreadId = 0; + mnCount--; + OMutex::release(); + } + } +} + +// ----------------------------------------------------------------------- + +sal_Bool SalYieldMutex::tryToAcquire() +{ + if ( OMutex::tryToAcquire() ) + { + mnCount++; + mnThreadId = GetCurrentThreadId(); + return sal_True; + } + else + return sal_False; +} + +// ----------------------------------------------------------------------- + +ULONG SalYieldMutex::GetAcquireCount( ULONG nThreadId ) +{ + if ( nThreadId == mnThreadId ) + return mnCount; + else + return 0; +} + +// ----------------------------------------------------------------------- + +void ImplSalYieldMutexAcquireWithWait() +{ + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( !pInst ) + return; + + // If we are the main thread, then we must wait with wait, because + // in if we don't reschedule, then we create deadlocks if a Windows + // Function is called from another thread. If we arn't the main thread, + // than we call qcquire directly. + ULONG nThreadId = GetCurrentThreadId(); + SalData* pSalData = GetSalData(); + if ( pSalData->mnAppThreadId == nThreadId ) + { + // Wenn wir den Mutex nicht bekommen, muessen wir solange + // warten, bis wir Ihn bekommen + BOOL bAcquire = FALSE; + do + { + if ( pInst->mpSalYieldMutex->tryToAcquire() ) + bAcquire = TRUE; + else + { + pInst->mpSalWaitMutex->acquire(); + if ( pInst->mpSalYieldMutex->tryToAcquire() ) + { + bAcquire = TRUE; + pInst->mpSalWaitMutex->release(); + } + else + { + pInst->mnYieldWaitCount++; + pInst->mpSalWaitMutex->release(); + QMSG aTmpMsg; + WinGetMsg( pSalData->mhAB, &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD ); + pInst->mnYieldWaitCount--; + if ( pInst->mnYieldWaitCount ) + WinPostMsg( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0 , 0 ); + } + } + } + while ( !bAcquire ); + } + else + pInst->mpSalYieldMutex->acquire(); +} + +// ----------------------------------------------------------------------- + +BOOL ImplSalYieldMutexTryToAcquire() +{ + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst ) + return pInst->mpSalYieldMutex->tryToAcquire(); + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +void ImplSalYieldMutexAcquire() +{ + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst ) + pInst->mpSalYieldMutex->acquire(); +} + +// ----------------------------------------------------------------------- + +void ImplSalYieldMutexRelease() +{ + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst ) + pInst->mpSalYieldMutex->release(); +} + +// ----------------------------------------------------------------------- + +ULONG ImplSalReleaseYieldMutex() +{ + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( !pInst ) + return 0; + + SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex; + ULONG nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() ); + ULONG n = nCount; + while ( n ) + { + pYieldMutex->release(); + n--; + } + + return nCount; +} + +// ----------------------------------------------------------------------- + +void ImplSalAcquireYieldMutex( ULONG nCount ) +{ + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( !pInst ) + return; + + SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex; + while ( nCount ) + { + pYieldMutex->acquire(); + nCount--; + } +} + +// ----------------------------------------------------------------------- + +#ifdef DBG_UTIL + +void ImplDbgTestSolarMutex() +{ + SalData* pSalData = GetSalData(); + ULONG nCurThreadId = GetCurrentThreadId(); + if ( pSalData->mnAppThreadId != nCurThreadId ) + { + if ( pSalData->mpFirstInstance ) + { + SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex; + if ( pYieldMutex->mnThreadId != nCurThreadId ) + { + DBG_ERROR( "SolarMutex not locked, and not thread save code in VCL is called from outside of the main thread" ); + } + } + } + else + { + if ( pSalData->mpFirstInstance ) + { + SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex; + if ( pYieldMutex->mnThreadId != nCurThreadId ) + { + DBG_ERROR( "SolarMutex not locked in the main thread" ); + } + } + } +} + +#endif + +// ======================================================================= + +void InitSalData() +{ + SalData* pSalData = new SalData; + memset( pSalData, 0, sizeof( SalData ) ); + SetSalData( pSalData ); +} + +// ----------------------------------------------------------------------- + +void DeInitSalData() +{ + SalData* pSalData = GetSalData(); + if ( pSalData->mpFontMetrics ) + delete pSalData->mpFontMetrics; + delete pSalData; + SetSalData( NULL ); +} + +// ----------------------------------------------------------------------- + +void InitSalMain() +{ + PPIB pib; + PTIB tib; + HAB hAB; + HMQ hMQ; + SalData* pData = GetAppSalData(); +#if OSL_DEBUG_LEVEL>0 +printf("InitSalMain\n"); +#endif + + // morph application to PM + DosGetInfoBlocks(&tib, &pib); + // Change flag from VIO to PM: + if (pib->pib_ultype==2) pib->pib_ultype = 3; + + // create anchor block + hAB = WinInitialize( 0 ); + if ( !hAB ) + return; + + // create message queue + hMQ = WinCreateMsgQueue( hAB, 60 ); + if ( !hMQ ) + { + WinTerminate( hAB ); + return; + } + + if ( pData ) // Im AppServer NULL + { + // Ankerblock und Messagequeue merken + pData->mhAB = hAB; + pData->mhMQ = hMQ; + } + +} + +void DeInitSalMain() +{ +#if OSL_DEBUG_LEVEL>0 +printf("DeInitSalMain\n"); +#endif + + SalData* pData = GetAppSalData(); + // destroy message queue and anchor block + WinDestroyMsgQueue( pData->mhMQ ); + WinTerminate( pData->mhAB ); + +} + +// ----------------------------------------------------------------------- + +SalInstance* CreateSalInstance() +{ + SalData* pSalData = GetSalData(); + + // determine the os2 version + ULONG nMayor; + ULONG nMinor; + DosQuerySysInfo( QSV_VERSION_MAJOR, QSV_VERSION_MAJOR, &nMayor, sizeof( nMayor ) ); + DosQuerySysInfo( QSV_VERSION_MINOR, QSV_VERSION_MINOR, &nMinor, sizeof( nMinor ) ); + aSalShlData.mnVersion = (USHORT)(nMayor*10 + nMinor); + + pSalData->mnAppThreadId = GetCurrentThreadId(); + + // register frame class + if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_FRAME_CLASSNAME, + (PFNWP)SalFrameWndProc, CS_MOVENOTIFY /* 17/08 CS_HITTEST | CS_MOVENOTIFY */, + SAL_FRAME_WNDEXTRA ) ) + { + return NULL; + } + // register subframe class + if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_SUBFRAME_CLASSNAME, + (PFNWP)SalFrameWndProc, CS_SAVEBITS| CS_MOVENOTIFY, + SAL_FRAME_WNDEXTRA ) ) + { + return NULL; + } + // register object class + if ( !WinRegisterClass( pSalData->mhAB, (PSZ)SAL_COM_CLASSNAME, + (PFNWP)SalComWndProc, 0, 0 )) + { + return NULL; + } + + HWND hComWnd = WinCreateWindow( HWND_OBJECT, (PCSZ)SAL_COM_CLASSNAME, + (PCSZ)"", 0, 0, 0, 0, 0, + HWND_OBJECT, HWND_TOP, + 222, NULL, NULL); + if ( !hComWnd ) + return NULL; + +#if OSL_DEBUG_LEVEL>0 + debug_printf("CreateSalInstance hComWnd %x\n", hComWnd); +#endif + Os2SalInstance* pInst = new Os2SalInstance; + + // init instance (only one instance in this version !!!) + pSalData->mpFirstInstance = pInst; + pInst->mhAB = pSalData->mhAB; + pInst->mhMQ = pSalData->mhMQ; + pInst->mnArgc = pSalData->mnArgc; + pInst->mpArgv = pSalData->mpArgv; + pInst->mhComWnd = hComWnd; + + // AppIcon ermitteln + ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, pInst->mhAppIcon); + + // init static GDI Data + ImplInitSalGDI(); + + return pInst; +} + +// ----------------------------------------------------------------------- + +void DestroySalInstance( SalInstance* pInst ) +{ + SalData* pSalData = GetSalData(); + + // (only one instance in this version !!!) + ImplFreeSalGDI(); + +#ifdef ENABLE_IME + // IME-Daten freigeben + if ( pSalData->mpIMEData ) + ImplReleaseSALIMEData(); +#endif + + // reset instance + if ( pSalData->mpFirstInstance == pInst ) + pSalData->mpFirstInstance = NULL; + + delete pInst; +} + +// ----------------------------------------------------------------------- + +Os2SalInstance::Os2SalInstance() +{ + mhComWnd = 0; + mpSalYieldMutex = new SalYieldMutex( this ); + mpSalWaitMutex = new vos::OMutex; + mnYieldWaitCount = 0; + mpSalYieldMutex->acquire(); + ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex ); +} + +// ----------------------------------------------------------------------- + +Os2SalInstance::~Os2SalInstance() +{ + ::tools::SolarMutex::SetSolarMutex( 0 ); + mpSalYieldMutex->release(); + delete mpSalYieldMutex; + delete mpSalWaitMutex; + WinDestroyWindow( mhComWnd); +} + +// ----------------------------------------------------------------------- + +vos::IMutex* Os2SalInstance::GetYieldMutex() +{ + return mpSalYieldMutex; +} +// ----------------------------------------------------------------------- + +ULONG Os2SalInstance::ReleaseYieldMutex() +{ + return ImplSalReleaseYieldMutex(); +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::AcquireYieldMutex( ULONG nCount ) +{ + ImplSalAcquireYieldMutex( nCount ); +} + +// ----------------------------------------------------------------------- + +static void ImplSalYield( BOOL bWait, BOOL bHandleAllCurrentEvents ) +{ + QMSG aMsg; + bool bWasMsg = false, bOneEvent = false; + bool bQuit = false; + + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1; + do + { + if ( WinPeekMsg( pInst->mhAB, &aMsg, 0, 0, 0, PM_REMOVE ) ) + { + WinDispatchMsg( pInst->mhAB, &aMsg ); + bOneEvent = bWasMsg = true; + if (aMsg.msg == WM_QUIT) + bQuit = true; + } + else + bOneEvent = false; + } while( --nMaxEvents && bOneEvent ); + + if ( bWait && ! bWasMsg ) + { + if ( WinGetMsg( pInst->mhAB, &aMsg, 0, 0, 0 ) ) + WinDispatchMsg( pInst->mhAB, &aMsg ); + else + bQuit = true; + } + + if (bQuit) + { + ImplSalYieldMutexAcquireWithWait(); + Os2SalFrame* pFrame = GetSalData()->mpFirstFrame; + if ( pFrame ) + { + if (pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 )) + WinCancelShutdown( pFrame->mhAB, FALSE ); + } + ImplSalYieldMutexRelease(); + } + +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) +{ + SalYieldMutex* pYieldMutex = mpSalYieldMutex; + SalData* pSalData = GetSalData(); + ULONG nCurThreadId = GetCurrentThreadId(); + ULONG nCount = pYieldMutex->GetAcquireCount( nCurThreadId ); + ULONG n = nCount; + while ( n ) + { + pYieldMutex->release(); + n--; + } + if ( pSalData->mnAppThreadId != nCurThreadId ) + { + // #97739# A SendMessage call blocks until the called thread (here: the main thread) + // returns. During a yield however, messages are processed in the main thread that might + // result in a new message loop due to opening a dialog. Thus, SendMessage would not + // return which will block this thread! + // Solution: just give up the time slice and hope that messages are processed + // by the main thread anyway (where all windows are created) + // If the mainthread is not currently handling messages, then our SendMessage would + // also do nothing, so this seems to be reasonable. + + // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open + if( ImplGetSVData()->maAppData.mnModalMode ) + DosSleep(1); + else + WinSendMsg( mhComWnd, SAL_MSG_THREADYIELD, (MPARAM)bWait, (MPARAM)bHandleAllCurrentEvents ); + + n = nCount; + while ( n ) + { + pYieldMutex->acquire(); + n--; + } + } + else + { + ImplSalYield( bWait, bHandleAllCurrentEvents ); + + n = nCount; + while ( n ) + { + ImplSalYieldMutexAcquireWithWait(); + n--; + } + } +} + +// ----------------------------------------------------------------------- + +MRESULT EXPENTRY SalComWndProc( HWND hWnd, ULONG nMsg, + MPARAM nMP1, MPARAM nMP2 ) +{ + //debug_printf( "SalComWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); + + switch ( nMsg ) + { + case SAL_MSG_PRINTABORTJOB: + //ImplSalPrinterAbortJobAsync( (HDC)wParam ); + break; + case SAL_MSG_THREADYIELD: + ImplSalYield( (bool)nMP1, (bool) nMP2); + return 0; + // If we get this message, because another GetMessage() call + // has recieved this message, we must post this message to + // us again, because in the other case we wait forever. + case SAL_MSG_RELEASEWAITYIELD: + { + Os2SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst && pInst->mnYieldWaitCount ) + WinPostMsg( hWnd, SAL_MSG_RELEASEWAITYIELD, nMP1, nMP2 ); + } + return 0; + case SAL_MSG_STARTTIMER: + ImplSalStartTimer( (ULONG)nMP2, FALSE); + return 0; + case SAL_MSG_CREATEFRAME: + return (MRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)nMP2, (ULONG)nMP1 ); + case SAL_MSG_DESTROYFRAME: + delete (SalFrame*)nMP2; + return 0; + case SAL_MSG_DESTROYHWND: + //We only destroy the native window here. We do NOT destroy the SalFrame contained + //in the structure (GetWindowPtr()). + if (WinDestroyWindow((HWND)nMP2) == 0) + { + OSL_ENSURE(0, "DestroyWindow failed!"); + //Failure: We remove the SalFrame from the window structure. So we avoid that + // the window structure may contain an invalid pointer, once the SalFrame is deleted. + SetWindowPtr((HWND)nMP2, 0); + } + return 0; + case SAL_MSG_CREATEOBJECT: + return (MRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (Os2SalFrame*)(ULONG)nMP2 ); + case SAL_MSG_DESTROYOBJECT: + delete (SalObject*)nMP2; + return 0; + case SAL_MSG_CREATESOUND: + //return (MRESULT)((Os2SalSound*)nMP2)->ImplCreate(); + return 0; + case SAL_MSG_DESTROYSOUND: + //((Os2SalSound*)nMP2)->ImplDestroy(); + return 0; + case SAL_MSG_POSTTIMER: + SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, (ULONG)nMP2 ); + break; + case WM_TIMER: + SalTimerProc( hWnd, 0, 0, 0 ); + break; + } + + return WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); +} + +// ----------------------------------------------------------------------- + +bool Os2SalInstance::AnyInput( USHORT nType ) +{ + SalData* pSalData = GetSalData(); + QMSG aQMSG; + + if ( (nType & (INPUT_ANY)) == INPUT_ANY ) + { + // Any Input + if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, 0, 0, PM_NOREMOVE ) ) + return TRUE; + } + else + { + if ( nType & INPUT_MOUSE ) + { + // Test auf Mouseinput + if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, + WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE ) ) + return TRUE; + } + + if ( nType & INPUT_KEYBOARD ) + { + // Test auf Keyinput + if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, + WM_CHAR, WM_CHAR, PM_NOREMOVE ) ) + return !(SHORT1FROMMP( aQMSG.mp1 ) & KC_KEYUP); + } + + if ( nType & INPUT_PAINT ) + { + // Test auf Paintinput + if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, + WM_PAINT, WM_PAINT, PM_NOREMOVE ) ) + return TRUE; + } + + if ( nType & INPUT_TIMER ) + { + // Test auf Timerinput + if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, + WM_TIMER, WM_TIMER, PM_NOREMOVE ) ) + return TRUE; + } + + if ( nType & INPUT_OTHER ) + { + // Test auf sonstigen Input + if ( WinPeekMsg( pSalData->mhAB, &aQMSG, 0, 0, 0, PM_NOREMOVE ) ) + return TRUE; + } + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +SalFrame* Os2SalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle ) +{ + // Um auf Main-Thread umzuschalten + return (SalFrame*)WinSendMsg( mhComWnd, SAL_MSG_CREATEFRAME, (MPARAM)nSalFrameStyle, (MPARAM)pSystemParentData->hWnd ); +} + +// ----------------------------------------------------------------------- + +SalFrame* Os2SalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle ) +{ + // Um auf Main-Thread umzuschalten + HWND mhWndClient; +//31/05/06 YD use client as owner(parent) so positioning will not need to +// take care of borders and captions + if ( pParent ) + mhWndClient = static_cast<Os2SalFrame*>(pParent)->mhWndClient; + else + mhWndClient = 0; + return (SalFrame*)WinSendMsg( mhComWnd, SAL_MSG_CREATEFRAME, (MPARAM)nSalFrameStyle, (MPARAM)mhWndClient ); +} + + +// ----------------------------------------------------------------------- + +void Os2SalInstance::DestroyFrame( SalFrame* pFrame ) +{ + WinSendMsg( mhComWnd, SAL_MSG_DESTROYFRAME, 0, (MPARAM)pFrame ); +} + +// ----------------------------------------------------------------------- + +SalObject* Os2SalInstance::CreateObject( SalFrame* pParent, + SystemWindowData* /*pWindowData*/, // SystemWindowData meaningless on Windows + BOOL /*bShow*/ ) +{ + // Um auf Main-Thread umzuschalten + return (SalObject*)WinSendMsg( mhComWnd, SAL_MSG_CREATEOBJECT, 0, (MPARAM)pParent ); +} + + +// ----------------------------------------------------------------------- + +void Os2SalInstance::DestroyObject( SalObject* pObject ) +{ + WinSendMsg( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (MPARAM)pObject ); +} + +// ----------------------------------------------------------------------- + +void* Os2SalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) +{ + rReturnedBytes = 1; + rReturnedType = AsciiCString; + return (void*) ""; +} + +void Os2SalInstance::AddToRecentDocumentList(const rtl::OUString& /*rFileUrl*/, const rtl::OUString& /*rMimeType*/) +{ +} + +// ----------------------------------------------------------------------- + +SalTimer* Os2SalInstance::CreateSalTimer() +{ + return new Os2SalTimer(); +} + +// ----------------------------------------------------------------------- + +SalBitmap* Os2SalInstance::CreateSalBitmap() +{ + return new Os2SalBitmap(); +} + +// ----------------------------------------------------------------------- + +class Os2ImeStatus : public SalI18NImeStatus +{ + public: + Os2ImeStatus() {} + virtual ~Os2ImeStatus() {} + + // asks whether there is a status window available + // to toggle into menubar + virtual bool canToggle() { return false; } + virtual void toggle() {} +}; + +SalI18NImeStatus* Os2SalInstance::CreateI18NImeStatus() +{ + return new Os2ImeStatus(); +} + +// ----------------------------------------------------------------------- + +const ::rtl::OUString& SalGetDesktopEnvironment() +{ + static ::rtl::OUString aDesktopEnvironment( RTL_CONSTASCII_USTRINGPARAM( "OS/2" ) ); + return aDesktopEnvironment; +} + +SalSession* Os2SalInstance::CreateSalSession() +{ + return NULL; +} + diff --git a/vcl/os2/source/app/sallang.cxx b/vcl/os2/source/app/sallang.cxx new file mode 100644 index 000000000000..fab9328464f2 --- /dev/null +++ b/vcl/os2/source/app/sallang.cxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sallang.cxx,v $ + * $Revision: 1.4 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SALLANG_HXX +#include <sallang.hxx> +#endif + +// ======================================================================= + +// ----------------------------------------------------------------------- +// English (US/UK/AUS/CAN/NZ/EIRE/SAFRICA/JAMAICA/CARRIBEAN) +static const wchar_t* aImplLangEnglishTab[LSTR_COUNT] = +{ + L"Shift", // LSTR_KEY_SHIFT + L"Ctrl", // LSTR_KEY_CTRL + L"Alt", // LSTR_KEY_ALT + L"Up", // LSTR_KEY_UP + L"Down", // LSTR_KEY_DOWN + L"Left", // LSTR_KEY_LEFT + L"Right", // LSTR_KEY_RIGHT + L"Home", // LSTR_KEY_HOME + L"End", // LSTR_KEY_END + L"PageUp", // LSTR_KEY_PAGEUP + L"PageDown", // LSTR_KEY_PAGEDOWN + L"Enter", // LSTR_KEY_RETURN + L"Esc", // LSTR_KEY_ESC + L"Tab", // LSTR_KEY_TAB + L"Backspace", // LSTR_KEY_BACKSPACE + L"Space", // LSTR_KEY_SPACE + L"Insert", // LSTR_KEY_INSERT + L"Del", // LSTR_KEY_DELETE +}; + +// ======================================================================= + +const sal_Unicode** ImplGetLangTab( LanguageType eLang ) +{ + // Sprachtabelle ermitteln + const wchar_t** pLangTab; + //switch ( International::GetNeutralLanguage( eLang ) ) + switch ( eLang ) + { +#if 0 + case LANGUAGE_DANISH: + pLangTab = aImplLangDanishTab; + break; + + case LANGUAGE_DUTCH: + case LANGUAGE_DUTCH_BELGIAN: + pLangTab = aImplLangDutchTab; + break; + + case LANGUAGE_FINNISH: + pLangTab = aImplLangFinnishTab; + break; + + case LANGUAGE_FRENCH: + pLangTab = aImplLangFrenchTab; + break; + + case LANGUAGE_GERMAN: + pLangTab = aImplLangGermanTab; + break; + + case LANGUAGE_ITALIAN: + pLangTab = aImplLangItalianTab; + break; + + case LANGUAGE_NORWEGIAN: + case LANGUAGE_NORWEGIAN_BOKMAL: + pLangTab = aImplLangNorwegianTab; + break; + + case LANGUAGE_PORTUGUESE: + case LANGUAGE_PORTUGUESE_BRAZILIAN: + pLangTab = aImplLangPortugueseTab; + break; + + case LANGUAGE_SPANISH: + pLangTab = aImplLangSpanishTab; + break; + + case LANGUAGE_SWEDISH: + pLangTab = aImplLangSwedishTab; + break; +#endif + default: + pLangTab = aImplLangEnglishTab; + break; + } + + return (const sal_Unicode**)pLangTab; +} diff --git a/vcl/os2/source/app/salshl.cxx b/vcl/os2/source/app/salshl.cxx new file mode 100644 index 000000000000..54957efa58bf --- /dev/null +++ b/vcl/os2/source/app/salshl.cxx @@ -0,0 +1,126 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salshl.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <svpm.h> + +#define _SV_SALSHL_CXX +#include <saldata.hxx> +#include <tools/debug.hxx> + +// ======================================================================= + +SalShlData aSalShlData; + +HMODULE ImplGetModule(void); +static HMODULE mhMod = ImplGetModule(); + +// ======================================================================= + +APIRET APIENTRY DosQueryModFromEIP (HMODULE *phMod, ULONG *pObjNum, + ULONG BuffLen, PCHAR pBuff, ULONG *pOffset, ULONG Address); + +HMODULE ImplGetModule(void) +{ + HMODULE hMod; + ULONG ObjNum; + CHAR Buff[2*_MAX_PATH]; + ULONG Offset; + APIRET rc; + + // get module handle (and name) + rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff, &Offset, (ULONG)ImplGetModule); + if (rc) + return NULL; + // return module handle + aSalShlData.mhMod = hMod; + return hMod; +} + +// ======================================================================= + +HPOINTER ImplLoadSalCursor( int nId ) +{ + DBG_ASSERT( aSalShlData.mhMod, "no DLL instance handle" ); + + HPOINTER hPointer = WinLoadPointer( HWND_DESKTOP, aSalShlData.mhMod, nId ); + + DBG_ASSERT( hPointer, "pointer not found in sal resource" ); +#if OSL_DEBUG_LEVEL>0 + if (!hPointer) + debug_printf( "ImplLoadSalCursor: pointer %d not found in sal resource\n", nId); +#endif + return hPointer; +} + +// ----------------------------------------------------------------------- + +BOOL ImplLoadSalIcon( int nId, HPOINTER& rIcon) +{ + DBG_ASSERT( aSalShlData.mhMod, "no DLL instance handle" ); + + SalData* pSalData = GetSalData(); + + // check the cache first + SalIcon *pSalIcon = pSalData->mpFirstIcon; + while( pSalIcon ) + { + if( pSalIcon->nId != nId ) + pSalIcon = pSalIcon->pNext; + else + { + rIcon = pSalIcon->hIcon; + return (rIcon != 0); + } + } + + // Try at first to load the icons from the application exe file + rIcon = WinLoadPointer( HWND_DESKTOP, NULL, nId ); + if ( !rIcon ) + { + // If the application don't provide these icons, then we try + // to load the icon from the VCL resource + rIcon = WinLoadPointer( HWND_DESKTOP, aSalShlData.mhMod, nId ); + } + + if( rIcon ) + { + // add to icon cache + pSalIcon = new SalIcon(); + pSalIcon->nId = nId; + pSalIcon->hIcon = rIcon; + pSalIcon->pNext = pSalData->mpFirstIcon; + pSalData->mpFirstIcon = pSalIcon; + } + + return (rIcon != 0); +} + +// ======================================================================= + diff --git a/vcl/os2/source/app/saltimer.cxx b/vcl/os2/source/app/saltimer.cxx new file mode 100644 index 000000000000..56552ed59379 --- /dev/null +++ b/vcl/os2/source/app/saltimer.cxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: saltimer.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <svpm.h> + +#define _SV_SALTIMER_CXX +#include <saldata.hxx> +#include <saltimer.h> +#include <salinst.h> + +// ======================================================================= + +// Maximale Periode +#define MAX_SYSPERIOD 65533 +#define IDTIMER 10 + +// ======================================================================= + +void ImplSalStartTimer( ULONG nMS, BOOL bMutex ) +{ + SalData* pSalData = GetSalData(); + + // Periode darf nicht zu gross sein, da OS2 2.11 mit USHORT arbeitet + // Remenber the time of the timer + pSalData->mnTimerMS = nMS; + if ( !bMutex ) + pSalData->mnTimerOrgMS = nMS; + + // Periode darf nicht zu gross sein, da Windows mit USHORT arbeitet + if ( nMS > MAX_SYSPERIOD ) + nMS = MAX_SYSPERIOD; + + // Gibt es einen Timer, dann zerstoren + if ( pSalData->mnTimerId ) + WinStopTimer( pSalData->mhAB, pSalData->mpFirstInstance->mhComWnd, pSalData->mnTimerId ); + + // Make a new timer with new period + pSalData->mnTimerId = WinStartTimer( pSalData->mhAB, pSalData->mpFirstInstance->mhComWnd, IDTIMER, nMS ); + pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS; +} + +// ----------------------------------------------------------------------- + +Os2SalTimer::~Os2SalTimer() +{ +} + +// ----------------------------------------------------------------------- + +void Os2SalTimer::Start( ULONG nMS ) +{ + // Um auf Main-Thread umzuschalten + SalData* pSalData = GetSalData(); + if ( pSalData->mpFirstInstance ) + { + if ( pSalData->mnAppThreadId != GetCurrentThreadId() ) + WinPostMsg( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (MPARAM)nMS ); + else + WinSendMsg( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (MPARAM)nMS ); + } + else + ImplSalStartTimer( nMS, FALSE); +} + +// ----------------------------------------------------------------------- + +void Os2SalTimer::Stop() +{ + SalData* pSalData = GetSalData(); + + // Exitstiert ein Timer, dann diesen zerstoeren + if ( pSalData->mnTimerId ) { + WinStopTimer( pSalData->mhAB, pSalData->mpFirstInstance->mhComWnd, pSalData->mnTimerId ); + pSalData->mnTimerId = 0; + pSalData->mnNextTimerTime = 0; + } +} + +// ----------------------------------------------------------------------- + +void SalTimerProc( HWND, UINT, UINT nId, ULONG ) +{ + SalData* pSalData = GetSalData(); + ImplSVData* pSVData = ImplGetSVData(); + + // Test for MouseLeave + SalTestMouseLeave(); + + bool bRecursive = pSalData->mbInTimerProc && (nId != SALTIMERPROC_RECURSIVE); + if ( pSVData->mpSalTimer && ! bRecursive ) + { + // Try to aquire the mutex. If we don't get the mutex then we + // try this a short time later again. + if ( ImplSalYieldMutexTryToAcquire() ) + { + bRecursive = pSalData->mbInTimerProc && (nId != SALTIMERPROC_RECURSIVE); + if ( pSVData->mpSalTimer && ! bRecursive ) + { + pSalData->mbInTimerProc = TRUE; + pSVData->mpSalTimer->CallCallback(); + pSalData->mbInTimerProc = FALSE; + ImplSalYieldMutexRelease(); + + // Run the timer in the correct time, if we start this + // with a small timeout, because we don't get the mutex + if ( pSalData->mnTimerId && + (pSalData->mnTimerMS != pSalData->mnTimerOrgMS) ) + ImplSalStartTimer( pSalData->mnTimerOrgMS, FALSE ); + } + } + else + ImplSalStartTimer( 10, TRUE ); + } + +} + diff --git a/vcl/os2/source/gdi/makefile.mk b/vcl/os2/source/gdi/makefile.mk new file mode 100644 index 000000000000..0f740490898f --- /dev/null +++ b/vcl/os2/source/gdi/makefile.mk @@ -0,0 +1,60 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7.154.1 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=SV +TARGET=salgdi + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +YD00_CXXFILES= salgdi.cxx \ + salgdi2.cxx \ + salgdi3.cxx \ + salvd.cxx \ + salprn.cxx \ + salbmp.cxx + +SLOFILES= $(SLO)$/salgdi.obj \ + $(SLO)$/salgdi2.obj \ + $(SLO)$/salgdi3.obj \ + $(SLO)$/salvd.obj \ + $(SLO)$/salprn.obj \ + $(SLO)$/salbmp.obj \ + $(SLO)$/os2layout.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/os2/source/gdi/os2layout.cxx b/vcl/os2/source/gdi/os2layout.cxx new file mode 100644 index 000000000000..dffb6a412f9b --- /dev/null +++ b/vcl/os2/source/gdi/os2layout.cxx @@ -0,0 +1,1059 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: os2layout.cxx,v $ + * $Revision: 1.6 $ + * + * 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 <tools/svwin.h> + +#include <rtl/ustring.hxx> +#include <osl/module.h> +#include <salgdi.h> +#include <saldata.hxx> +#include <vcl/sallayout.hxx> + +#ifndef __H_FT2LIB +#include <wingdi.h> +#include <ft2lib.h> +#endif + +#include <cstdio> +#include <malloc.h> + +#ifdef GCP_KERN_HACK + #include <algorithm> +#endif // GCP_KERN_HACK + +// for GetMirroredChar +#include <vcl/svapp.hxx> + +#include <hash_map> +typedef std::hash_map<int,int> IntMap; + +#define DROPPED_OUTGLYPH 0xFFFF + +using namespace rtl; + +// ======================================================================= + +// OS/2 specific physical font instance +class ImplOs2FontEntry : public ImplFontEntry +{ +public: + ImplOs2FontEntry( ImplFontSelectData& ); + ~ImplOs2FontEntry(); + +private: + // TODO: also add HFONT??? Watch out for issues with too many active fonts... + +#ifdef GCP_KERN_HACK +public: + bool HasKernData() const; + void SetKernData( int, const KERNINGPAIRS* ); + int GetKerning( sal_Unicode, sal_Unicode ) const; +private: + KERNINGPAIRS* mpKerningPairs; + int mnKerningPairs; +#endif // GCP_KERN_HACK + +public: + int GetCachedGlyphWidth( int nCharCode ) const; + void CacheGlyphWidth( int nCharCode, int nCharWidth ); +private: + IntMap maWidthMap; +}; + +// ----------------------------------------------------------------------- + +inline void ImplOs2FontEntry::CacheGlyphWidth( int nCharCode, int nCharWidth ) +{ + maWidthMap[ nCharCode ] = nCharWidth; +} + +inline int ImplOs2FontEntry::GetCachedGlyphWidth( int nCharCode ) const +{ + IntMap::const_iterator it = maWidthMap.find( nCharCode ); + if( it == maWidthMap.end() ) + return -1; + return it->second; +} + +// ======================================================================= + +class Os2Layout : public SalLayout +{ +public: + Os2Layout( HDC, const ImplOs2FontData&, ImplOs2FontEntry& ); + virtual void InitFont() const; + void SetFontScale( float f ) { mfFontScale = f; } + float GetFontScale() const { return mfFontScale; } + +protected: + HPS mhPS; // OS2 device handle + FATTRS mhFont; + int mnBaseAdv; // x-offset relative to Layout origin + float mfFontScale; // allows metrics emulation of huge font sizes + + const ImplOs2FontData& mrOs2FontData; + ImplOs2FontEntry& mrOs2FontEntry; +}; + +// ======================================================================= + +class Os2SalLayout : public Os2Layout +{ +public: + Os2SalLayout( HPS, BYTE nCharSet, const ImplOs2FontData&, ImplOs2FontEntry& ); + virtual ~Os2SalLayout(); + + virtual bool LayoutText( ImplLayoutArgs& ); + virtual void AdjustLayout( ImplLayoutArgs& ); + virtual void DrawText( SalGraphics& ) const; + + virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&, + sal_Int32* pGlyphAdvances, int* pCharIndexes ) const; + + virtual long FillDXArray( long* pDXArray ) const; + virtual int GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const; + virtual void GetCaretPositions( int nArraySize, long* pCaretXArray ) const; + + // for glyph+font+script fallback + virtual void MoveGlyph( int nStart, long nNewXPos ); + virtual void DropGlyph( int nStart ); + virtual void Simplify( bool bIsBase ); + +protected: + void Justify( long nNewWidth ); + void ApplyDXArray( const ImplLayoutArgs& ); + +protected: + +private: + int mnGlyphCount; + int mnCharCount; + sal_Unicode* mpOutGlyphs; + int* mpGlyphAdvances; // if possible this is shared with mpGlyphAdvances[] + int* mpGlyphOrigAdvs; + int* mpCharWidths; // map rel char pos to char width + int* mpChars2Glyphs; // map rel char pos to abs glyph pos + int* mpGlyphs2Chars; // map abs glyph pos to abs char pos + bool* mpGlyphRTLFlags; // BiDi status for glyphs: true=>RTL + mutable long mnWidth; + bool mbDisableGlyphs; + + int mnNotdefWidth; + BYTE mnCharSet; + +}; + +// ======================================================================= + +Os2Layout::Os2Layout( HPS hPS, const ImplOs2FontData& rWFD, ImplOs2FontEntry& rWFE ) +: mhPS( hPS ), + mnBaseAdv( 0 ), + mfFontScale( 1.0 ), + mrOs2FontData( rWFD ), + mrOs2FontEntry( rWFE ) +{ + BOOL fSuccess; + fSuccess = Ft2QueryLogicalFont( mhPS, LCID_BASE, NULL, &mhFont, sizeof(FATTRS)); +} + +// ----------------------------------------------------------------------- + +void Os2Layout::InitFont() const +{ + // select fallback level 0 font + APIRET rc = Ft2CreateLogFont( mhPS, NULL, LCID_BASE, (PFATTRS)&mhFont); +} + +// ======================================================================= + +Os2SalLayout::Os2SalLayout( HPS hPS, BYTE nCharSet, + const ImplOs2FontData& rOs2FontData, ImplOs2FontEntry& rOs2FontEntry ) +: Os2Layout( hPS, rOs2FontData, rOs2FontEntry ), + mnGlyphCount( 0 ), + mnCharCount( 0 ), + mpOutGlyphs( NULL ), + mpGlyphAdvances( NULL ), + mpGlyphOrigAdvs( NULL ), + mpCharWidths( NULL ), + mpChars2Glyphs( NULL ), + mpGlyphs2Chars( NULL ), + mpGlyphRTLFlags( NULL ), + mnWidth( 0 ), + mnNotdefWidth( -1 ), + mnCharSet( nCharSet ), + mbDisableGlyphs( false ) +{ + mbDisableGlyphs = true; +} + +// ----------------------------------------------------------------------- + +Os2SalLayout::~Os2SalLayout() +{ + delete[] mpGlyphRTLFlags; + delete[] mpGlyphs2Chars; + delete[] mpChars2Glyphs; + if( mpCharWidths != mpGlyphAdvances ) + delete[] mpCharWidths; + delete[] mpGlyphOrigAdvs; + delete[] mpGlyphAdvances; + delete[] mpOutGlyphs; +} + +// ----------------------------------------------------------------------- + +bool Os2SalLayout::LayoutText( ImplLayoutArgs& rArgs ) +{ + // prepare layout + // TODO: fix case when recyclying old Os2SalLayout object + mbDisableGlyphs |= ((rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) != 0); + mnCharCount = rArgs.mnEndCharPos - rArgs.mnMinCharPos; + + if( !mbDisableGlyphs ) + { + // Win32 glyph APIs have serious problems with vertical layout + // => workaround is to use the unicode methods then + if( rArgs.mnFlags & SAL_LAYOUT_VERTICAL ) + mbDisableGlyphs = true; + else + // use cached value from font face + mbDisableGlyphs = mrOs2FontData.IsGlyphApiDisabled(); + } + + // TODO: use a cached value for bDisableAsianKern from upper layers +#if 0 + if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN ) + { + TEXTMETRICA aTextMetricA; + if( ::GetTextMetricsA( mhDC, &aTextMetricA ) + && !(aTextMetricA.tmPitchAndFamily & TMPF_FIXED_PITCH) ) + rArgs.mnFlags &= ~SAL_LAYOUT_KERNING_ASIAN; + } +#endif + + // layout text + int i, j; + + mnGlyphCount = 0; + bool bVertical = (rArgs.mnFlags & SAL_LAYOUT_VERTICAL) != 0; + + // count the number of chars to process if no RTL run + rArgs.ResetPos(); + bool bHasRTL = false; + while( rArgs.GetNextRun( &i, &j, &bHasRTL ) && !bHasRTL ) + mnGlyphCount += j - i; + + // if there are RTL runs we need room to remember individual BiDi flags + if( bHasRTL ) + { + mpGlyphRTLFlags = new bool[ mnCharCount ]; + for( i = 0; i < mnCharCount; ++i ) + mpGlyphRTLFlags[i] = false; + } + + // rewrite the logical string if needed to prepare for the API calls + const sal_Unicode* pBidiStr = rArgs.mpStr + rArgs.mnMinCharPos; + if( (mnGlyphCount != mnCharCount) || bVertical ) + { + // we need to rewrite the pBidiStr when any of + // - BiDirectional layout + // - vertical layout + // - partial runs (e.g. with control chars or for glyph fallback) + // are involved + sal_Unicode* pRewrittenStr = (sal_Unicode*)alloca( mnCharCount * sizeof(sal_Unicode) ); + pBidiStr = pRewrittenStr; + + // note: glyph to char mapping is relative to first character + mpChars2Glyphs = new int[ mnCharCount ]; + mpGlyphs2Chars = new int[ mnCharCount ]; + for( i = 0; i < mnCharCount; ++i ) + mpChars2Glyphs[i] = mpGlyphs2Chars[i] = -1; + + mnGlyphCount = 0; + rArgs.ResetPos(); + bool bIsRTL = false; + while( rArgs.GetNextRun( &i, &j, &bIsRTL ) ) + { + do + { + // get the next leftmost character in this run + int nCharPos = bIsRTL ? --j : i++; + sal_Unicode cChar = rArgs.mpStr[ nCharPos ]; + + // in the RTL case mirror the character and remember its RTL status + if( bIsRTL ) + { + cChar = ::GetMirroredChar( cChar ); + mpGlyphRTLFlags[ mnGlyphCount ] = true; + } + + // for vertical writing use vertical alternatives + if( bVertical ) + { + sal_Unicode cVert = ::GetVerticalChar( cChar ); + if( cVert ) + cChar = cVert; + } + + // rewrite the original string + // update the mappings between original and rewritten string + pRewrittenStr[ mnGlyphCount ] = cChar; + mpGlyphs2Chars[ mnGlyphCount ] = nCharPos; + mpChars2Glyphs[ nCharPos - rArgs.mnMinCharPos ] = mnGlyphCount; + ++mnGlyphCount; + } while( i < j ); + } + } + + mpOutGlyphs = new sal_Unicode[ mnGlyphCount ]; + mpGlyphAdvances = new int[ mnGlyphCount ]; + + if( rArgs.mnFlags & (SAL_LAYOUT_KERNING_PAIRS | SAL_LAYOUT_KERNING_ASIAN) ) + mpGlyphOrigAdvs = new int[ mnGlyphCount ]; + +#ifndef GCP_KERN_HACK + DWORD nGcpOption = 0; + // enable kerning if requested + if( rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS ) + nGcpOption |= GCP_USEKERNING; +#endif // GCP_KERN_HACK + + LONG lLcid = Ft2QueryCharSet( mhPS); + + for( i = 0; i < mnGlyphCount; ++i ) + mpOutGlyphs[i] = pBidiStr[ i ]; + mnWidth = 0; + for( i = 0; i < mnGlyphCount; ++i ) + { + const sal_Unicode* pCodes = &pBidiStr[i]; + // check for surrogate pairs + if( (pCodes[0] & 0xFC00) == 0xDC00 ) + continue; + bool bSurrogate = ((pCodes[0] & 0xFC00) == 0xD800); + + // get the width of the corresponding code point + int nCharCode = pCodes[0]; + if( bSurrogate ) + nCharCode = 0x10000 + ((pCodes[0] & 0x03FF) << 10) + (pCodes[1] & 0x03FF); + int nGlyphWidth = mrOs2FontEntry.GetCachedGlyphWidth( nCharCode ); + if( nGlyphWidth == -1 ) + { + if (!Ft2QueryStringWidthW( mhPS, (LPWSTR)&pCodes[0], 1, (LONG*)&nGlyphWidth)) + nGlyphWidth = 0; + mrOs2FontEntry.CacheGlyphWidth( nCharCode, nGlyphWidth ); + } + mpGlyphAdvances[ i ] = nGlyphWidth; + mnWidth += nGlyphWidth; + + // remaining codes of surrogate pair get a zero width + if( bSurrogate ) + mpGlyphAdvances[ i+1 ] = 0; + + // check with the font face if glyph fallback is needed + if( mrOs2FontData.HasChar( nCharCode ) ) + continue; + // Type1 charmaps are not complete (or buggy), use FT2 to check again + if (Ft2FontSupportsUnicodeChar( mhPS, lLcid, TRUE, nCharCode)) + continue; + +#if OSL_DEBUG_LEVEL>0 + debug_printf("Os2SalLayout::LayoutText font does not support unicode char\n"); +#endif + // request glyph fallback at this position in the string + bool bRTL = mpGlyphRTLFlags ? mpGlyphRTLFlags[i] : false; + int nCharPos = mpGlyphs2Chars ? mpGlyphs2Chars[i]: i + rArgs.mnMinCharPos; + rArgs.NeedFallback( nCharPos, bRTL ); + if( bSurrogate ) + rArgs.NeedFallback( nCharPos+1, bRTL ); + + if( rArgs.mnFlags & SAL_LAYOUT_FOR_FALLBACK ) + { + // when we already are layouting for glyph fallback + // then a new unresolved glyph is not interesting + mnNotdefWidth = 0; + mpOutGlyphs[i] = DROPPED_OUTGLYPH; + if( mbDisableGlyphs && bSurrogate ) + mpOutGlyphs[i+1] = DROPPED_OUTGLYPH; + } + else + { + if( mnNotdefWidth < 0 ) + { + // get the width of the NotDef glyph + LONG aExtent; + mnNotdefWidth = 0; + if (Ft2QueryStringWidthW( mhPS, (LPWSTR)&rArgs.mpStr[ nCharPos ], 1, &aExtent)) + mnNotdefWidth = aExtent; + } + // use a better NotDef glyph + if( !mbDisableGlyphs ) + mpOutGlyphs[i] = 0; + } + + // replace the current glyph with the NotDef glyph + mnWidth += mnNotdefWidth - mpGlyphAdvances[i]; + mpGlyphAdvances[i] = mnNotdefWidth; + if( mpGlyphOrigAdvs ) + mpGlyphOrigAdvs[i] = mnNotdefWidth; + } + +#ifdef GCP_KERN_HACK + // apply kerning if the layout engine has not yet done it + if( rArgs.mnFlags & (SAL_LAYOUT_KERNING_ASIAN|SAL_LAYOUT_KERNING_PAIRS) ) + { +#else // GCP_KERN_HACK + // apply just asian kerning + if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN ) + { + if( !(rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS) ) +#endif // GCP_KERN_HACK + for( i = 0; i < mnGlyphCount; ++i ) + mpGlyphOrigAdvs[i] = mpGlyphAdvances[i]; + + // #99658# also apply asian kerning on the substring border + int nLen = mnGlyphCount; + if( rArgs.mnMinCharPos + nLen < rArgs.mnLength ) + ++nLen; + for( i = 1; i < nLen; ++i ) + { +#ifdef GCP_KERN_HACK + if( rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS ) + { + int nKernAmount = mrOs2FontEntry.GetKerning( pBidiStr[i-1], pBidiStr[i] ); + mpGlyphAdvances[ i-1 ] += nKernAmount; + mnWidth += nKernAmount; + } + else if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN ) +#endif // GCP_KERN_HACK + + if( (0x3000 == (0xFF00 & pBidiStr[i-1])) + && (0x3000 == (0xFF00 & pBidiStr[i])) ) + { + long nKernFirst = +CalcAsianKerning( pBidiStr[i-1], true, bVertical ); + long nKernNext = -CalcAsianKerning( pBidiStr[i], false, bVertical ); + + long nDelta = (nKernFirst < nKernNext) ? nKernFirst : nKernNext; + if( nDelta<0 && nKernFirst!=0 && nKernNext!=0 ) + { + nDelta = (nDelta * mpGlyphAdvances[i-1] + 2) / 4; + mpGlyphAdvances[i-1] += nDelta; + mnWidth += nDelta; + } + } + } + } + + // calculate virtual char widths + if( !mpGlyphs2Chars ) + mpCharWidths = mpGlyphAdvances; + else + { + mpCharWidths = new int[ mnCharCount ]; + for( i = 0; i < mnCharCount; ++i ) + mpCharWidths[ i ] = 0; + for( i = 0; i < mnGlyphCount; ++i ) + { + int j = mpGlyphs2Chars[ i ] - rArgs.mnMinCharPos; + if( j >= 0 ) + mpCharWidths[ j ] += mpGlyphAdvances[ i ]; + } + } + + // scale layout metrics if needed + if( mfFontScale != 1.0 ) + { + mnWidth *= mfFontScale; + mnBaseAdv *= mfFontScale; + for( i = 0; i < mnCharCount; ++i ) + mpCharWidths[ i ] *= mfFontScale; + if( mpGlyphAdvances != mpCharWidths ) + for( i = 0; i < mnGlyphCount; ++i ) + mpGlyphAdvances[ i ] *= mfFontScale; + if( mpGlyphOrigAdvs && (mpGlyphOrigAdvs != mpGlyphAdvances) ) + for( i = 0; i < mnGlyphCount; ++i ) + mpGlyphOrigAdvs[ i ] *= mfFontScale; + } + + return true; +} + +// ----------------------------------------------------------------------- + +int Os2SalLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int& nStart, + sal_Int32* pGlyphAdvances, int* pCharIndexes ) const +{ + // return zero if no more glyph found + if( nStart >= mnGlyphCount ) + return 0; + + // calculate glyph position relative to layout base + // TODO: avoid for nStart!=0 case by reusing rPos + long nXOffset = mnBaseAdv; + for( int i = 0; i < nStart; ++i ) + nXOffset += mpGlyphAdvances[ i ]; + + // calculate absolute position in pixel units + Point aRelativePos( nXOffset, 0 ); + rPos = GetDrawPosition( aRelativePos ); + + int nCount = 0; + while( nCount < nLen ) + { + // update return values {nGlyphIndex,nCharPos,nGlyphAdvance} + long nGlyphIndex = mpOutGlyphs[ nStart ]; + if( mbDisableGlyphs ) + { + if( mnLayoutFlags & SAL_LAYOUT_VERTICAL ) + { + sal_Unicode cChar = (sal_Unicode)(nGlyphIndex & GF_IDXMASK); +#ifdef GNG_VERT_HACK + if( mrOs2FontData.HasGSUBstitutions( mhPS ) + && mrOs2FontData.IsGSUBstituted( cChar ) ) + nGlyphIndex |= GF_ROTL | GF_GSUB; + else +#endif // GNG_VERT_HACK + { + nGlyphIndex |= GetVerticalFlags( cChar ); + if( !(nGlyphIndex & GF_ROTMASK) ) + nGlyphIndex |= GF_VERT; + } + } + nGlyphIndex |= GF_ISCHAR; + } + ++nCount; + *(pGlyphs++) = nGlyphIndex; + if( pGlyphAdvances ) + *(pGlyphAdvances++) = mpGlyphAdvances[ nStart ]; + if( pCharIndexes ) + { + int nCharPos; + if( !mpGlyphs2Chars ) + nCharPos = nStart + mnMinCharPos; + else + nCharPos = mpGlyphs2Chars[nStart]; + *(pCharIndexes++) = nCharPos; + } + + // stop at last glyph + if( ++nStart >= mnGlyphCount ) + break; + + // stop when next x-position is unexpected + if( !pGlyphAdvances && mpGlyphOrigAdvs ) + if( mpGlyphAdvances[nStart-1] != mpGlyphOrigAdvs[nStart-1] ) + break; + } + + return nCount; +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::DrawText( SalGraphics& rGraphics ) const +{ + if( mnGlyphCount <= 0 ) + return; + + Point aPos = GetDrawPosition( Point( mnBaseAdv, 0 ) ); + POINTL aPt; + APIRET rc; + + aPt.x = aPos.X(); + aPt.y = static_cast<Os2SalGraphics&>(rGraphics).mnHeight - aPos.Y(); + + // ft2lib doesn't work with printer hps, so we fallback to codepage printing + // until cp1200 support will work. + if (static_cast<Os2SalGraphics&>(rGraphics).mbPrinter) { + // convert to codepage + ByteString str( mpOutGlyphs, gsl_getSystemTextEncoding() ); + // gliph size is not recalculated, so it could be wrong! + rc = Ft2CharStringPosAtA( static_cast<Os2SalGraphics&>(rGraphics).mhPS, + &aPt, NULL, CHS_VECTOR, mnGlyphCount, (PSZ)str.GetBuffer(), + (LONG*)mpGlyphAdvances, 0); + } else { + // try unicode rendering to screen + rc = Ft2CharStringPosAtW( static_cast<Os2SalGraphics&>(rGraphics).mhPS, + &aPt, NULL, CHS_VECTOR, mnGlyphCount, (LPWSTR)mpOutGlyphs, + (LONG*)mpGlyphAdvances, 0); + if (rc == GPI_ERROR) { + // if *W fails, convert to codepage and use *A (fallback to GPI into ft2) + ByteString str( mpOutGlyphs, gsl_getSystemTextEncoding() ); +#if OSL_DEBUG_LEVEL>10 + debug_printf("Os2SalLayout::DrawText HPS %08x PosAtW failed '%s'!\n",static_cast<Os2SalGraphics&>(rGraphics).mhPS,str.GetBuffer()); +#endif + // gliph size is not recalculated, so it could be wrong! + rc = Ft2CharStringPosAtA( static_cast<Os2SalGraphics&>(rGraphics).mhPS, + &aPt, NULL, CHS_VECTOR, mnGlyphCount, (PSZ)str.GetBuffer(), + (LONG*)mpGlyphAdvances, 0); + } + } +} + +// ----------------------------------------------------------------------- + +long Os2SalLayout::FillDXArray( long* pDXArray ) const +{ + if( !mnWidth ) + { + long mnWidth = mnBaseAdv; + for( int i = 0; i < mnGlyphCount; ++i ) + mnWidth += mpGlyphAdvances[ i ]; + } + + if( pDXArray != NULL ) + { + for( int i = 0; i < mnCharCount; ++i ) + pDXArray[ i ] = mpCharWidths[ i ]; + } + + return mnWidth; +} + +// ----------------------------------------------------------------------- + +int Os2SalLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const +// NOTE: the nFactor is used to prevent rounding errors for small nCharExtra values +{ + if( mnWidth ) + if( (mnWidth * nFactor + mnCharCount * nCharExtra) <= nMaxWidth ) + return STRING_LEN; + + long nExtraWidth = mnBaseAdv * nFactor; + for( int n = 0; n < mnCharCount; ++n ) + { + // skip unused characters + if( mpChars2Glyphs && (mpChars2Glyphs[n] < 0) ) + continue; + // add char widths until max + nExtraWidth += mpCharWidths[ n ] * nFactor; + if( nExtraWidth >= nMaxWidth ) + return (mnMinCharPos + n); + nExtraWidth += nCharExtra; + } + + return STRING_LEN; +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::GetCaretPositions( int nMaxIdx, long* pCaretXArray ) const +{ + long nXPos = mnBaseAdv; + + if( !mpGlyphs2Chars ) + { + for( int i = 0; i < nMaxIdx; i += 2 ) + { + pCaretXArray[ i ] = nXPos; + nXPos += mpGlyphAdvances[ i>>1 ]; + pCaretXArray[ i+1 ] = nXPos; + } + } + else + { + int i; + for( i = 0; i < nMaxIdx; ++i ) + pCaretXArray[ i ] = -1; + + // assign glyph positions to character positions + for( i = 0; i < mnGlyphCount; ++i ) + { + int nCurrIdx = mpGlyphs2Chars[ i ] - mnMinCharPos; + long nXRight = nXPos + mpCharWidths[ nCurrIdx ]; + nCurrIdx *= 2; + if( !(mpGlyphRTLFlags && mpGlyphRTLFlags[i]) ) + { + // normal positions for LTR case + pCaretXArray[ nCurrIdx ] = nXPos; + pCaretXArray[ nCurrIdx+1 ] = nXRight; + } + else + { + // reverse positions for RTL case + pCaretXArray[ nCurrIdx ] = nXRight; + pCaretXArray[ nCurrIdx+1 ] = nXPos; + } + nXPos += mpGlyphAdvances[ i ]; + } + } +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::Justify( long nNewWidth ) +{ + long nOldWidth = mnWidth; + mnWidth = nNewWidth; + + if( mnGlyphCount <= 0 ) + return; + + if( nNewWidth == nOldWidth ) + return; + + // the rightmost glyph cannot be stretched + const int nRight = mnGlyphCount - 1; + nOldWidth -= mpGlyphAdvances[ nRight ]; + nNewWidth -= mpGlyphAdvances[ nRight ]; + + // count stretchable glyphs + int nStretchable = 0, i; + for( i = 0; i < nRight; ++i ) + if( mpGlyphAdvances[i] >= 0 ) + ++nStretchable; + + // stretch these glyphs + int nDiffWidth = nNewWidth - nOldWidth; + for( i = 0; (i < nRight) && (nStretchable > 0); ++i ) + { + if( mpGlyphAdvances[i] <= 0 ) + continue; + int nDeltaWidth = nDiffWidth / nStretchable; + mpGlyphAdvances[i] += nDeltaWidth; + --nStretchable; + nDiffWidth -= nDeltaWidth; + } +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::AdjustLayout( ImplLayoutArgs& rArgs ) +{ + SalLayout::AdjustLayout( rArgs ); + + // adjust positions if requested + if( rArgs.mpDXArray ) + ApplyDXArray( rArgs ); + else if( rArgs.mnLayoutWidth ) + Justify( rArgs.mnLayoutWidth ); + else + return; + + // recalculate virtual char widths if they were changed + if( mpCharWidths != mpGlyphAdvances ) + { + int i; + if( !mpGlyphs2Chars ) + { + // standard LTR case + for( i = 0; i < mnGlyphCount; ++i ) + mpCharWidths[ i ] = mpGlyphAdvances[ i ]; + } + else + { + // BiDi or complex case + for( i = 0; i < mnCharCount; ++i ) + mpCharWidths[ i ] = 0; + for( i = 0; i < mnGlyphCount; ++i ) + { + int j = mpGlyphs2Chars[ i ] - rArgs.mnMinCharPos; + if( j >= 0 ) + mpCharWidths[ j ] += mpGlyphAdvances[ i ]; + } + } + } +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::ApplyDXArray( const ImplLayoutArgs& rArgs ) +{ + // try to avoid disturbance of text flow for LSB rounding case; + const long* pDXArray = rArgs.mpDXArray; + + int i = 0; + long nOldWidth = mnBaseAdv; + for(; i < mnCharCount; ++i ) + { + int j = !mpChars2Glyphs ? i : mpChars2Glyphs[i]; + if( j >= 0 ) + { + nOldWidth += mpGlyphAdvances[ j ]; + int nDiff = nOldWidth - pDXArray[ i ]; + + // disabled because of #104768# + // works great for static text, but problems when typing + // if( nDiff>+1 || nDiff<-1 ) + // only bother with changing anything when something moved + if( nDiff != 0 ) + break; + } + } + if( i >= mnCharCount ) + return; + + if( !mpGlyphOrigAdvs ) + { + mpGlyphOrigAdvs = new int[ mnGlyphCount ]; + for( i = 0; i < mnGlyphCount; ++i ) + mpGlyphOrigAdvs[ i ] = mpGlyphAdvances[ i ]; + } + + mnWidth = mnBaseAdv; + for( i = 0; i < mnCharCount; ++i ) + { + int j = !mpChars2Glyphs ? i : mpChars2Glyphs[i]; + if( j >= 0 ) + mpGlyphAdvances[j] = pDXArray[i] - mnWidth; + mnWidth = pDXArray[i]; + } +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::MoveGlyph( int nStart, long nNewXPos ) +{ + if( nStart > mnGlyphCount ) + return; + + // calculate the current x-position of the requested glyph + // TODO: cache absolute positions + int nXPos = mnBaseAdv; + for( int i = 0; i < nStart; ++i ) + nXPos += mpGlyphAdvances[i]; + + // calculate the difference to the current glyph position + int nDelta = nNewXPos - nXPos; + + // adjust the width of the layout if it was already cached + if( mnWidth ) + mnWidth += nDelta; + + // depending on whether the requested glyph is leftmost in the layout + // adjust either the layout's or the requested glyph's relative position + if( nStart > 0 ) + mpGlyphAdvances[ nStart-1 ] += nDelta; + else + mnBaseAdv += nDelta; +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::DropGlyph( int nStart ) +{ + mpOutGlyphs[ nStart ] = DROPPED_OUTGLYPH; +} + +// ----------------------------------------------------------------------- + +void Os2SalLayout::Simplify( bool bIsBase ) +{ + // return early if no glyph has been dropped + int i = mnGlyphCount; + while( (--i >= 0) && (mpOutGlyphs[ i ] != DROPPED_OUTGLYPH) ); + if( i < 0 ) + return; + + // convert the layout to a sparse layout if it is not already + if( !mpGlyphs2Chars ) + { + mpGlyphs2Chars = new int[ mnGlyphCount ]; + mpCharWidths = new int[ mnCharCount ]; + // assertion: mnGlyphCount == mnCharCount + for( int k = 0; k < mnGlyphCount; ++k ) + { + mpGlyphs2Chars[ k ] = mnMinCharPos + k; + mpCharWidths[ k ] = mpGlyphAdvances[ k ]; + } + } + + // remove dropped glyphs that are rightmost in the layout + for( i = mnGlyphCount; --i >= 0; ) + { + if( mpOutGlyphs[ i ] != DROPPED_OUTGLYPH ) + break; + if( mnWidth ) + mnWidth -= mpGlyphAdvances[ i ]; + int nRelCharPos = mpGlyphs2Chars[ i ] - mnMinCharPos; + if( nRelCharPos >= 0 ) + mpCharWidths[ nRelCharPos ] = 0; + } + mnGlyphCount = i + 1; + + // keep original glyph widths around + if( !mpGlyphOrigAdvs ) + { + mpGlyphOrigAdvs = new int[ mnGlyphCount ]; + for( int k = 0; k < mnGlyphCount; ++k ) + mpGlyphOrigAdvs[ k ] = mpGlyphAdvances[ k ]; + } + + // remove dropped glyphs inside the layout + int nNewGC = 0; + for( i = 0; i < mnGlyphCount; ++i ) + { + if( mpOutGlyphs[ i ] == DROPPED_OUTGLYPH ) + { + // adjust relative position to last valid glyph + int nDroppedWidth = mpGlyphAdvances[ i ]; + mpGlyphAdvances[ i ] = 0; + if( nNewGC > 0 ) + mpGlyphAdvances[ nNewGC-1 ] += nDroppedWidth; + else + mnBaseAdv += nDroppedWidth; + + // zero the virtual char width for the char that has a fallback + int nRelCharPos = mpGlyphs2Chars[ i ] - mnMinCharPos; + if( nRelCharPos >= 0 ) + mpCharWidths[ nRelCharPos ] = 0; + } + else + { + if( nNewGC != i ) + { + // rearrange the glyph array to get rid of the dropped glyph + mpOutGlyphs[ nNewGC ] = mpOutGlyphs[ i ]; + mpGlyphAdvances[ nNewGC ] = mpGlyphAdvances[ i ]; + mpGlyphOrigAdvs[ nNewGC ] = mpGlyphOrigAdvs[ i ]; + mpGlyphs2Chars[ nNewGC ] = mpGlyphs2Chars[ i ]; + } + ++nNewGC; + } + } + + mnGlyphCount = nNewGC; + if( mnGlyphCount <= 0 ) + mnWidth = mnBaseAdv = 0; +} + +// ======================================================================= + +SalLayout* Os2SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel ) +{ + Os2SalLayout* pLayout = NULL; + DBG_ASSERT( mpOs2FontEntry[nFallbackLevel], "WinSalGraphics mpWinFontEntry==NULL"); + + const ImplOs2FontData& rFontFace = *mpOs2FontData[ nFallbackLevel ]; + ImplOs2FontEntry& rFontInstance = *mpOs2FontEntry[ nFallbackLevel ]; + + { +#ifdef GCP_KERN_HACK + if( (rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS) && !rFontInstance.HasKernData() ) + { + // TODO: directly cache kerning info in the rFontInstance + // TODO: get rid of kerning methods+data in WinSalGraphics object + GetKernPairs( 0, NULL ); + rFontInstance.SetKernData( mnFontKernPairCount, mpFontKernPairs ); + } +#endif // GCP_KERN_HACK + + //BYTE eCharSet = ANSI_CHARSET; + //if( mpLogFont ) + // eCharSet = mpLogFont->lfCharSet; + pLayout = new Os2SalLayout( mhPS, 0, rFontFace, rFontInstance ); + } + + if( mfFontScale != 1.0 ) + pLayout->SetFontScale( mfFontScale ); + + return pLayout; +} + +// ======================================================================= + +ImplOs2FontEntry::ImplOs2FontEntry( ImplFontSelectData& rFSD ) +: ImplFontEntry( rFSD ), + maWidthMap( 512 ) +#ifdef GCP_KERN_HACK + ,mpKerningPairs( NULL ) + ,mnKerningPairs( -1 ) +#endif // GCP_KERN_HACK +{ +} + +// ----------------------------------------------------------------------- + +ImplOs2FontEntry::~ImplOs2FontEntry() +{ +#ifdef GCP_KERN_HACK + delete[] mpKerningPairs; +#endif // GCP_KERN_HACK +} + +// ----------------------------------------------------------------------- + +#ifdef GCP_KERN_HACK +bool ImplOs2FontEntry::HasKernData() const +{ + return (mnKerningPairs >= 0); +} + +// ----------------------------------------------------------------------- + +void ImplOs2FontEntry::SetKernData( int nPairCount, const KERNINGPAIRS* pPairData ) +{ + mnKerningPairs = nPairCount; + mpKerningPairs = new KERNINGPAIRS[ mnKerningPairs ]; + ::memcpy( mpKerningPairs, (const void*)pPairData, nPairCount*sizeof(KERNINGPAIRS) ); +} + +// ----------------------------------------------------------------------- + +int ImplOs2FontEntry::GetKerning( sal_Unicode cLeft, sal_Unicode cRight ) const +{ + int nKernAmount = 0; + if( mpKerningPairs ) + { + const KERNINGPAIRS aRefPair = { cLeft, cRight, 0 }; + const KERNINGPAIRS* pFirstPair = mpKerningPairs; + const KERNINGPAIRS* pEndPair = mpKerningPairs + mnKerningPairs; + const KERNINGPAIRS* pPair = std::lower_bound( pFirstPair, + pEndPair, aRefPair, ImplCmpKernData ); + if( (pPair != pEndPair) + && (pPair->sFirstChar == aRefPair.sFirstChar) + && (pPair->sSecondChar == aRefPair.sSecondChar) ) + nKernAmount = pPair->lKerningAmount; + } + + return nKernAmount; +} +#endif // GCP_KERN_HACK + +// ======================================================================= + +ImplFontData* ImplOs2FontData::Clone() const +{ + if( mpUnicodeMap ) + mpUnicodeMap->AddReference(); + ImplFontData* pClone = new ImplOs2FontData( *this ); + return pClone; +} + +// ----------------------------------------------------------------------- + +ImplFontEntry* ImplOs2FontData::CreateFontInstance( ImplFontSelectData& rFSD ) const +{ + //debug_printf("ImplOs2FontData::CreateFontInstance\n"); + ImplFontEntry* pEntry = new ImplOs2FontEntry( rFSD ); + return pEntry; +} + +// ======================================================================= + diff --git a/vcl/os2/source/gdi/salbmp.cxx b/vcl/os2/source/gdi/salbmp.cxx new file mode 100644 index 000000000000..a281f615be55 --- /dev/null +++ b/vcl/os2/source/gdi/salbmp.cxx @@ -0,0 +1,740 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salbmp.cxx,v $ + * $Revision: 1.7 $ + * + * 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 <svpm.h> + +#define _SV_SALBMP_CXX +#include <rtl/alloc.h> +#include <vcl/salbtype.hxx> +#include <salgdi.h> +#include <saldata.hxx> +#include <salbmp.h> +#include <vcl/bitmap.hxx> // for BitmapSystemData +#include <string.h> + +#ifndef __H_FT2LIB +#include <wingdi.h> +#include <ft2lib.h> +#endif + +// ----------- +// - Inlines - +// ----------- + +inline void ImplSetPixel4( const HPBYTE pScanline, long nX, const BYTE cIndex ) +{ + BYTE& rByte = pScanline[ nX >> 1 ]; + + ( nX & 1 ) ? ( rByte &= 0xf0, rByte |= ( cIndex & 0x0f ) ) : + ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) ); +} + +// ------------- +// - Os2SalBitmap - +// ------------- + +Os2SalBitmap::Os2SalBitmap() : + mhDIB ( 0 ), + mhDIB1Subst ( 0 ), + mhDDB ( 0 ), + mnBitCount ( 0 ) +{ +} + +// ------------------------------------------------------------------ + +Os2SalBitmap::~Os2SalBitmap() +{ + Destroy(); +} + +// ------------------------------------------------------------------ + +bool Os2SalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle ) +{ + BOOL bRet = TRUE; + + if( bDIB ) + mhDIB = (HANDLE) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap ); + else + mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap ); + + if( mhDIB ) + { + // bitmap-header is the beginning of memory block + PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) mhDIB; + + maSize = Size( pBIH->cx, pBIH->cy ); + mnBitCount = pBIH->cBitCount; + + if( mnBitCount ) + mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24; + } + else if( mhDDB ) + { + BITMAPINFOHEADER2 aDDBInfoHeader; + + aDDBInfoHeader.cbFix = sizeof( aDDBInfoHeader ); + + if( GpiQueryBitmapInfoHeader( mhDDB, &aDDBInfoHeader ) ) + { + maSize = Size( aDDBInfoHeader.cx, aDDBInfoHeader.cy ); + mnBitCount = aDDBInfoHeader.cPlanes * aDDBInfoHeader.cBitCount; + + if( mnBitCount ) + { + mnBitCount = ( mnBitCount <= 1 ) ? 1 : + ( mnBitCount <= 4 ) ? 4 : + ( mnBitCount <= 8 ) ? 8 : 24; + } + } + else + { + mhDDB = 0; + bRet = FALSE; + } + + } + else + bRet = FALSE; + + return bRet; +} + +// ------------------------------------------------------------------ + +bool Os2SalBitmap::Create( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal ) +{ + bool bRet = FALSE; + + mhDIB = ImplCreateDIB( rSize, nBitCount, rPal ); + + if( mhDIB ) + { + maSize = rSize; + mnBitCount = nBitCount; + bRet = TRUE; + } + + return bRet; +} + +// ------------------------------------------------------------------ + +bool Os2SalBitmap::Create( const SalBitmap& rSSalBitmap ) +{ + bool bRet = FALSE; + const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap); + + if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB ) + { + HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB, + rSalBitmap.mhDIB != 0 ); + + if( hNewHdl ) + { + if( rSalBitmap.mhDIB ) + mhDIB = (HANDLE) hNewHdl; + else if( rSalBitmap.mhDDB ) + mhDDB = (HBITMAP) hNewHdl; + + maSize = rSalBitmap.maSize; + mnBitCount = rSalBitmap.mnBitCount; + bRet = TRUE; + } + } + + return bRet; +} + +// ------------------------------------------------------------------ + +bool Os2SalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics ) +{ + bool bRet = FALSE; + const Os2SalBitmap& rSalBmp = static_cast<const Os2SalBitmap&>(rSSalBmp); + Os2SalGraphics* pGraphics = static_cast<Os2SalGraphics*>(pSGraphics); + + if( rSalBmp.mhDIB ) + { + HPS hPS = pGraphics->mhPS; + HBITMAP hNewDDB; + BITMAPINFOHEADER2 aInfoHeader; + const Size aSize( rSalBmp.GetSize() ); + long nFormat[ 2 ]; + + memset( &aInfoHeader, 0, sizeof( aInfoHeader ) ); + aInfoHeader.cbFix = 16; + aInfoHeader.cx = aSize.Width(); + aInfoHeader.cy = aSize.Height(); + + GpiQueryDeviceBitmapFormats( hPS, 2L, (PLONG) &nFormat ); + aInfoHeader.cPlanes = nFormat[ 0 ]; + aInfoHeader.cBitCount = nFormat[ 1 ]; + + // ! wegen Postscript-Treiber + if( !aInfoHeader.cBitCount ) + aInfoHeader.cBitCount = 24; + else if( ( aInfoHeader.cPlanes == 1 ) && ( aInfoHeader.cBitCount == 1 ) ) + aInfoHeader.cBitCount = 4; + + // BitCount == 1 ist wegen aller moeglichen Treiberfehler nicht moeglich + if( rSalBmp.GetBitCount() == 1 ) + { + HANDLE hTmp = ImplCreateDIB4FromDIB1( rSalBmp.mhDIB ); + PBYTE pBits = (PBYTE) hTmp + *(ULONG*) hTmp + ImplGetDIBColorCount( hTmp ) * sizeof( RGB2 ); + + hNewDDB = GpiCreateBitmap( hPS, &aInfoHeader, CBM_INIT, pBits, (PBITMAPINFO2) hTmp ); + rtl_freeMemory( (void*)hTmp ); + } + else + { + PBYTE pBits = (PBYTE) rSalBmp.mhDIB + *(ULONG*) rSalBmp.mhDIB + ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGB2 ); + hNewDDB = GpiCreateBitmap( hPS, &aInfoHeader, CBM_INIT, pBits, (PBITMAPINFO2) rSalBmp.mhDIB ); + } + + aInfoHeader.cbFix = sizeof( aInfoHeader ); + + if( hNewDDB && GpiQueryBitmapInfoHeader( hNewDDB, &aInfoHeader ) ) + { + mhDDB = hNewDDB; + maSize = Size( aInfoHeader.cx, aInfoHeader.cy ); + mnBitCount = aInfoHeader.cPlanes * aInfoHeader.cBitCount; + + if( mnBitCount ) + { + mnBitCount = ( mnBitCount <= 1 ) ? 1 : + ( mnBitCount <= 4 ) ? 4 : + ( mnBitCount <= 8 ) ? 8 : 24; + } + + bRet = TRUE; + } + else if( hNewDDB ) + GpiDeleteBitmap( hNewDDB ); + } + + return bRet; +} + +// ------------------------------------------------------------------ + +bool Os2SalBitmap::Create( const SalBitmap& rSSalBmp, USHORT nNewBitCount ) +{ + bool bRet = FALSE; + const Os2SalBitmap& rSalBmp = static_cast<const Os2SalBitmap&>(rSSalBmp); + + if( rSalBmp.mhDDB ) + { + mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() ); + + if( mhDIB ) + { + // bitmap-header is the beginning of memory block + PBITMAPINFO2 pBI = (PBITMAPINFO2) mhDIB; + const int nLines = (int) rSalBmp.maSize.Height(); + PBYTE pBits = (PBYTE) pBI + *(ULONG*) pBI + ImplGetDIBColorCount( mhDIB ) * sizeof( RGB2 ); + SIZEL aSizeL = { rSalBmp.maSize.Width(), nLines }; + HAB hAB = GetSalData()->mhAB; + DEVOPENSTRUC aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + HDC hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 ); + HPS hMemPS = Ft2CreatePS( hAB, hMemDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS ); + HBITMAP hMemOld = (HBITMAP) Ft2SetBitmap( hMemPS, rSalBmp.mhDDB ); + + if( GpiQueryBitmapBits( hMemPS, 0, nLines, pBits, pBI ) == nLines ) + { + maSize = rSalBmp.maSize; + mnBitCount = nNewBitCount; + bRet = TRUE; + } + else + { + rtl_freeMemory( (void*)mhDIB ); + mhDIB = 0; + } + + Ft2SetBitmap( hMemPS, hMemOld ); + Ft2DestroyPS( hMemPS ); + DevCloseDC( hMemDC ); + } + } + + return bRet; +} + +// ------------------------------------------------------------------ + +void Os2SalBitmap::Destroy() +{ + if( mhDIB ) + rtl_freeMemory( (void*)mhDIB ); + else if( mhDDB ) + GpiDeleteBitmap( mhDDB ); + + if( mhDIB1Subst ) + { + rtl_freeMemory( (void*)mhDIB1Subst ); + mhDIB1Subst = NULL; + } + + maSize = Size(); + mnBitCount = 0; +} + +// ------------------------------------------------------------------ + +void Os2SalBitmap::ImplReplacehDIB1Subst( HANDLE hDIB1Subst ) +{ + if( mhDIB1Subst ) + rtl_freeMemory( (void*)mhDIB1Subst ); + + mhDIB1Subst = hDIB1Subst; +} + +// ------------------------------------------------------------------ + +USHORT Os2SalBitmap::ImplGetDIBColorCount( HANDLE hDIB ) +{ + USHORT nColors = 0; + + if( hDIB ) + { + // bitmap infos can be found at the beginning of the memory + PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) hDIB; + + if( pBIH->cBitCount <= 8 ) + { + if( pBIH->cclrUsed ) + nColors = (USHORT) pBIH->cclrUsed; + else + nColors = 1 << pBIH->cBitCount; + } + } + + return nColors; +} + +// ------------------------------------------------------------------ + +HANDLE Os2SalBitmap::ImplCreateDIB( const Size& rSize, USHORT nBits, const BitmapPalette& rPal ) +{ + DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 24, "Unsupported BitCount!" ); + + HANDLE hDIB = 0; + + if ( rSize.Width() && rSize.Height() && ( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 24 ) ) + { + const ULONG nImageSize = AlignedWidth4Bytes( nBits * rSize.Width() ) * rSize.Height(); + const USHORT nColors = ( nBits <= 8 ) ? ( 1 << nBits ) : 0; + + hDIB = (HANDLE) rtl_allocateZeroMemory( sizeof( BITMAPINFOHEADER2 ) + nColors * sizeof( RGB2 ) + nImageSize ); + + if( hDIB ) + { + // bitmap infos can be found at the beginning of the memory + PBITMAPINFO2 pBI = (PBITMAPINFO2) hDIB; + PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) pBI; + + pBIH->cbFix = sizeof( BITMAPINFOHEADER2 ); + pBIH->cx = rSize.Width(); + pBIH->cy = rSize.Height(); + pBIH->cPlanes = 1; + pBIH->cBitCount = nBits; + pBIH->ulCompression = BCA_UNCOMP; // BI_RGB; + pBIH->cbImage = nImageSize; + pBIH->cxResolution = 0; + pBIH->cyResolution = 0; + pBIH->cclrUsed = 0; + pBIH->cclrImportant = 0; + + // Rest auf 0 setzen + memset( (PBYTE) &pBIH->usUnits, 0, (PBYTE) pBI->argbColor - (PBYTE) &pBIH->usUnits ); + + if( nColors ) + { + const USHORT nMinCount = Min( nColors, rPal.GetEntryCount() ); + + if( nMinCount ) + memcpy( pBI->argbColor, rPal.ImplGetColorBuffer(), nMinCount * sizeof( RGB2 ) ); + } + } + } + + return hDIB; +} + +// ------------------------------------------------------------------ + +HANDLE Os2SalBitmap::ImplCreateDIB4FromDIB1( HANDLE hDIB1 ) +{ + PBITMAPINFO2 pBI = (PBITMAPINFO2) hDIB1; + PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) pBI; + PBYTE pBits = (PBYTE) pBI + *(ULONG*) pBIH + Os2SalBitmap::ImplGetDIBColorCount( hDIB1 ) * sizeof( RGB2 ); + ULONG nWidth = pBIH->cx, nHeight = pBIH->cy; + ULONG nAligned = AlignedWidth4Bytes( nWidth ); + ULONG nAligned4 = AlignedWidth4Bytes( nWidth << 2 ); + ULONG nSize4 = sizeof( BITMAPINFOHEADER2 ) + ( sizeof( RGB2 ) << 4 ) + nAligned4 * nHeight; + PBYTE pDIB4 = (PBYTE) rtl_allocateZeroMemory( nSize4 ); + PBITMAPINFO2 pBI4 = (PBITMAPINFO2) pDIB4; + PBITMAPINFOHEADER2 pBIH4 = (PBITMAPINFOHEADER2) pBI4; + BYTE aMap[ 4 ] = { 0x00, 0x01, 0x10, 0x11 }; + + memset( pBIH4, 0, sizeof( BITMAPINFOHEADER2 ) ); + pBIH4->cbFix = sizeof( BITMAPINFOHEADER2 ); + pBIH4->cx = nWidth; + pBIH4->cy = nHeight; + pBIH4->cPlanes = 1; + pBIH4->cBitCount = 4; + + // die ersten beiden Eintraege der 1Bit-Farbtabelle kopieren + memcpy( pBI4->argbColor, pBI->argbColor, sizeof( RGB2 ) << 1 ); + + PBYTE pBits4 = (PBYTE) pBI4 + *(ULONG*) pBIH4 + ( sizeof( RGB2 ) << 4 ); + + // 4Bit-DIB-Bilddaten setzen + for( ULONG nY = 0UL; nY < nHeight; nY++ ) + { + PBYTE pTmp = pBits; pBits += nAligned; + PBYTE pTmp4 = pBits4; pBits4 += nAligned4; + + for( ULONG nX = 0UL; nX < nWidth; nX += 8UL ) + { + *pTmp4++ = aMap[ ( *pTmp >> 6 ) & 3 ]; + *pTmp4++ = aMap[ ( *pTmp >> 4 ) & 3 ]; + *pTmp4++ = aMap[ ( *pTmp >> 2 ) & 3 ]; + *pTmp4++ = aMap[ *pTmp++ & 3 ]; + } + } + + return (HANDLE) pDIB4; +} + +// ------------------------------------------------------------------ + +HANDLE Os2SalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, BOOL bDIB ) +{ + HANDLE hCopy = 0; + + if( bDIB && hHdl ) + { + PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) hHdl; + const ULONG nSize = sizeof( BITMAPINFOHEADER2 ) + + ImplGetDIBColorCount( hHdl ) * sizeof( RGB2 ) + + ( pBIH->cbImage ? pBIH->cbImage : AlignedWidth4Bytes( pBIH->cx * pBIH->cBitCount ) ); + + BYTE* pCopy = (BYTE*)rtl_allocateZeroMemory( nSize ); + memcpy( pCopy, (BYTE*) hHdl, nSize ); + hCopy = (HANDLE) pCopy; + } + else if( hHdl ) + { + HAB hAB = GetSalData()->mhAB; + HDC hSrcMemDC; + HDC hDestMemDC; + HPS hSrcMemPS; + HPS hDestMemPS; + HBITMAP hCopyBitmap; + BITMAPINFOHEADER2 aInfoHeader; + DEVOPENSTRUC aDevOpenStruc; + SIZEL size; + + aInfoHeader.cbFix = sizeof( BITMAPINFOHEADER2 ); + GpiQueryBitmapInfoHeader( hHdl, &aInfoHeader ); + size.cx = aInfoHeader.cx; + size.cy = aInfoHeader.cy; + + // Memory DCs erzeugen + aDevOpenStruc.pszLogAddress = 0; + aDevOpenStruc.pszDriverName = (PSZ)"DISPLAY"; + + hSrcMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 2, (PDEVOPENDATA)&aDevOpenStruc, 0 ); + hDestMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 2, (PDEVOPENDATA)&aDevOpenStruc, 0 ); + + // Memory PSs erzeugen + hSrcMemPS = Ft2CreatePS( hAB, hSrcMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS ); + hDestMemPS = Ft2CreatePS( hAB, hDestMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS ); + + Ft2SetBitmap( hSrcMemPS, hHdl ); + + if( !hHdl ) + { + memset( &aInfoHeader, 0, sizeof( BITMAPINFOHEADER2 ) ); + aInfoHeader.cbFix = sizeof( BITMAPINFOHEADER2 ); + aInfoHeader.cx = 0; + aInfoHeader.cy = 0; + aInfoHeader.cPlanes = 1; + aInfoHeader.cBitCount = 1; + } + + hCopy = GpiCreateBitmap( hDestMemPS, &aInfoHeader, 0, NULL, NULL ); + Ft2SetBitmap( hDestMemPS, hCopy ); + + POINTL pts[3]; + + pts[0].x = 0; + pts[0].y = 0; + pts[1].x = size.cx; + pts[1].y = size.cy; + pts[2].x = 0; + pts[2].y = 0; + + GpiBitBlt( hDestMemPS, hSrcMemPS, 3, pts, ROP_SRCCOPY, BBO_IGNORE ); + + Ft2SetBitmap( hSrcMemPS, (HBITMAP)0L); + Ft2SetBitmap( hDestMemPS, (HBITMAP)0L); + Ft2Associate( hSrcMemPS, NULLHANDLE ); + Ft2Associate( hDestMemPS, NULLHANDLE ); + Ft2DestroyPS( hSrcMemPS ); + Ft2DestroyPS( hDestMemPS ); + DevCloseDC( hSrcMemDC ); + DevCloseDC( hDestMemDC ); + } + + return hCopy; +} + +// ------------------------------------------------------------------ + +BitmapBuffer* Os2SalBitmap::AcquireBuffer( bool bReadOnly ) +{ + BitmapBuffer* pBuffer = NULL; + + if( mhDIB ) + { + // bitmap infos can be found at the beginning of the memory + PBITMAPINFO2 pBI = (PBITMAPINFO2) mhDIB; + PBITMAPINFOHEADER2 pBIH = (PBITMAPINFOHEADER2) pBI; + + if( ( pBIH->ulCompression == BCA_RLE4 ) || ( pBIH->ulCompression == BCA_RLE8 ) ) + { + Size aSizePix( pBIH->cx, pBIH->cy ); + HANDLE hNewDIB = ImplCreateDIB( aSizePix, pBIH->cBitCount, BitmapPalette() ); + + if( hNewDIB ) + { + // bitmap infos can be found at the beginning of the memory + PBITMAPINFO2 pNewBI = (PBITMAPINFO2) hNewDIB; + PBITMAPINFOHEADER2 pNewBIH = (PBITMAPINFOHEADER2) pNewBI; + const USHORT nColorCount = ImplGetDIBColorCount( hNewDIB ); + const ULONG nOffset = *(ULONG*) pBI + nColorCount * sizeof( RGB2 ); + BYTE* pOldBits = (BYTE*) pBI + nOffset; + BYTE* pNewBits = (BYTE*) pNewBI + nOffset; + + memcpy( pNewBI, pBI, nOffset ); + pNewBIH->ulCompression = 0; + ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->ulCompression == BCA_RLE4 ); + + rtl_freeMemory( (void*)mhDIB ); + + mhDIB = hNewDIB; + pBI = pNewBI; + pBIH = pNewBIH; + } + } + + if( pBIH->cPlanes == 1 ) + { + pBuffer = new BitmapBuffer; + + pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP | + ( pBIH->cBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL : + pBIH->cBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL : + pBIH->cBitCount == 8 ? BMP_FORMAT_8BIT_PAL : + pBIH->cBitCount == 16 ? BMP_FORMAT_16BIT_TC_LSB_MASK : + pBIH->cBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR : + pBIH->cBitCount == 32 ? BMP_FORMAT_32BIT_TC_MASK : 0UL ); + + if( BMP_SCANLINE_FORMAT( pBuffer->mnFormat ) ) + { + pBuffer->mnWidth = maSize.Width(); + pBuffer->mnHeight = maSize.Height(); + pBuffer->mnScanlineSize = AlignedWidth4Bytes( maSize.Width() * pBIH->cBitCount ); + pBuffer->mnBitCount = (USHORT) pBIH->cBitCount; + + if( pBuffer->mnBitCount <= 8 ) + { + const USHORT nPalCount = ImplGetDIBColorCount( mhDIB ); + + pBuffer->maPalette.SetEntryCount( nPalCount ); + + if( nPalCount ) + memcpy( pBuffer->maPalette.ImplGetColorBuffer(), pBI->argbColor, nPalCount * sizeof( RGB2 ) ); + + pBuffer->mpBits = (BYTE*) pBI + *(ULONG*) pBI + nPalCount * sizeof( RGB2 ); + } + else + pBuffer->mpBits = (BYTE*) pBI + *(ULONG*) pBI; + } + else + { + delete pBuffer; + pBuffer = NULL; + } + } + } + + if( pBuffer && mhDIB1Subst ) + { + rtl_freeMemory( (void*)mhDIB1Subst ); + mhDIB1Subst = 0; + } + + return pBuffer; +} + +// ------------------------------------------------------------------ + +void Os2SalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) +{ + if( pBuffer ) + { + if( mhDIB ) + { + if( !bReadOnly && !!pBuffer->maPalette ) + { + // bitmap infos can be found at the beginning of the memory + PBITMAPINFO2 pBI = (PBITMAPINFO2) mhDIB; + const USHORT nCount = pBuffer->maPalette.GetEntryCount(); + + if( nCount ) + memcpy( pBI->argbColor, pBuffer->maPalette.ImplGetColorBuffer(), nCount * sizeof( RGB2 ) ); + } + } + + delete pBuffer; + } +} + +// ------------------------------------------------------------------ + +void Os2SalBitmap::ImplDecodeRLEBuffer( const BYTE* pSrcBuf, BYTE* pDstBuf, + const Size& rSizePixel, BOOL bRLE4 ) +{ + HPBYTE pRLE = (HPBYTE) pSrcBuf; + HPBYTE pDIB = (HPBYTE) pDstBuf; + HPBYTE pRow = (HPBYTE) pDstBuf; + ULONG nWidthAl = AlignedWidth4Bytes( rSizePixel.Width() * ( bRLE4 ? 4UL : 8UL ) ); + HPBYTE pLast = pDIB + rSizePixel.Height() * nWidthAl - 1; + ULONG nCountByte; + ULONG nRunByte; + ULONG nX = 0; + ULONG i; + BYTE cTmp; + BOOL bEndDecoding = FALSE; + + if( pRLE && pDIB ) + { + do + { + if( !( nCountByte = *pRLE++ ) ) + { + nRunByte = *pRLE++; + + if( nRunByte > 2UL ) + { + if( bRLE4 ) + { + nCountByte = nRunByte >> 1UL; + + for( i = 0; i < nCountByte; i++ ) + { + cTmp = *pRLE++; + ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); + ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); + } + + if( nRunByte & 1 ) + ImplSetPixel4( pDIB, nX++, *pRLE++ >> 4 ); + + if( ( ( nRunByte + 1 ) >> 1 ) & 1 ) + pRLE++; + } + else + { + memcpy( &pDIB[ nX ], pRLE, nRunByte ); + pRLE += nRunByte; + nX += nRunByte; + + if( nRunByte & 1 ) + pRLE++; + } + } + else if( !nRunByte ) + { + pDIB = ( pRow += nWidthAl ); + nX = 0UL; + } + else if( nRunByte == 1 ) + bEndDecoding = TRUE; + else + { + nX += *pRLE++; + pDIB = ( pRow += ( *pRLE++ ) * nWidthAl ); + } + } + else + { + cTmp = *pRLE++; + + if( bRLE4 ) + { + nRunByte = nCountByte >> 1; + + for( i = 0; i < nRunByte; i++ ) + { + ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); + ImplSetPixel4( pDIB, nX++, cTmp & 0x0f ); + } + + if( nCountByte & 1 ) + ImplSetPixel4( pDIB, nX++, cTmp >> 4 ); + } + else + { + for( i = 0; i < nCountByte; i++ ) + pDIB[ nX++ ] = cTmp; + } + } + } + while( !bEndDecoding && ( pDIB <= pLast ) ); + } +} + +bool Os2SalBitmap::GetSystemData( BitmapSystemData& rData ) +{ + bool bRet = false; + if( mhDIB || mhDDB ) + { + bRet = true; + rData.pDIB = (void*)mhDIB; + rData.pDDB = (void*)mhDDB; + } + return bRet; +} diff --git a/vcl/os2/source/gdi/salgdi.cxx b/vcl/os2/source/gdi/salgdi.cxx new file mode 100644 index 000000000000..082e690c09e7 --- /dev/null +++ b/vcl/os2/source/gdi/salgdi.cxx @@ -0,0 +1,1046 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salgdi.cxx,v $ + * $Revision: 1.8.6.1 $ + * + * 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> +#include <svpm.h> + +#define _SV_SALGDI_CXX +#include <tools/debug.hxx> +#include <saldata.hxx> +#include <salgdi.h> +#include <tools/debug.hxx> +#include <salframe.h> +#include <tools/poly.hxx> +#ifndef _RTL_STRINGBUF_HXX +#include <rtl/strbuf.hxx> +#endif + +#ifndef __H_FT2LIB +#include <wingdi.h> +#include <ft2lib.h> +#endif + +// ----------- +// - Defines - +// ----------- + +// ClipRegions funktionieren immer noch nicht auf allen getesteten Druckern +#define SAL_PRINTER_CLIPPATH 1 +// #define SAL_PRINTER_POLYPATH 1 + +// ======================================================================= + +void ImplInitSalGDI() +{ +} + +// ----------------------------------------------------------------------- + +void ImplFreeSalGDI() +{ + SalData* pSalData = GetSalData(); + + // delete icon cache + SalIcon* pIcon = pSalData->mpFirstIcon; + while( pIcon ) + { + SalIcon* pTmp = pIcon->pNext; + WinDestroyPointer( pIcon->hIcon ); + delete pIcon; + pIcon = pTmp; + } + +} + +// ======================================================================= + +void ImplSalInitGraphics( Os2SalGraphics* pData ) +{ + GpiCreateLogColorTable( pData->mhPS, LCOL_RESET, LCOLF_RGB, 0, 0, NULL ); +} + +// ----------------------------------------------------------------------- + +void ImplSalDeInitGraphics( Os2SalGraphics* pData ) +{ +} + +// ======================================================================= + +Os2SalGraphics::Os2SalGraphics() +{ + for( int i = 0; i < MAX_FALLBACK; ++i ) + { + mhFonts[ i ] = 0; + mpOs2FontData[ i ] = NULL; + mpOs2FontEntry[ i ] = NULL; + } + + mfFontScale = 1.0; + + mhPS = 0; + mhDC = 0; + mbLine = FALSE; + mbFill = FALSE; + mbXORMode = FALSE; + mnFontMetricCount = 0; + mpFontMetrics = NULL; + mpClipRectlAry = NULL; + + mhDefFont = 0; + mpFontKernPairs = NULL; + mnFontKernPairCount = 0; + mbFontKernInit = FALSE; + +} + +// ----------------------------------------------------------------------- + +Os2SalGraphics::~Os2SalGraphics() +{ + Ft2DeleteSetId( mhPS, LCID_BASE); + + if ( mpFontMetrics ) + delete mpFontMetrics; + + if ( mpFontKernPairs ) + delete mpFontKernPairs; + +} + +// ----------------------------------------------------------------------- + +static SalColor ImplGetROPSalColor( SalROPColor nROPColor ) +{ + SalColor nSalColor; + + switch( nROPColor ) + { + case SAL_ROP_0: + nSalColor = MAKE_SALCOLOR( 0, 0, 0 ); + break; + + case SAL_ROP_1: + case SAL_ROP_INVERT: + nSalColor = MAKE_SALCOLOR( 255, 255, 255 ); + break; + } + + return nSalColor; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::GetResolution( long& rDPIX, long& rDPIY ) +{ + // since OOo asks for DPI, I will query FONT_RES, which seems to be + // more correct than _RESOLUTION fields (on my wide screen lcd) + // and does not require conversion + DevQueryCaps( mhDC, CAPS_HORIZONTAL_FONT_RES, 1, &rDPIX ); + DevQueryCaps( mhDC, CAPS_VERTICAL_FONT_RES, 1, &rDPIY ); +} + +// ----------------------------------------------------------------------- + +USHORT Os2SalGraphics::GetBitCount() +{ + LONG nBitCount; + DevQueryCaps( mhDC, CAPS_COLOR_BITCOUNT, 1, &nBitCount ); + return (USHORT)nBitCount; +} + +// ----------------------------------------------------------------------- + +long Os2SalGraphics::GetGraphicsWidth() const +{ + if( mhWnd ) + { + Os2SalFrame* pFrame = (Os2SalFrame*)GetWindowPtr( mhWnd ); + if( pFrame ) + { + if( pFrame->maGeometry.nWidth ) + return pFrame->maGeometry.nWidth; + else + { + // TODO: perhaps not needed, maGeometry should always be up-to-date + RECTL aRect; + WinQueryWindowRect( mhWnd, &aRect ); + return aRect.xRight; + } + } + } + + return 0; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::ResetClipRegion() +{ +#ifdef SAL_PRINTER_CLIPPATH + if ( mbPrinter ) + GpiSetClipPath( mhPS, 0, SCP_RESET ); + else +#endif + { + HRGN hOldRegion; + + GpiSetClipRegion( mhPS, NULL, &hOldRegion ); + if ( hOldRegion ) + GpiDestroyRegion( mhPS, hOldRegion ); + } +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::BeginSetClipRegion( ULONG nCount ) +{ + mpClipRectlAry = new RECTL[ nCount ]; + mnClipElementCount = 0; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalGraphics::unionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + RECTL* pClipRect = &mpClipRectlAry[ mnClipElementCount ]; + pClipRect->xLeft = nX; + pClipRect->yTop = mnHeight - nY; + pClipRect->xRight = nX + nWidth; + pClipRect->yBottom = mnHeight - (nY + nHeight); + mnClipElementCount++; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +bool Os2SalGraphics::unionClipRegion( const ::basegfx::B2DPolyPolygon& ) +{ + // TODO: implement and advertise OutDevSupport_B2DClip support + return false; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::EndSetClipRegion() +{ +#ifdef SAL_PRINTER_CLIPPATH + if ( mbPrinter ) + { + GpiSetClipPath( mhPS, 0, SCP_RESET ); + GpiBeginPath( mhPS, 1L ); + + for( int i = 0; i < mnClipElementCount; i++ ) + { + POINTL aPt; + RECTL* pClipRect = &mpClipRectlAry[ i ]; + + aPt.x = pClipRect->xLeft; + aPt.y = pClipRect->yTop-1; + Ft2Move( mhPS, &aPt ); + + aPt.x = pClipRect->xRight-1; + aPt.y = pClipRect->yBottom; + + Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 ); + } + + GpiEndPath( mhPS ); + GpiSetClipPath( mhPS, 1L, SCP_ALTERNATE | SCP_AND ); + } + else +#endif + { + HRGN hClipRegion = GpiCreateRegion( mhPS, + mnClipElementCount, + mpClipRectlAry ); + HRGN hOldRegion; + + GpiSetClipRegion( mhPS, hClipRegion, &hOldRegion ); + if( hOldRegion ) + GpiDestroyRegion( mhPS, hOldRegion ); + } + + delete [] mpClipRectlAry; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::SetLineColor() +{ + // don't draw line! + mbLine = FALSE; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::SetLineColor( SalColor nSalColor ) +{ + LINEBUNDLE lb; + + // set color + lb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + + Ft2SetAttrs( mhPS, + PRIM_LINE, + LBB_COLOR, + 0, + &lb ); + + // draw line! + mbLine = TRUE; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::SetFillColor() +{ + // don't fill area! + mbFill = FALSE; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::SetFillColor( SalColor nSalColor ) +{ + AREABUNDLE ab; + + // set color + ab.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + + Ft2SetAttrs( mhPS, + PRIM_AREA, + ABB_COLOR, + 0, + &ab ); + + // fill area! + mbFill = TRUE; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::SetXORMode( bool bSet, bool ) +{ + mbXORMode = bSet; + LONG nMixMode = bSet ? FM_XOR : FM_OVERPAINT; + + // set mix mode for lines + LINEBUNDLE lb; + lb.usMixMode = nMixMode; + Ft2SetAttrs( mhPS, + PRIM_LINE, + LBB_MIX_MODE, + 0, + &lb ); + + // set mix mode for areas + AREABUNDLE ab; + ab.usMixMode = nMixMode; + Ft2SetAttrs( mhPS, + PRIM_AREA, + ABB_MIX_MODE, + 0, + &ab ); + + // set mix mode for text + CHARBUNDLE cb; + cb.usMixMode = nMixMode; + Ft2SetAttrs( mhPS, + PRIM_CHAR, + CBB_MIX_MODE, + 0, + &cb ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::SetROPLineColor( SalROPColor nROPColor ) +{ + SetLineColor( ImplGetROPSalColor( nROPColor ) ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::SetROPFillColor( SalROPColor nROPColor ) +{ + SetFillColor( ImplGetROPSalColor( nROPColor ) ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawPixel( long nX, long nY ) +{ + POINTL aPt; + + aPt.x = nX; + aPt.y = TY( nY ); + + // set color + Ft2SetPel( mhPS, &aPt ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) +{ + // save old color + LINEBUNDLE oldLb; + GpiQueryAttrs( mhPS, + PRIM_LINE, + LBB_COLOR, + &oldLb ); + + // set new color + LINEBUNDLE lb; + lb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + Ft2SetAttrs( mhPS, + PRIM_LINE, + LBB_COLOR, + 0, + &lb ); + + // set color of pixel + POINTL aPt; + aPt.x = nX; + aPt.y = TY( nY ); + Ft2SetPel( mhPS, &aPt ); + + // restore old color + Ft2SetAttrs( mhPS, + PRIM_LINE, + LBB_COLOR, + 0, + &oldLb ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) +{ + // OS2 zeichnet den Endpunkt mit + POINTL aPt; + aPt.x = nX1; + aPt.y = TY( nY1 ); + Ft2Move( mhPS, &aPt ); + aPt.x = nX2; + aPt.y = TY( nY2 ); + GpiLine( mhPS, &aPt ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) +{ + POINTL aPt; + long lControl; + + if ( mbFill ) + { + if ( mbLine ) + lControl = DRO_OUTLINEFILL; + else + lControl = DRO_FILL; + } + else + { + if ( mbLine ) + lControl = DRO_OUTLINE; + else + return; + } + + aPt.x = nX; + aPt.y = TY( nY ); + Ft2Move( mhPS, &aPt ); + aPt.x = nX + nWidth - 1; + aPt.y = TY( nY + nHeight - 1 ); + Ft2Box( mhPS, lControl, &aPt, 0, 0 ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawPolyLine( ULONG nPoints, const SalPoint* pPtAry ) +{ + // convert all points to sys orientation + POINTL* pOS2PtAry = new POINTL[ nPoints ]; + POINTL* pTempOS2PtAry = pOS2PtAry; + const SalPoint* pTempPtAry = pPtAry; + ULONG nTempPoints = nPoints; + long nHeight = mnHeight - 1; + + while( nTempPoints-- ) + { + (*pTempOS2PtAry).x = (*pTempPtAry).mnX; + (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY; + pTempOS2PtAry++; + pTempPtAry++; + } + + Ft2Move( mhPS, pOS2PtAry ); + GpiPolyLine( mhPS, nPoints, pOS2PtAry ); + delete [] pOS2PtAry; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawPolygon( ULONG nPoints, const SalPoint* pPtAry ) +{ + PM_POLYGON aPolygon; + + // create polygon + aPolygon.aPointl = new POINTL[ nPoints ]; + aPolygon.ulPoints = nPoints; + + // convert all points to sys orientation + POINTL* pTempOS2PtAry = aPolygon.aPointl; + const SalPoint* pTempPtAry = pPtAry; + ULONG nTempPoints = nPoints; + long nHeight = mnHeight - 1; + + while( nTempPoints-- ) + { + (*pTempOS2PtAry).x = (*pTempPtAry).mnX; + (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY; + pTempOS2PtAry++; + pTempPtAry++; + } + + // Innenleben zeichnen + if ( mbFill ) + { +#ifdef SAL_PRINTER_POLYPATH + if ( mbPrinter ) + { + Ft2BeginPath( mhPS, 1 ); + Ft2Move( mhPS, aPolygon.aPointl ); + Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl ); + Ft2EndPath( mhPS ); + Ft2FillPath( mhPS, 1, 0 ); + + if ( mbLine ) + { + Ft2Move( mhPS, aPolygon.aPointl ); + Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl ); + } + } + else +#endif + { + ULONG nOptions = POLYGON_ALTERNATE; + + if ( mbLine ) + nOptions |= POLYGON_BOUNDARY; + else + nOptions |= POLYGON_NOBOUNDARY; + + Ft2Move( mhPS, aPolygon.aPointl ); + GpiPolygons( mhPS, 1, &aPolygon, nOptions, POLYGON_EXCL ); + } + } + else + { + if ( mbLine ) + { + Ft2Move( mhPS, aPolygon.aPointl ); + GpiPolyLine( mhPS, nPoints, aPolygon.aPointl ); + } + } + + delete [] aPolygon.aPointl; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawPolyPolygon( ULONG nPoly, const ULONG* pPoints, + PCONSTSALPOINT* pPtAry ) +{ + ULONG i; + long nHeight = mnHeight - 1; + PM_POLYGON* aPolygonAry = new PM_POLYGON[ nPoly ]; + + for( i = 0; i < nPoly; i++ ) + { + const SalPoint * pTempPtAry = (const SalPoint*)pPtAry[ i ]; + + // create polygon + ULONG nTempPoints = pPoints[ i ]; + POINTL * pTempOS2PtAry = new POINTL[ nTempPoints ]; + + // convert all points to sys orientation + aPolygonAry[ i ].ulPoints = nTempPoints; + aPolygonAry[ i ].aPointl = pTempOS2PtAry; + + while( nTempPoints-- ) + { + (*pTempOS2PtAry).x = (*pTempPtAry).mnX; + (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY; + pTempOS2PtAry++; + pTempPtAry++; + } + } + + // Innenleben zeichnen + if ( mbFill ) + { +#ifdef SAL_PRINTER_POLYPATH + if ( mbPrinter ) + { + Ft2BeginPath( mhPS, 1 ); + for ( i = 0; i < nPoly; i++ ) + { + Ft2Move( mhPS, aPolygonAry[i].aPointl ); + Ft2PolyLine( mhPS, aPolygonAry[i].ulPoints, aPolygonAry[i].aPointl ); + } + Ft2EndPath( mhPS ); + Ft2FillPath( mhPS, 1, 0 ); + } + else +#endif + { + ULONG nOptions = POLYGON_ALTERNATE; + + if ( mbLine ) + nOptions |= POLYGON_BOUNDARY; + else + nOptions |= POLYGON_NOBOUNDARY; + + Ft2Move( mhPS, aPolygonAry[ 0 ].aPointl ); + GpiPolygons( mhPS, nPoly, aPolygonAry, nOptions, POLYGON_EXCL ); + } + } + else + { + if ( mbLine ) + { + for( i = 0; i < nPoly; i++ ) + { + Ft2Move( mhPS, aPolygonAry[ i ].aPointl ); + GpiPolyLine( mhPS, aPolygonAry[ i ].ulPoints, aPolygonAry[ i ].aPointl ); + } + } + } + + // cleanup + for( i = 0; i < nPoly; i++ ) + delete [] aPolygonAry[ i ].aPointl; + delete [] aPolygonAry; +} + +// ----------------------------------------------------------------------- + +bool Os2SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ ) +{ + // TODO: implement and advertise OutDevSupport_B2DDraw support + return false; +} + +// ----------------------------------------------------------------------- + +bool Os2SalGraphics::drawPolyLine( + const basegfx::B2DPolygon& /*rPolygon*/, + const basegfx::B2DVector& /*rLineWidths*/, + basegfx::B2DLineJoin /*eLineJoin*/) +{ + // TODO: implement + return false; +} + +// ----------------------------------------------------------------------- + +sal_Bool Os2SalGraphics::drawPolyLineBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) +{ + return sal_False; +} + +// ----------------------------------------------------------------------- + +sal_Bool Os2SalGraphics::drawPolygonBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) +{ + return sal_False; +} + +// ----------------------------------------------------------------------- + +sal_Bool Os2SalGraphics::drawPolyPolygonBezier( ULONG nPoly, const ULONG* pPoints, + const SalPoint* const* pPtAry, const BYTE* const* pFlgAry ) +{ + return sal_False; +} + +// ======================================================================= + +// MAXIMUM BUFSIZE EQ 0xFFFF +#define POSTSCRIPT_BUFSIZE 0x4000 +// we only try to get the BoundingBox in the first 4096 bytes +#define POSTSCRIPT_BOUNDINGSEARCH 0x1000 + +static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, ULONG nComp, ULONG nSize ) +{ + while ( nComp-- >= nSize ) + { + ULONG i; + for ( i = 0; i < nSize; i++ ) + { + if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) ) + break; + } + if ( i == nSize ) + return pSource; + pSource++; + } + return NULL; +} + + +static BOOL ImplGetBoundingBox( double* nNumb, BYTE* pSource, ULONG nSize ) +{ + BOOL bRetValue = FALSE; + BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nSize, 14 ); + if ( pDest ) + { + nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0; + pDest += 14; + + int nSizeLeft = nSize - ( pDest - pSource ); + if ( nSizeLeft > 100 ) + nSizeLeft = 100; // only 100 bytes following the bounding box will be checked + + int i; + for ( i = 0; ( i < 4 ) && nSizeLeft; i++ ) + { + int nDivision = 1; + BOOL bDivision = FALSE; + BOOL bNegative = FALSE; + BOOL bValid = TRUE; + + while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++; + BYTE nByte = *pDest; + while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) ) + { + switch ( nByte ) + { + case '.' : + if ( bDivision ) + bValid = FALSE; + else + bDivision = TRUE; + break; + case '-' : + bNegative = TRUE; + break; + default : + if ( ( nByte < '0' ) || ( nByte > '9' ) ) + nSizeLeft = 1; // error parsing the bounding box values + else if ( bValid ) + { + if ( bDivision ) + nDivision*=10; + nNumb[i] *= 10; + nNumb[i] += nByte - '0'; + } + break; + } + nSizeLeft--; + nByte = *(++pDest); + } + if ( bNegative ) + nNumb[i] = -nNumb[i]; + if ( bDivision && ( nDivision != 1 ) ) + nNumb[i] /= nDivision; + } + if ( i == 4 ) + bRetValue = TRUE; + } + return bRetValue; +} + +#if 0 +static void ImplWriteDouble( BYTE** pBuf, double nNumber ) +{ +// *pBuf += sprintf( (char*)*pBuf, "%f", nNumber ); + + if ( nNumber < 0 ) + { + *(*pBuf)++ = (BYTE)'-'; + nNumber = -nNumber; + } + ULONG nTemp = (ULONG)nNumber; + const String aNumber1( nTemp ); + ULONG nLen = aNumber1.Len(); + + for ( USHORT n = 0; n < nLen; n++ ) + *(*pBuf)++ = aNumber1[ n ]; + + nTemp = (ULONG)( ( nNumber - nTemp ) * 100000 ); + if ( nTemp ) + { + *(*pBuf)++ = (BYTE)'.'; + const String aNumber2( nTemp ); + + ULONG nLen = aNumber2.Len(); + if ( nLen < 8 ) + { + for ( n = 0; n < ( 5 - nLen ); n++ ) + { + *(*pBuf)++ = (BYTE)'0'; + } + } + for ( USHORT n = 0; n < nLen; n++ ) + { + *(*pBuf)++ = aNumber2[ n ]; + } + } + *(*pBuf)++ = ' '; +} +#endif + +inline void ImplWriteString( BYTE** pBuf, const char* sString ) +{ + strcpy( (char*)*pBuf, sString ); + *pBuf += strlen( sString ); +} + +BOOL Os2SalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize ) +{ + if ( !mbPrinter ) + return FALSE; + + BOOL bRet = FALSE; + LONG nLong = 0; + if ( !(DevQueryCaps( mhDC, CAPS_TECHNOLOGY, 1, &nLong ) && + (CAPS_TECH_POSTSCRIPT == nLong)) ) + return FALSE; + + BYTE* pBuf = new BYTE[ POSTSCRIPT_BUFSIZE ]; + double nBoundingBox[4]; + + if ( pBuf && ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) ) + { + LONG pOS2DXAry[4]; // hack -> print always 2 white space + POINTL aPt; + aPt.x = 0; + aPt.y = 0; + PCH pStr = (PCH) " "; + for( long i = 0; i < 4; i++ ) + pOS2DXAry[i] = i; + Ft2CharStringPosAt( mhPS, &aPt, NULL, 0, 2, (PCH)pStr,(PLONG)&pOS2DXAry[0] ); + + OStringBuffer aBuf( POSTSCRIPT_BUFSIZE ); + + // reserve place for a USHORT + aBuf.append( "aa" ); + + // #107797# Write out EPS encapsulation header + // ---------------------------------------------------------------------------------- + + // directly taken from the PLRM 3.0, p. 726. Note: + // this will definitely cause problems when + // recursively creating and embedding PostScript files + // in OOo, since we use statically-named variables + // here (namely, b4_Inc_state_salWin, dict_count_salWin and + // op_count_salWin). Currently, I have no idea on how to + // work around that, except from scanning and + // interpreting the EPS for unused identifiers. + + // append the real text + aBuf.append( "\n\n/b4_Inc_state_salWin save def\n" + "/dict_count_salWin countdictstack def\n" + "/op_count_salWin count 1 sub def\n" + "userdict begin\n" + "/showpage {} def\n" + "0 setgray 0 setlinecap\n" + "1 setlinewidth 0 setlinejoin\n" + "10 setmiterlimit [] 0 setdash newpath\n" + "/languagelevel where\n" + "{\n" + " pop languagelevel\n" + " 1 ne\n" + " {\n" + " false setstrokeadjust false setoverprint\n" + " } if\n" + "} if\n\n" ); + +#if 0 + // #i10737# Apply clipping manually + // ---------------------------------------------------------------------------------- + + // Windows seems to ignore any clipping at the HDC, + // when followed by a POSTSCRIPT_PASSTHROUGH + + // Check whether we've got a clipping, consisting of + // exactly one rect (other cases should be, but aren't + // handled currently) + + // TODO: Handle more than one rectangle here (take + // care, the buffer can handle only POSTSCRIPT_BUFSIZE + // characters!) + if ( mhRegion != 0 && + mpStdClipRgnData != NULL && + mpClipRgnData == mpStdClipRgnData && + mpClipRgnData->rdh.nCount == 1 ) + { + RECT* pRect = &(mpClipRgnData->rdh.rcBound); + + aBuf.append( "\nnewpath\n" ); + aBuf.append( pRect->left ); + aBuf.append( " " ); + aBuf.append( pRect->top ); + aBuf.append( " moveto\n" ); + aBuf.append( pRect->right ); + aBuf.append( " " ); + aBuf.append( pRect->top ); + aBuf.append( " lineto\n" ); + aBuf.append( pRect->right ); + aBuf.append( " " ); + aBuf.append( pRect->bottom ); + aBuf.append( " lineto\n" ); + aBuf.append( pRect->left ); + aBuf.append( " " ); + aBuf.append( pRect->bottom ); + aBuf.append( " lineto\n" + "closepath\n" + "clip\n" + "newpath\n" ); + } +#endif + + // #107797# Write out buffer + // ---------------------------------------------------------------------------------- + *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 ); + //Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); + DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(), + (PBYTE)aBuf.getStr(), 0, NULL ); + + double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] ); + double dM22 = - ( nHeight / (nBoundingBox[1] - nBoundingBox[3] ) ); + + // reserve a USHORT again + aBuf.setLength( 2 ); + aBuf.append( "\n\n[" ); + aBuf.append( dM11 ); + aBuf.append( " 0 0 " ); + aBuf.append( dM22 ); + aBuf.append( ' ' ); + aBuf.append( nX - ( dM11 * nBoundingBox[0] ) ); + aBuf.append( ' ' ); + aBuf.append( nY - ( dM22 * nBoundingBox[3] ) ); + aBuf.append( "] concat\n" + "%%BeginDocument:\n" ); + *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 ); + DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(), + (PBYTE)aBuf.getStr(), 0, NULL ); +#if 0 + BYTE* pTemp = pBuf; + ImplWriteString( &pTemp, "save\n[ " ); + ImplWriteDouble( &pTemp, dM11 ); + ImplWriteDouble( &pTemp, 0 ); + ImplWriteDouble( &pTemp, 0 ); + ImplWriteDouble( &pTemp, dM22 ); + ImplWriteDouble( &pTemp, nX - ( dM11 * nBoundingBox[0] ) ); + ImplWriteDouble( &pTemp, mnHeight - nY - ( dM22 * nBoundingBox[3] ) ); + ImplWriteString( &pTemp, "] concat /showpage {} def\n" ); + + if ( DevEscape( mhDC, DEVESC_RAWDATA, pTemp - pBuf, + (PBYTE)pBuf, 0, NULL ) == DEV_OK ) +#endif // + { + UINT32 nToDo = nSize; + UINT32 nDoNow; + bRet = TRUE; + while( nToDo && bRet ) + { + nDoNow = 0x4000; + if ( nToDo < nDoNow ) + nDoNow = nToDo; + + if ( DevEscape( mhDC, DEVESC_RAWDATA, nDoNow, (PBYTE)pPtr + nSize - nToDo, + 0, NULL ) == -1 ) + bRet = FALSE; + nToDo -= nDoNow; + } + + if ( bRet ) + { + strcpy ( (char*)pBuf, "\nrestore\n" ); + if ( DevEscape( mhDC, DEVESC_RAWDATA, 9, (PBYTE)pBuf, + 0, NULL ) == DEV_OK ) bRet = TRUE; + } + + // #107797# Write out EPS encapsulation footer + // ---------------------------------------------------------------------------------- + // reserve a USHORT again + aBuf.setLength( 2 ); + aBuf.append( "%%EndDocument\n" + "count op_count_salWin sub {pop} repeat\n" + "countdictstack dict_count_salWin sub {end} repeat\n" + "b4_Inc_state_salWin restore\n\n" ); + *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 ); + DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(), + (PBYTE)aBuf.getStr(), 0, NULL ); + bRet = TRUE; + + } + } + delete [] pBuf; + return bRet; +} + +/* + * IsNativeControlSupported() + * + * Returns TRUE if the platform supports native + * drawing of the control defined by nPart + */ +BOOL Os2SalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) +{ + return( FALSE ); +} + +// ----------------------------------------------------------------------- + +SystemGraphicsData Os2SalGraphics::GetGraphicsData() const +{ + SystemGraphicsData aRes; + aRes.nSize = sizeof(aRes); +#if 0 + aRes.hDC = mhDC; +#endif + return aRes; +} + +// ----------------------------------------------------------------------- diff --git a/vcl/os2/source/gdi/salgdi2.cxx b/vcl/os2/source/gdi/salgdi2.cxx new file mode 100644 index 000000000000..733517ffa9b4 --- /dev/null +++ b/vcl/os2/source/gdi/salgdi2.cxx @@ -0,0 +1,789 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salgdi2.cxx,v $ + * $Revision: 1.7 $ + * + * 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> +#include <svpm.h> + +#define _SV_SALGDI2_CXX +#include <salbmp.h> +#include <saldata.hxx> +#ifndef _SV_SALIDS_HRC +#include <salids.hrc> +#endif +#include <salgdi.h> +#include <salvd.h> +#include <vcl/salbtype.hxx> + +#ifndef __H_FT2LIB +#include <wingdi.h> +#include <ft2lib.h> +#endif + +BOOL bFastTransparent = FALSE; + +// ----------- +// - Defines - +// ----------- + +#define RGBCOLOR( r, g, b ) ((ULONG)(((BYTE)(b)|((USHORT)(g)<<8))|(((ULONG)(BYTE)(r))<<16))) +#define TY( y ) (mnHeight-(y)-1) + +// --------------- +// - SalGraphics - +// --------------- + +bool Os2SalGraphics::supportsOperation( OutDevSupportType ) const +{ + return false; +} + + +void Os2SalGraphics::copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics ) +{ + HPS hSrcPS; + POINTL thePoints[4]; + long nSrcHeight; + + if ( pSrcGraphics ) + { + //hSrcPS = pSrcGraphics->mhPS; + //nSrcHeight = pSrcGraphics->mnHeight; + hSrcPS = static_cast<Os2SalGraphics*>(pSrcGraphics)->mhPS; + nSrcHeight = static_cast<Os2SalGraphics*>(pSrcGraphics)->mnHeight; + } + else + { + hSrcPS = mhPS; + nSrcHeight = mnHeight; + } + + // lower-left corner of target + thePoints[0].x = pPosAry->mnDestX; + thePoints[0].y = TY( pPosAry->mnDestY + pPosAry->mnDestHeight - 1 ); + + // upper-right corner of target + thePoints[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth; + thePoints[1].y = TY( pPosAry->mnDestY - 1 ); + + // lower-left corner of source + thePoints[2].x = pPosAry->mnSrcX; + thePoints[2].y = nSrcHeight - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight ); + + if ( ( pPosAry->mnDestWidth != pPosAry->mnSrcWidth ) || ( pPosAry->mnDestHeight != pPosAry->mnSrcHeight ) ) + { + // upper-right corner of Source + thePoints[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth; + thePoints[3].y = nSrcHeight - pPosAry->mnSrcY + pPosAry->mnSrcHeight; + + GpiBitBlt( mhPS, hSrcPS, 4, thePoints, + mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE ); + } + else + { + GpiBitBlt( mhPS, hSrcPS, 3, thePoints, + mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE ); + } +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::copyArea( long nDestX, long nDestY, + long nSrcX, long nSrcY, + long nSrcWidth, long nSrcHeight, + USHORT nFlags ) +{ + POINTL thePoints[3]; + + // lower-left corner of target + thePoints[0].x = nDestX; + thePoints[0].y = TY( nDestY + nSrcHeight - 1 ); + + // upper-right corner of target + thePoints[1].x = nDestX + nSrcWidth; + thePoints[1].y = TY( nDestY - 1 ); + + // lower-left corner of source + thePoints[2].x = nSrcX; + thePoints[2].y = TY( nSrcY + nSrcHeight - 1); + + if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && mbWindow ) + { + // Overlap-Bereich berechnen und invalidieren + Point aVCLSrcPos( nSrcX, nSrcY ); + Size aVCLSrcSize( nSrcWidth, nSrcHeight ); + Rectangle aVCLSrcRect( aVCLSrcPos, aVCLSrcSize ); + Rectangle aVCLClipRect; + SWP aSWP; + + WinQueryWindowPos( mhWnd, &aSWP ); + aVCLClipRect.Right() = aSWP.cx-1; + aVCLClipRect.Bottom() = aSWP.cy-1; + if ( !aVCLSrcRect.Intersection( aVCLClipRect ).IsEmpty() ) + { + RECTL aSrcRect; + RECTL aTempRect; + HRGN hInvalidateRgn; + HRGN hTempRgn; + HWND hWnd; + long nRgnType; + + long nVCLScrHeight = aVCLSrcRect.GetHeight(); + aSrcRect.xLeft = aVCLSrcRect.Left(); + aSrcRect.yBottom = TY( aVCLSrcRect.Top()+nVCLScrHeight-1 ); + aSrcRect.xRight = aSrcRect.xLeft+aVCLSrcRect.GetWidth(); + aSrcRect.yTop = aSrcRect.yBottom+nVCLScrHeight; + + // Rechteck in Screen-Koordinaaten umrechnen + POINTL aPt; + long nScreenDX = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ); + long nScreenDY = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ); + aPt.x = 0; + aPt.y = 0; + WinMapWindowPoints( mhWnd, HWND_DESKTOP, &aPt, 1 ); + aSrcRect.xLeft += aPt.x; + aSrcRect.yTop += aPt.y; + aSrcRect.xRight += aPt.x; + aSrcRect.yBottom += aPt.y; + hInvalidateRgn = 0; + // Bereiche ausserhalb des sichtbaren Bereiches berechnen + if ( aSrcRect.xLeft < 0 ) + { + if ( !hInvalidateRgn ) + hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect ); + aTempRect.xLeft = -31999; + aTempRect.yBottom = 0; + aTempRect.xRight = 0; + aTempRect.yTop = 31999; + hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect ); + GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF ); + GpiDestroyRegion( mhPS, hTempRgn ); + } + if ( aSrcRect.yBottom < 0 ) + { + if ( !hInvalidateRgn ) + hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect ); + aTempRect.xLeft = 0; + aTempRect.yBottom = -31999; + aTempRect.xRight = 31999; + aTempRect.yTop = 0; + hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect ); + GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF ); + GpiDestroyRegion( mhPS, hTempRgn ); + } + if ( aSrcRect.xRight > nScreenDX ) + { + if ( !hInvalidateRgn ) + hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect ); + aTempRect.xLeft = nScreenDX; + aTempRect.yBottom = 0; + aTempRect.xRight = 31999; + aTempRect.yTop = 31999; + hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect ); + GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF ); + GpiDestroyRegion( mhPS, hTempRgn ); + } + if ( aSrcRect.yTop > nScreenDY ) + { + if ( !hInvalidateRgn ) + hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect ); + aTempRect.xLeft = 0; + aTempRect.yBottom = nScreenDY; + aTempRect.xRight = 31999; + aTempRect.yTop = 31999; + hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect ); + GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF ); + GpiDestroyRegion( mhPS, hTempRgn ); + } + + // Bereiche die von anderen Fenstern ueberlagert werden berechnen + // Calculate areas that are overlapped by other windows + HWND hWndParent = WinQueryWindow( mhWnd, QW_PARENT ); + hWnd = WinQueryWindow( HWND_DESKTOP, QW_TOP ); + aVCLSrcRect = Rectangle( aSrcRect.xLeft, aSrcRect.yBottom, aSrcRect.xRight, aSrcRect.yTop ); + while ( hWnd ) + { + if ( hWnd == hWndParent ) + break; + if ( WinIsWindowVisible( hWnd ) ) + { + WinQueryWindowPos( hWnd, &aSWP ); + if ( !(aSWP.fl & SWP_MINIMIZE) ) + { + aVCLClipRect = Rectangle( Point( aSWP.x, aSWP.y ), Size( aSWP.cx, aSWP.cy ) ); + if ( aVCLSrcRect.IsOver( aVCLClipRect ) ) + { + if ( !hInvalidateRgn ) + hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect ); + aTempRect.xLeft = aSWP.x; + aTempRect.yBottom = aSWP.y; + aTempRect.xRight = aTempRect.xLeft+aSWP.cx; + aTempRect.yTop = aTempRect.yBottom+aSWP.cy; + hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect ); + GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF ); + GpiDestroyRegion( mhPS, hTempRgn ); + } + } + } + hWnd = WinQueryWindow( hWnd, QW_NEXT ); + } + + if ( hInvalidateRgn ) + { + hTempRgn = GpiCreateRegion( mhPS, 1, &aSrcRect ); + nRgnType = GpiCombineRegion( mhPS, hInvalidateRgn, hTempRgn, hInvalidateRgn, CRGN_DIFF ); + GpiDestroyRegion( mhPS, hTempRgn ); + if ( (nRgnType != RGN_ERROR) && (nRgnType != RGN_NULL) ) + { + long nOffX = (nDestX-nSrcX); + long nOffY = (nSrcY-nDestY); + aPt.x = nOffX-aPt.x; + aPt.y = nOffY-aPt.y; + GpiOffsetRegion( mhPS, hInvalidateRgn, &aPt ); + WinInvalidateRegion( mhWnd, hInvalidateRgn, TRUE ); + // Hier loesen wir nur ein Update aus, wenn es der + // MainThread ist, damit es beim Bearbeiten der + // Paint-Message keinen Deadlock gibt, da der + // SolarMutex durch diesen Thread schon gelockt ist + SalData* pSalData = GetSalData(); + ULONG nCurThreadId = GetCurrentThreadId(); + if ( pSalData->mnAppThreadId == nCurThreadId ) + WinUpdateWindow( mhWnd ); + } + GpiDestroyRegion( mhPS, hInvalidateRgn ); + } + } + } + + GpiBitBlt( mhPS, mhPS, 3, thePoints, + ROP_SRCCOPY, BBO_IGNORE ); + +} + +// ----------------------------------------------------------------------- + +void ImplDrawBitmap( HPS hPS, long nScreenHeight, + const SalTwoRect* pPosAry, const Os2SalBitmap& rSalBitmap, + BOOL bPrinter, int nDrawMode ) +{ + if( hPS ) + { + HANDLE hDrawDIB; + HBITMAP hDrawDDB = rSalBitmap.ImplGethDDB(); + Os2SalBitmap* pTmpSalBmp = NULL; + BOOL bPrintDDB = ( bPrinter && hDrawDDB ); + BOOL bDrawDDB1 = ( ( rSalBitmap.GetBitCount() == 1 ) && hDrawDDB ); + + if( bPrintDDB || bDrawDDB1 ) + { + pTmpSalBmp = new Os2SalBitmap; + pTmpSalBmp->Create( rSalBitmap, rSalBitmap.GetBitCount() ); + hDrawDIB = pTmpSalBmp->ImplGethDIB(); + } + else + hDrawDIB = rSalBitmap.ImplGethDIB(); + + if( hDrawDIB ) + { + HANDLE hSubst = rSalBitmap.ImplGethDIB1Subst(); + POINTL pts[ 4 ]; + BITMAPINFO2* pBI = (BITMAPINFO2*) hDrawDIB; + BITMAPINFOHEADER2* pBIH = (BITMAPINFOHEADER2*) pBI; + const long nHeight = pBIH->cy; + long nInfoSize = *(ULONG*) pBI + rSalBitmap.ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGB2 ); + BYTE* pBits = (BYTE*) pBI + nInfoSize; + + pts[0].x = pPosAry->mnDestX; + pts[0].y = nScreenHeight - pPosAry->mnDestY - pPosAry->mnDestHeight; + pts[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth - 1; + pts[1].y = nScreenHeight - pPosAry->mnDestY - 1; + + pts[2].x = pPosAry->mnSrcX; + pts[2].y = nHeight - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight ); + pts[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth; + pts[3].y = nHeight - pPosAry->mnSrcY; + + // if we've got a 1Bit DIB, we create a 4Bit substitute + if( ( pBIH->cBitCount == 1 ) && !hSubst ) + { + // create 4Bit substitute + hSubst = Os2SalBitmap::ImplCreateDIB4FromDIB1( hDrawDIB ); + + // replace substitute only, if it is no temporary SalBitmap + if( !( bPrintDDB || bDrawDDB1 ) ) + ( (Os2SalBitmap&) rSalBitmap ).ImplReplacehDIB1Subst( hSubst ); + } + + if( hSubst ) + { + pBI = (BITMAPINFO2*) hSubst; + pBIH = (BITMAPINFOHEADER2*) pBI; + nInfoSize = *(ULONG*) pBI + rSalBitmap.ImplGetDIBColorCount( hSubst ) * sizeof( RGB2 ); + pBits = (BYTE*) pBI + nInfoSize; + } + + if( bPrinter ) + { + BYTE* pDummy; + + // expand 8Bit-DIB's to 24Bit-DIB's, because some printer drivers + // have problems to print these DIB's (strange) + if( pBIH->cBitCount == 8 && pBIH->ulCompression == BCA_UNCOMP ) + { + const long nWidth = pBIH->cx; + const long nHeight = pBIH->cy; + const long nWidthAl8 = AlignedWidth4Bytes( nWidth * 8 ); + const long nWidthAl24 = AlignedWidth4Bytes( nWidth * 24 ); + const long nNewImageSize = nHeight * nWidthAl24; + BITMAPINFOHEADER2* pNewInfo; + + pDummy = new BYTE[ sizeof( BITMAPINFO2 ) + nNewImageSize ]; + memset( pDummy, 0, sizeof( BITMAPINFO2 ) ); + + pNewInfo = (BITMAPINFOHEADER2*) pDummy; + pNewInfo->cbFix = sizeof( BITMAPINFOHEADER2 ); + pNewInfo->cx = nWidth; + pNewInfo->cy = nHeight; + pNewInfo->cPlanes = 1; + pNewInfo->cBitCount = 24; + pNewInfo->ulCompression = BCA_UNCOMP; + pNewInfo->cbImage = nNewImageSize; + + BYTE* pBitsSrc = (BYTE*) pBIH + nInfoSize; + BYTE* pBitsDst = pDummy + sizeof( BITMAPINFO2 ); + + for( long nY = 0UL; nY < nHeight; nY++ ) + { + BYTE* pSrcLine = pBitsSrc + nY * nWidthAl8; + BYTE* pDstLine = pBitsDst + nY * nWidthAl24; + + for( long nX = 0UL; nX < nWidth; nX++ ) + { + const RGB2& rQuad = pBI->argbColor[ *pSrcLine++ ]; + + *pDstLine++ = rQuad.bBlue; + *pDstLine++ = rQuad.bGreen; + *pDstLine++ = rQuad.bRed; + } + } + + nInfoSize = sizeof( BITMAPINFO2 ); + } + else + { + const long nImageSize = ( pBIH->cbImage ? pBIH->cbImage : ( pBIH->cy * AlignedWidth4Bytes( pBIH->cx * pBIH->cBitCount ) ) ); + const long nTotalSize = nInfoSize + nImageSize; + + pDummy = new BYTE[ nTotalSize ]; + memcpy( pDummy, pBI, nTotalSize ); + } + + GpiDrawBits( hPS, pDummy + nInfoSize, (BITMAPINFO2*) pDummy, 4L, pts, nDrawMode, BBO_IGNORE ); + delete[] pDummy; + } + else + GpiDrawBits( hPS, pBits, pBI, 4L, pts, nDrawMode, BBO_IGNORE ); + } + else if( hDrawDDB && !bPrintDDB ) + { + POINTL pts[ 4 ]; + + pts[0].x = pPosAry->mnDestX; + pts[0].y = nScreenHeight - pPosAry->mnDestY - pPosAry->mnDestHeight; + pts[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth - 1; + pts[1].y = nScreenHeight - pPosAry->mnDestY - 1; + + pts[2].x = pPosAry->mnSrcX; + pts[2].y = rSalBitmap.GetSize().Height() - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight ); + pts[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth; + pts[3].y = rSalBitmap.GetSize().Height() - pPosAry->mnSrcY; + + GpiWCBitBlt( hPS, hDrawDDB, 4L, pts, nDrawMode, BBO_IGNORE ); +/* + HPS hDrawPS = ImplGetCachedPS( CACHED_HPS_DRAW, hDrawDDB ); + Ft2BitBlt( hPS, hDrawPS, 4, pts, nDrawMode, BBO_IGNORE ); + ImplReleaseCachedPS( CACHED_HPS_DRAW ); +*/ + } + + if( bPrintDDB || bDrawDDB1 ) + delete pTmpSalBmp; + } +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap ) +{ + ImplDrawBitmap( mhPS, mnHeight, + pPosAry, static_cast<const Os2SalBitmap&>(rSalBitmap), + mbPrinter, + mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + SalColor nTransparentColor ) +{ + DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); + //const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap); + // an FM: kann erst einmal unberuecksichtigt bleiben + drawBitmap( pPosAry, rSalBitmap ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSSalBitmap, + const SalBitmap& rSTransparentBitmap ) +{ + DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); + + const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap); + const Os2SalBitmap& rTransparentBitmap = static_cast<const Os2SalBitmap&>(rSTransparentBitmap); + + if( bFastTransparent ) + { + ImplDrawBitmap( mhPS, mnHeight, pPosAry, rTransparentBitmap, FALSE, ROP_SRCAND ); + ImplDrawBitmap( mhPS, mnHeight, pPosAry, rSalBitmap, FALSE, ROP_SRCPAINT ); + } + else + { + SalTwoRect aPosAry = *pPosAry; + int nDstX = (int) aPosAry.mnDestX; + int nDstY = (int) aPosAry.mnDestY; + int nDstWidth = (int) aPosAry.mnDestWidth; + int nDstHeight = (int) aPosAry.mnDestHeight; + HAB hAB = GetSalData()->mhAB; + HPS hPS = mhPS; + DEVOPENSTRUC aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + SIZEL aSizeL = { nDstWidth, nDstHeight }; + POINTL aPtL[ 3 ]; + + HDC hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 ); + HPS hMemPS = Ft2CreatePS( hAB, hMemDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS ); + HBITMAP hMemBitmap = ImplCreateVirDevBitmap( hMemDC, hMemPS, nDstWidth, nDstHeight, 0 ); + HBITMAP hMemOld = (HBITMAP) Ft2SetBitmap( hMemPS, hMemBitmap ); + HDC hMaskDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 ); + HPS hMaskPS = Ft2CreatePS( hAB, hMaskDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS ); + HBITMAP hMaskBitmap = ImplCreateVirDevBitmap( hMaskDC, hMaskPS, nDstWidth, nDstHeight, 0 ); + HBITMAP hMaskOld = (HBITMAP) Ft2SetBitmap( hMaskPS, hMaskBitmap ); +/* + HPS hMemPS = ImplGetCachedPS( CACHED_HPS_1, 0 ); + HPS hMaskPS = ImplGetCachedPS( CACHED_HPS_2, 0 ); +*/ + aPosAry.mnDestX = aPosAry.mnDestY = 0L; + + aPtL[ 0 ].x = 0; + aPtL[ 0 ].y = 0; + aPtL[ 1 ].x = nDstWidth; + aPtL[ 1 ].y = nDstHeight; + aPtL[ 2 ].x = nDstX; + aPtL[ 2 ].y = TY( nDstY + nDstHeight - 1 ); + + GpiBitBlt( hMemPS, hPS, 3, aPtL, ROP_SRCCOPY, BBO_IGNORE ); + ImplDrawBitmap( hMaskPS, nDstHeight, &aPosAry, rTransparentBitmap, FALSE, ROP_SRCCOPY ); + + aPtL[ 2 ].x = 0; + aPtL[ 2 ].y = 0; + + GpiBitBlt( hMemPS, hMaskPS, 3, aPtL, ROP_SRCAND, BBO_IGNORE ); + ImplDrawBitmap( hMaskPS, nDstHeight, &aPosAry, rSalBitmap, FALSE, ROP_SRCERASE ); + GpiBitBlt( hMemPS, hMaskPS, 3, aPtL, ROP_SRCPAINT, BBO_IGNORE ); + + aPtL[ 0 ].x = nDstX; + aPtL[ 0 ].y = TY( nDstY + nDstHeight - 1 ); + aPtL[ 1 ].x = nDstX + nDstWidth; + aPtL[ 1 ].y = TY( nDstY - 1 ); + + GpiBitBlt( hPS, hMemPS, 3, aPtL, ROP_SRCCOPY, BBO_IGNORE ); + + Ft2SetBitmap( hMaskPS, hMaskOld ); + Ft2DestroyPS( hMaskPS ); + DevCloseDC( hMaskDC ); + GpiDeleteBitmap( hMaskBitmap ); + + Ft2SetBitmap( hMemPS, hMemOld ); + Ft2DestroyPS( hMemPS ); + DevCloseDC( hMemDC ); + GpiDeleteBitmap( hMemBitmap ); + +/* + ImplReleaseCachedPS( CACHED_HPS_1 ); + ImplReleaseCachedPS( CACHED_HPS_2 ); +*/ + } +} + +// ----------------------------------------------------------------------- + +bool Os2SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, + const SalBitmap& rSrcBitmap, + const SalBitmap& rAlphaBmp ) +{ + // TODO(P3) implement alpha blending + return false; +} + +// ----------------------------------------------------------------------- + +bool Os2SalGraphics::drawAlphaRect( long nX, long nY, long nWidth, + long nHeight, sal_uInt8 nTransparency ) +{ + // TODO(P3) implement alpha blending + return false; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::drawMask( const SalTwoRect* pPosAry, + const SalBitmap& rSSalBitmap, + SalColor nMaskColor ) +{ + DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); + + const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap); + + SalTwoRect aPosAry = *pPosAry; + HPS hPS = mhPS; + IMAGEBUNDLE aBundle, aOldBundle; + AREABUNDLE aAreaBundle, aOldAreaBundle; + const ULONG nColor = RGBCOLOR( SALCOLOR_RED( nMaskColor ), + SALCOLOR_GREEN( nMaskColor ), + SALCOLOR_BLUE( nMaskColor ) ); + + GpiQueryAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, &aOldBundle ); + aBundle.lColor = RGBCOLOR( 0, 0, 0 ); + aBundle.lBackColor = RGBCOLOR( 0xFF, 0xFF, 0xFF ); + Ft2SetAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, 0, &aBundle ); + + GpiQueryAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL | + ABB_MIX_MODE | ABB_BACK_MIX_MODE, &aOldAreaBundle ); + aAreaBundle.lColor = nColor; + aAreaBundle.lBackColor = nColor; + aAreaBundle.usSymbol = PATSYM_SOLID; + aAreaBundle.usMixMode = FM_OVERPAINT; + aAreaBundle.usBackMixMode = BM_OVERPAINT; + Ft2SetAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL | + ABB_MIX_MODE | ABB_BACK_MIX_MODE, 0, &aAreaBundle ); + + ImplDrawBitmap( hPS, mnHeight, &aPosAry, rSalBitmap, FALSE, 0x00B8L ); + + Ft2SetAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, 0, &aOldBundle ); + Ft2SetAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL | + ABB_MIX_MODE | ABB_BACK_MIX_MODE, 0, &aOldAreaBundle ); +} + +// ----------------------------------------------------------------------- + +SalBitmap* Os2SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY ) +{ + HAB hAB = GetSalData()->mhAB; + SIZEL size = { nDX, nDY }; + Os2SalBitmap* pSalBitmap = NULL; + + // create device context (at this time allways display compatible) + DEVOPENSTRUC aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + HDC hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 ); + HPS hMemPS = Ft2CreatePS( hAB, hMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS ); + HBITMAP hMemBmp = ImplCreateVirDevBitmap( hMemDC, hMemPS, nDX, nDY, 0 ); + HBITMAP hMemOld = Ft2SetBitmap( hMemPS, hMemBmp ); + + // creation successfull? + if( hMemDC && hMemPS && hMemBmp ) + { + POINTL thePoints[ 3 ]; + + // lower-left corner of target + thePoints[ 0 ].x = 0; + thePoints[ 0 ].y = 0; + + // upper-right corner of target + thePoints[ 1 ].x = nDX; + thePoints[ 1 ].y = nDY; + + // lower-left corner of source + thePoints[ 2 ].x = nX; + thePoints[ 2 ].y = TY( nY + nDY - 1 ); + + long lHits = GpiBitBlt( hMemPS, mhPS, 3, thePoints, + mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE ); + + if( hMemPS ) + { + Ft2SetBitmap( hMemPS, hMemOld ); + Ft2DestroyPS( hMemPS ); + } + + if( hMemDC ) + DevCloseDC( hMemDC ); + + if( lHits == GPI_OK ) + { + pSalBitmap = new Os2SalBitmap; + + if( !pSalBitmap->Create( hMemBmp, FALSE, FALSE ) ) + { + delete pSalBitmap; + pSalBitmap = NULL; + } + } + } + + if( !pSalBitmap ) + GpiDeleteBitmap( hMemBmp ); + + // return pointer to SAL-Bitmap + return pSalBitmap; +} + +// ----------------------------------------------------------------------- + +SalColor Os2SalGraphics::getPixel( long nX, long nY ) +{ + POINTL aPt = { nX, TY( nY ) }; + LONG nColor = Ft2QueryPel( mhPS, &aPt ); + + return MAKE_SALCOLOR( (BYTE) ( nColor >> 16 ), (BYTE) ( nColor >> 8 ), (BYTE) nColor ); +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) +{ + if( nFlags & SAL_INVERT_TRACKFRAME ) + { + // save old vylues + LINEBUNDLE oldLb; + LINEBUNDLE lb; + GpiQueryAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, &oldLb ); + + // set linetype to short dash + lb.lColor = RGBCOLOR( 255, 255, 255 ); + lb.usMixMode = FM_XOR; + lb.usType = LINETYPE_ALTERNATE; + Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &lb ); + + // draw inverted box + POINTL aPt; + + aPt.x = nX; + aPt.y = TY( nY ); + + Ft2Move( mhPS, &aPt ); + + aPt.x = nX + nWidth - 1; + aPt.y = TY( nY + nHeight - 1 ); + + Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 ); + + // restore old values + Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &oldLb ); + + } + else + { + // save old values + AREABUNDLE oldAb; + AREABUNDLE ab; + + GpiQueryAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, &oldAb ); + + // set fill color to black + ab.lColor = RGBCOLOR( 255, 255, 255 ); + ab.usMixMode = FM_XOR; + ab.usSymbol = (nFlags & SAL_INVERT_50) ? PATSYM_DENSE5 : PATSYM_SOLID; + Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &ab ); + + // draw inverted box + POINTL aPt; + + aPt.x = nX; + aPt.y = TY( nY ); + + Ft2Move( mhPS, &aPt ); + + aPt.x = nX + nWidth - 1; + aPt.y = TY( nY + nHeight - 1 ); + + Ft2Box( mhPS, DRO_FILL, &aPt, 0, 0 ); + + // restore old values + Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &oldAb ); + } +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::invert( ULONG nPoints, const SalPoint* pPtAry, SalInvert nFlags ) +{ + if( nFlags & SAL_INVERT_TRACKFRAME ) + { + // save old vylues + LINEBUNDLE oldLb; + LINEBUNDLE lb; + GpiQueryAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, &oldLb ); + + // set linetype to short dash + lb.lColor = RGBCOLOR( 255, 255, 255 ); + lb.usMixMode = FM_XOR; + lb.usType = LINETYPE_ALTERNATE; + Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &lb ); + + // Draw Polyline + drawPolyLine( nPoints, pPtAry ); + + // restore old values + Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &oldLb ); + } + else + { + // save old values + AREABUNDLE oldAb; + AREABUNDLE ab; + + GpiQueryAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, &oldAb ); + + // set fill color to black + ab.lColor = RGBCOLOR( 255, 255, 255 ); + ab.usMixMode = FM_XOR; + ab.usSymbol = (nFlags & SAL_INVERT_50) ? PATSYM_DENSE5 : PATSYM_SOLID; + Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &ab ); + + // Draw Polyline + drawPolygon( nPoints, pPtAry ); + + // restore old values + Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &oldAb ); + } +} + diff --git a/vcl/os2/source/gdi/salgdi3.cxx b/vcl/os2/source/gdi/salgdi3.cxx new file mode 100644 index 000000000000..b25feee266e4 --- /dev/null +++ b/vcl/os2/source/gdi/salgdi3.cxx @@ -0,0 +1,1772 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salgdi3.cxx,v $ + * $Revision: 1.8 $ + * + * 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. + * + ************************************************************************/ + +#define INCL_GRE_STRINGS +#define INCL_GPI +#define INCL_DOS + +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include <svpm.h> + +#define _SV_SALGDI3_CXX +#include <tools/svwin.h> +#include <rtl/tencinfo.h> +#ifndef _OSL_FILE_HXX +#include <osl/file.hxx> +#endif +#ifndef _OSL_THREAD_HXX +#include <osl/thread.hxx> +#endif +#ifndef _OSL_PROCESS_HXX +#include <osl/process.h> +#endif +#include <vcl/svapp.hxx> +#include <saldata.hxx> +#include <salgdi.h> +#include <vcl/font.hxx> +#include <vcl/sallayout.hxx> +#include <tools/poly.hxx> +#include <tools/debug.hxx> +#include <rtl/textcvt.h> +#include <tools/debug.hxx> +#include <saldata.hxx> +#include <salgdi.h> +#ifndef _SV_OUTFONT_HXX +#include <vcl/outfont.hxx> +#endif +#include <sallayout.h> +#include <tools/poly.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> + +#ifndef __H_FT2LIB +#include <wingdi.h> +#include <ft2lib.h> +#endif + +#include "sft.hxx" + +#ifdef GCP_KERN_HACK +#include <algorithm> +#endif + +using namespace vcl; + +// ----------- +// - Inlines - +// ----------- + + +inline W32FIXED FixedFromDouble( double d ) +{ + const long l = (long) ( d * 65536. ); + return *(W32FIXED*) &l; +} + +// ----------------------------------------------------------------------- + +inline int IntTimes256FromFixed(W32FIXED f) +{ + int nFixedTimes256 = (f.value << 8) + ((f.fract+0x80) >> 8); + return nFixedTimes256; +} + +// ----------- +// - Defines - +// ----------- + +// this is a special codepage code, used to identify OS/2 symbol font. +#define SYMBOL_CHARSET 65400 + +// ======================================================================= + +UniString ImplSalGetUniString( const sal_Char* pStr, xub_StrLen nLen = STRING_LEN) +{ + return UniString( pStr, nLen, gsl_getSystemTextEncoding(), + RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT | + RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT | + RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT ); +} + +// ======================================================================= + +static USHORT ImplSalToCharSet( CharSet eCharSet ) +{ + // !!! Fuer DBCS-Systeme muss dieser Code auskommentiert werden und 0 + // !!! zurueckgegeben werden, solange die DBCS-Charsets nicht + // !!! durchgereicht werden + + switch ( eCharSet ) + { + case RTL_TEXTENCODING_IBM_437: + return 437; + + case RTL_TEXTENCODING_IBM_850: + return 850; + + case RTL_TEXTENCODING_IBM_860: + return 860; + + case RTL_TEXTENCODING_IBM_861: + return 861; + + case RTL_TEXTENCODING_IBM_863: + return 863; + + case RTL_TEXTENCODING_IBM_865: + return 865; + case RTL_TEXTENCODING_MS_1252: + return 1004; + case RTL_TEXTENCODING_SYMBOL: + return 65400; + } + + return 0; +} + +// ----------------------------------------------------------------------- + +static CharSet ImplCharSetToSal( USHORT usCodePage ) +{ + switch ( usCodePage ) + { + case 437: + return RTL_TEXTENCODING_IBM_437; + + case 850: + return RTL_TEXTENCODING_IBM_850; + + case 860: + return RTL_TEXTENCODING_IBM_860; + + case 861: + return RTL_TEXTENCODING_IBM_861; + + case 863: + return RTL_TEXTENCODING_IBM_863; + + case 865: + return RTL_TEXTENCODING_IBM_865; + case 1004: + return RTL_TEXTENCODING_MS_1252; + case 65400: + return RTL_TEXTENCODING_SYMBOL; + } + + return RTL_TEXTENCODING_DONTKNOW; +} + +// ----------------------------------------------------------------------- + +static FontFamily ImplFamilyToSal( BYTE bFamilyType ) +{ + switch ( bFamilyType ) + { + case 4: + return FAMILY_DECORATIVE; + case 3: + return FAMILY_SCRIPT; + } + + return FAMILY_DONTKNOW; +} + +// ----------------------------------------------------------------------- + +static FontWeight ImplWeightToSal( USHORT nWeight ) +{ + // Falls sich jemand an die alte Doku gehalten hat + if ( nWeight > 999 ) + nWeight /= 1000; + + switch ( nWeight ) + { + case 1: + return WEIGHT_THIN; + + case 2: + return WEIGHT_ULTRALIGHT; + + case 3: + return WEIGHT_LIGHT; + + case 4: + return WEIGHT_SEMILIGHT; + + case 5: + return WEIGHT_NORMAL; + + case 6: + return WEIGHT_SEMIBOLD; + + case 7: + return WEIGHT_BOLD; + + case 8: + return WEIGHT_ULTRABOLD; + + case 9: + return WEIGHT_BLACK; + } + + return WEIGHT_DONTKNOW; +} + +// ----------------------------------------------------------------------- + +static UniString ImpStyleNameToSal( const char* pFamilyName, + const char* pFaceName, + USHORT nLen ) +{ + if ( !nLen ) + nLen = strlen(pFamilyName); + + // strip FamilyName from FaceName + if ( strncmp( pFamilyName, pFaceName, nLen ) == 0 ) + { + USHORT nFaceLen = (USHORT)strlen( pFaceName+nLen ); + // Ist Facename laenger, schneiden wir den FamilyName ab + if ( nFaceLen > 1 ) + return UniString( pFaceName+(nLen+1), gsl_getSystemTextEncoding()); + else + return UniString(); + } + else + return UniString( pFaceName, gsl_getSystemTextEncoding()); +} + +// ----------------------------------------------------------------------- + +inline FontPitch ImplLogPitchToSal( BYTE fsType ) +{ + if ( fsType & FM_TYPE_FIXED ) + return PITCH_FIXED; + else + return PITCH_VARIABLE; +} + +// ----------------------------------------------------------------------- + +inline BYTE ImplPitchToWin( FontPitch ePitch ) +{ + if ( ePitch == PITCH_FIXED ) + return FM_TYPE_FIXED; + //else if ( ePitch == PITCH_VARIABLE ) + + return 0; +} + +// ----------------------------------------------------------------------- + +static ImplDevFontAttributes Os2Font2DevFontAttributes( const PFONTMETRICS pFontMetric) +{ + ImplDevFontAttributes aDFA; + + // get font face attributes + aDFA.meFamily = ImplFamilyToSal( pFontMetric->panose.bFamilyType); + aDFA.meWidthType = WIDTH_DONTKNOW; + aDFA.meWeight = ImplWeightToSal( pFontMetric->usWeightClass); + aDFA.meItalic = (pFontMetric->fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE; + aDFA.mePitch = ImplLogPitchToSal( pFontMetric->fsType ); + aDFA.mbSymbolFlag = (pFontMetric->usCodePage == SYMBOL_CHARSET); + + // get the font face name + // the maName field stores the font name without the style, so under OS/2 + // we must use the family name + aDFA.maName = UniString( pFontMetric->szFamilyname, gsl_getSystemTextEncoding()); + + aDFA.maStyleName = ImpStyleNameToSal( pFontMetric->szFamilyname, + pFontMetric->szFacename, + strlen( pFontMetric->szFamilyname) ); + + // get device specific font attributes + aDFA.mbOrientation = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0; + aDFA.mbDevice = (pFontMetric->fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE; + + aDFA.mbEmbeddable = false; + aDFA.mbSubsettable = false; + DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFamilyname); + if( fontType == FT2_FONTTYPE_TRUETYPE && !aDFA.mbDevice) + aDFA.mbSubsettable = true; + // for now we can only embed Type1 fonts + if( fontType == FT2_FONTTYPE_TYPE1 ) + aDFA.mbEmbeddable = true; + + // heuristics for font quality + // - standard-type1 > opentypeTT > truetype > non-standard-type1 > raster + // - subsetting > embedding > none + aDFA.mnQuality = 0; + if( fontType == FT2_FONTTYPE_TRUETYPE ) + aDFA.mnQuality += 50; + if( aDFA.mbSubsettable ) + aDFA.mnQuality += 200; + else if( aDFA.mbEmbeddable ) + aDFA.mnQuality += 100; + + // #i38665# prefer Type1 versions of the standard postscript fonts + if( aDFA.mbEmbeddable ) + { + if( aDFA.maName.EqualsAscii( "AvantGarde" ) + || aDFA.maName.EqualsAscii( "Bookman" ) + || aDFA.maName.EqualsAscii( "Courier" ) + || aDFA.maName.EqualsAscii( "Helvetica" ) + || aDFA.maName.EqualsAscii( "NewCenturySchlbk" ) + || aDFA.maName.EqualsAscii( "Palatino" ) + || aDFA.maName.EqualsAscii( "Symbol" ) + || aDFA.maName.EqualsAscii( "Times" ) + || aDFA.maName.EqualsAscii( "ZapfChancery" ) + || aDFA.maName.EqualsAscii( "ZapfDingbats" ) ) + aDFA.mnQuality += 500; + } + + aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW; + aDFA.meAntiAlias = ANTIALIAS_DONTKNOW; + + // TODO: add alias names + + return aDFA; +} + +// ======================================================================= + +// ----------------------------------------------------------------------- + +// ======================================================================= + +ImplOs2FontData::ImplOs2FontData( PFONTMETRICS _pFontMetric, + int nHeight, BYTE nPitchAndFamily ) +: ImplFontData( Os2Font2DevFontAttributes(_pFontMetric), 0 ), + pFontMetric( _pFontMetric ), + meOs2CharSet( _pFontMetric->usCodePage), + mnPitchAndFamily( nPitchAndFamily ), + mpFontCharSets( NULL ), + mpUnicodeMap( NULL ), + mbDisableGlyphApi( false ), + mbHasKoreanRange( false ), + mbHasCJKSupport( false ), + mbAliasSymbolsLow( false ), + mbAliasSymbolsHigh( false ), + mnId( 0 ) +{ + SetBitmapSize( 0, nHeight ); +} + +// ----------------------------------------------------------------------- + +ImplOs2FontData::~ImplOs2FontData() +{ + delete[] mpFontCharSets; + + if( mpUnicodeMap ) + mpUnicodeMap->DeReference(); +} + +// ----------------------------------------------------------------------- + +sal_IntPtr ImplOs2FontData::GetFontId() const +{ + return mnId; +} + +// ----------------------------------------------------------------------- + +void ImplOs2FontData::UpdateFromHPS( HPS hPS ) const +{ + // short circuit if already initialized + if( mpUnicodeMap != NULL ) + return; + + ReadCmapTable( hPS ); + ReadOs2Table( hPS ); + + // even if the font works some fonts have problems with the glyph API + // => the heuristic below tries to figure out which fonts have the problem + DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFacename); + if( fontType != FT2_FONTTYPE_TRUETYPE + && (pFontMetric->fsDefn & FM_DEFN_GENERIC) == 0) + mbDisableGlyphApi = true; +} + +// ----------------------------------------------------------------------- + +#ifdef GNG_VERT_HACK +bool ImplOs2FontData::HasGSUBstitutions( HPS hPS ) const +{ + if( !mbGsubRead ) + ReadGsubTable( hPS ); + return !maGsubTable.empty(); +} + +// ----------------------------------------------------------------------- + +bool ImplOs2FontData::IsGSUBstituted( sal_Ucs cChar ) const +{ + return( maGsubTable.find( cChar ) != maGsubTable.end() ); +} +#endif // GNG_VERT_HACK + +// ----------------------------------------------------------------------- + +ImplFontCharMap* ImplOs2FontData::GetImplFontCharMap() const +{ + mpUnicodeMap->AddReference(); + return mpUnicodeMap; +} + +// ----------------------------------------------------------------------- + +static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);} +static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);} +static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));} +static inline DWORD CalcTag( const char p[4]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); } + +void ImplOs2FontData::ReadOs2Table( HPS hPS ) const +{ + const DWORD Os2Tag = CalcTag( "OS/2" ); + DWORD nLength = Ft2GetFontData( hPS, Os2Tag, 0, NULL, 0 ); + if( (nLength == FT2_ERROR) || !nLength ) + return; + std::vector<unsigned char> aOS2map( nLength ); + unsigned char* pOS2map = &aOS2map[0]; + DWORD nRC = Ft2GetFontData( hPS, Os2Tag, 0, pOS2map, nLength ); + sal_uInt32 nVersion = GetUShort( pOS2map ); + if ( nVersion >= 0x0001 && nLength >= 58 ) + { + // We need at least version 0x0001 (TrueType rev 1.66) + // to have access to the needed struct members. + sal_uInt32 ulUnicodeRange1 = GetUInt( pOS2map + 42 ); + sal_uInt32 ulUnicodeRange2 = GetUInt( pOS2map + 46 ); + sal_uInt32 ulUnicodeRange3 = GetUInt( pOS2map + 50 ); + sal_uInt32 ulUnicodeRange4 = GetUInt( pOS2map + 54 ); + + // Check for CJK capabilities of the current font + mbHasCJKSupport = (ulUnicodeRange2 & 0x2fff0000) + | (ulUnicodeRange3 & 0x00000001); + mbHasKoreanRange= (ulUnicodeRange1 & 0x10000000) + | (ulUnicodeRange2 & 0x01100000); + } +} + + +// ----------------------------------------------------------------------- + +#ifdef GNG_VERT_HACK +void ImplOs2FontData::ReadGsubTable( HPS hPS ) const +{ + mbGsubRead = true; + + // check the existence of a GSUB table + const DWORD GsubTag = CalcTag( "GSUB" ); + DWORD nRC = Ft2GetFontData( hPS, GsubTag, 0, NULL, 0 ); + if( (nRC == FT2_ERROR) || !nRC ) + return; + + // TODO: directly read the GSUB table instead of going through sft + + // get raw font file data + DWORD nFontSize = Ft2GetFontData( hPS, 0, 0, NULL, 0 ); + if( nFontSize == FT2_ERROR ) + return; + std::vector<char> aRawFont( nFontSize+1 ); + aRawFont[ nFontSize ] = 0; + DWORD nFontSize2 = Ft2GetFontData( hPS, 0, 0, (void*)&aRawFont[0], nFontSize ); + if( nFontSize != nFontSize2 ) + return; + + // open font file + sal_uInt32 nFaceNum = 0; + if( !aRawFont[0] ) // TTC candidate + nFaceNum = ~0U; // indicate "TTC font extracts only" + + TrueTypeFont* pTTFont = NULL; + ::OpenTTFontBuffer( &aRawFont[0], nFontSize, nFaceNum, &pTTFont ); + if( !pTTFont ) + return; + + // add vertically substituted characters to list + static const sal_Unicode aGSUBCandidates[] = { + 0x0020, 0x0080, // ASCII + 0x2000, 0x2600, // misc + 0x3000, 0x3100, // CJK punctutation + 0x3300, 0x3400, // squared words + 0xFF00, 0xFFF0, // halfwidth|fullwidth forms + 0 }; + + for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 ) + for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar ) + if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) ) + maGsubTable.insert( cChar ); // insert GSUBbed unicodes + + CloseTTFont( pTTFont ); + +#if 0 + TrueTypeFont* pTTFont = NULL; + ::OpenTTFont( &aRawFont[0], nFontSize, nFaceNum, &pTTFont ); + if( !pTTFont ) + return; + + // add vertically substituted characters to list + static const sal_Unicode aGSUBCandidates[] = { + 0x0020, 0x0080, // ASCII + 0x2000, 0x2600, // misc + 0x3000, 0x3100, // CJK punctutation + 0x3300, 0x3400, // squared words + 0xFF00, 0xFFF0, // halfwidth|fullwidth forms + 0 }; + + for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 ) + for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar ) + if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) ) + maGsubTable.insert( cChar ); // insert GSUBbed unicodes + + CloseTTFont( pTTFont ); +#endif +} +#endif // GNG_VERT_HACK + +// ----------------------------------------------------------------------- + +void ImplOs2FontData::ReadCmapTable( HPS hPS ) const +{ + CmapResult aResult; + aResult.mnPairCount = 0; + aResult.mbSymbolic = (meOs2CharSet == SYMBOL_CHARSET); + aResult.mbRecoded = true; + + // get the CMAP table from the font which is selected into the DC + const DWORD CmapTag = CalcTag( "cmap" ); + DWORD nRC = Ft2GetFontData( hPS, CmapTag, 0, NULL, 0 ); + // read the CMAP table if available + if( nRC != FT2_ERROR ) + { + const int nLength = nRC; + std::vector<unsigned char> aCmap( nLength ); + unsigned char* pCmap = &aCmap[0]; + nRC = Ft2GetFontData( hPS, CmapTag, 0, pCmap, nLength ); + // parse the CMAP table + if( nRC == nLength ) + ParseCMAP( pCmap, nLength, aResult ); + } else { + // we need to define at least a simple charmap, otherwise this font + // will be mapped to default charmap, and OOo doesn't accept the + // system font to match the default charmap + aResult.mnPairCount = 1; + // ImplFontCharMap destructor will free this memory + aResult.mpPairCodes = new sal_uInt32[ 2 * aResult.mnPairCount ]; + aResult.mpPairCodes[0] = 0x0020; + aResult.mpPairCodes[1] = 0x00FF; + aResult.mpStartGlyphs = NULL; + } + + mbDisableGlyphApi |= aResult.mbRecoded; + + if( aResult.mnPairCount > 0 ) + mpUnicodeMap = new ImplFontCharMap( aResult.mnPairCount, + aResult.mpPairCodes, aResult.mpStartGlyphs ); + else + mpUnicodeMap = ImplFontCharMap::GetDefaultMap(); +} + +// ======================================================================= + +void Os2SalGraphics::SetTextColor( SalColor nSalColor ) +{ + CHARBUNDLE cb; + + cb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + + // set default color attributes + Ft2SetAttrs( mhPS, + PRIM_CHAR, + CBB_COLOR, + 0, + &cb ); +} + +// ----------------------------------------------------------------------- + +USHORT Os2SalGraphics::ImplDoSetFont( ImplFontSelectData* i_pFont, float& o_rFontScale, int nFallbackLevel) +{ + +#if OSL_DEBUG_LEVEL>10 + debug_printf( "Os2SalGraphics::ImplDoSetFont\n"); +#endif + + ImplOs2FontData* pFontData = (ImplOs2FontData*)i_pFont->mpFontData; + PFONTMETRICS pFontMetric = NULL; + FATTRS aFAttrs; + BOOL bOutline = FALSE; + APIRET rc; + + memset( &aFAttrs, 0, sizeof( FATTRS ) ); + aFAttrs.usRecordLength = sizeof( FATTRS ); + + aFAttrs.lMaxBaselineExt = i_pFont->mnHeight; + aFAttrs.lAveCharWidth = i_pFont->mnWidth; + + // do we have a pointer to the FONTMETRICS of the selected font? -> use it! + if ( pFontData ) + { + pFontMetric = pFontData->GetFontMetrics(); + + bOutline = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0; + + // use match®istry fields to get correct match + aFAttrs.lMatch = pFontMetric->lMatch; + aFAttrs.idRegistry = pFontMetric->idRegistry; + aFAttrs.usCodePage = pFontMetric->usCodePage; + + if ( bOutline ) + { + aFAttrs.fsFontUse |= FATTR_FONTUSE_OUTLINE; + if ( i_pFont->mnOrientation ) + aFAttrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE; + } + else + { + aFAttrs.lMaxBaselineExt = pFontMetric->lMaxBaselineExt; + aFAttrs.lAveCharWidth = pFontMetric->lAveCharWidth; + } + + } + + // use family name for outline fonts + if ( mbPrinter ) { + // use font face name for printers because otherwise ft2lib will fail + // to select the correct font for GPI (ticket#117) + strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) ); + } else if ( !pFontMetric) { + // use OOo name if fontmetrics not available! + ByteString aName( i_pFont->maName.GetToken( 0 ), gsl_getSystemTextEncoding()); + strncpy( (char*)(aFAttrs.szFacename), aName.GetBuffer(), sizeof( aFAttrs.szFacename ) ); + } else if ( bOutline) { + // use fontmetric family name for outline fonts + strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFamilyname, sizeof( aFAttrs.szFacename ) ); + } else { + // use real font face name for bitmaps (WarpSans only) + strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) ); + } + + if ( i_pFont->meItalic != ITALIC_NONE ) + aFAttrs.fsSelection |= FATTR_SEL_ITALIC; + if ( i_pFont->meWeight > WEIGHT_MEDIUM ) + aFAttrs.fsSelection |= FATTR_SEL_BOLD; + +#if OSL_DEBUG_LEVEL>1 + if (pFontMetric->szFacename[0] == 'A') { + debug_printf( "Os2SalGraphics::SetFont hps %x lMatch '%d'\n", mhPS, pFontMetric->lMatch); + debug_printf( "Os2SalGraphics::SetFont hps %x fontmetrics facename '%s'\n", mhPS, pFontMetric->szFacename); + debug_printf( "Os2SalGraphics::SetFont hps %x fattrs facename '%s'\n", mhPS, aFAttrs.szFacename); + } +#endif + + Ft2DeleteSetId( mhPS, nFallbackLevel + LCID_BASE); + if ( (rc=Ft2CreateLogFont( mhPS, NULL, nFallbackLevel + LCID_BASE, &aFAttrs)) == GPI_ERROR ) { +#if OSL_DEBUG_LEVEL>1 + ERRORID nLastError = WinGetLastError( GetSalData()->mhAB ); + debug_printf( "Os2SalGraphics::SetFont hps %x Ft2CreateLogFont failed err %x\n", mhPS, nLastError ); +#endif + return SAL_SETFONT_REMOVEANDMATCHNEW; + } + + CHARBUNDLE aBundle; + + ULONG nAttrsDefault = 0; + ULONG nAttrs = CBB_SET; + aBundle.usSet = nFallbackLevel + LCID_BASE; + + if ( bOutline ) + { + nAttrs |= CBB_BOX; + aBundle.sizfxCell.cy = MAKEFIXED( i_pFont->mnHeight, 0 ); + + if ( !i_pFont->mnWidth ) + { + LONG nXFontRes; + LONG nYFontRes; + LONG nHeight; + + // Auf die Aufloesung achten, damit das Ergebnis auch auf + // Drucken mit 180*360 DPI stimmt. Ausserdem muss gerundet + // werden, da auf meinem OS2 beispielsweise als + // Bildschirmaufloesung 3618*3622 PixelPerMeter zurueck- + // gegeben wird + GetResolution( nXFontRes, nYFontRes ); + nHeight = i_pFont->mnHeight; + nHeight *= nXFontRes; + nHeight += nYFontRes/2; + nHeight /= nYFontRes; + aBundle.sizfxCell.cx = MAKEFIXED( nHeight, 0 ); + } + else + aBundle.sizfxCell.cx = MAKEFIXED( i_pFont->mnWidth, 0 ); + } + + // set orientation for outlinefonts + if ( i_pFont->mnOrientation ) + { + if ( bOutline ) + { + nAttrs |= CBB_ANGLE; + double alpha = (double)(i_pFont->mnOrientation); + alpha *= 0.0017453292; // *PI / 1800 + mnOrientationY = (long) (1000.0 * sin( alpha )); + mnOrientationX = (long) (1000.0 * cos( alpha )); + aBundle.ptlAngle.x = mnOrientationX; + aBundle.ptlAngle.y = mnOrientationY; + } + else + { + mnOrientationX = 1; + mnOrientationY = 0; + nAttrs |= CBB_ANGLE; + aBundle.ptlAngle.x = 1; + aBundle.ptlAngle.y = 0; + } + } + else + { + mnOrientationX = 1; + mnOrientationY = 0; + nAttrs |= CBB_ANGLE; + aBundle.ptlAngle.x = 1; + aBundle.ptlAngle.y = 0; + } + + rc = Ft2SetAttrs( mhPS, PRIM_CHAR, nAttrs, nAttrsDefault, &aBundle ); + +#if OSL_DEBUG_LEVEL>1 + FONTMETRICS aOS2Metric = {0}; + Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ); +#endif + + return 0; +} + + +USHORT Os2SalGraphics::SetFont( ImplFontSelectData* pFont, int nFallbackLevel ) +{ + + // return early if there is no new font + if( !pFont ) + { +#if 0 + // deselect still active font + if( mhDefFont ) + Ft2SetCharSet( mhPS, mhDefFont ); + // release no longer referenced font handles + for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) + { + if( mhFonts[i] ) + Ft2DeleteSetId( mhPS, mhFonts[i] ); + mhFonts[ i ] = 0; + } +#endif + mhDefFont = 0; + return 0; + } + +#if OSL_DEBUG_LEVEL>10 + debug_printf( "Os2SalGraphics::SetFont\n"); +#endif + + DBG_ASSERT( pFont->mpFontData, "WinSalGraphics mpFontData==NULL"); + mpOs2FontEntry[ nFallbackLevel ] = reinterpret_cast<ImplOs2FontEntry*>( pFont->mpFontEntry ); + mpOs2FontData[ nFallbackLevel ] = static_cast<const ImplOs2FontData*>( pFont->mpFontData ); + + ImplDoSetFont( pFont, mfFontScale, nFallbackLevel); + + if( !mhDefFont ) + { + // keep default font + mhDefFont = nFallbackLevel + LCID_BASE; + } + else + { + // release no longer referenced font handles + for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) + { + if( mhFonts[i] ) + { +#if 0 + Ft2DeleteSetId( mhPS, mhFonts[i] ); +#endif + mhFonts[i] = 0; + } + } + } + + // store new font in correct layer + mhFonts[ nFallbackLevel ] = nFallbackLevel + LCID_BASE; + + // now the font is live => update font face + if( mpOs2FontData[ nFallbackLevel ] ) + mpOs2FontData[ nFallbackLevel ]->UpdateFromHPS( mhPS ); + + if( !nFallbackLevel ) + { + mbFontKernInit = TRUE; + if ( mpFontKernPairs ) + { + delete[] mpFontKernPairs; + mpFontKernPairs = NULL; + } + mnFontKernPairCount = 0; + } + + // some printers have higher internal resolution, so their + // text output would be different from what we calculated + // => suggest DrawTextArray to workaround this problem + if ( mbPrinter ) + return SAL_SETFONT_USEDRAWTEXTARRAY; + else + return 0; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::GetFontMetric( ImplFontMetricData* pMetric ) +{ + FONTMETRICS aOS2Metric; + Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ); + +#if OSL_DEBUG_LEVEL>1 + debug_printf( "Os2SalGraphics::GetFontMetric hps %x\n", mhPS); + if (aOS2Metric.szFacename[0] == 'A') { + debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics facename '%s'\n", mhPS, aOS2Metric.szFacename); + debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics lMatch '%d'\n", mhPS, aOS2Metric.lMatch); + } +#endif + + pMetric->maName = UniString( aOS2Metric.szFamilyname, gsl_getSystemTextEncoding()); + pMetric->maStyleName = ImpStyleNameToSal( aOS2Metric.szFamilyname, + aOS2Metric.szFacename, + strlen( aOS2Metric.szFamilyname ) ); + + // device independent font attributes + pMetric->meFamily = ImplFamilyToSal( aOS2Metric.panose.bFamilyType); + pMetric->mbSymbolFlag = (aOS2Metric.usCodePage == SYMBOL_CHARSET); + pMetric->meWeight = ImplWeightToSal( aOS2Metric.usWeightClass ); + pMetric->mePitch = ImplLogPitchToSal( aOS2Metric.fsType ); + pMetric->meItalic = (aOS2Metric.fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE; + pMetric->mnSlant = 0; + + // device dependend font attributes + pMetric->mbDevice = (aOS2Metric.fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE; + pMetric->mbScalableFont = (aOS2Metric.fsDefn & FM_DEFN_OUTLINE) ? true : false; + if( pMetric->mbScalableFont ) + { + // check if there are kern pairs + // TODO: does this work with GPOS kerning? + pMetric->mbKernableFont = (aOS2Metric.sKerningPairs > 0); + } + else + { + // bitmap fonts cannot be rotated directly + pMetric->mnOrientation = 0; + // bitmap fonts have no kerning + pMetric->mbKernableFont = false; + } + + // transformation dependend font metrics + if ( aOS2Metric.fsDefn & FM_DEFN_OUTLINE ) + { + pMetric->mnWidth = aOS2Metric.lEmInc; + } + else + { + pMetric->mnWidth = aOS2Metric.lAveCharWidth; + pMetric->mnOrientation = 0; + } + pMetric->mnIntLeading = aOS2Metric.lInternalLeading; + pMetric->mnExtLeading = aOS2Metric.lExternalLeading; + pMetric->mnAscent = aOS2Metric.lMaxAscender; + pMetric->mnDescent = aOS2Metric.lMaxDescender; + + // #107888# improved metric compatibility for Asian fonts... + // TODO: assess workaround below for CWS >= extleading + // TODO: evaluate use of aWinMetric.sTypo* members for CJK + if( mpOs2FontData[0] && mpOs2FontData[0]->SupportsCJK() ) + { + pMetric->mnIntLeading += pMetric->mnExtLeading; + + // #109280# The line height for Asian fonts is too small. + // Therefore we add half of the external leading to the + // ascent, the other half is added to the descent. + const long nHalfTmpExtLeading = pMetric->mnExtLeading / 2; + const long nOtherHalfTmpExtLeading = pMetric->mnExtLeading - nHalfTmpExtLeading; + + // #110641# external leading for Asian fonts. + // The factor 0.3 has been confirmed with experiments. + long nCJKExtLeading = static_cast<long>(0.30 * (pMetric->mnAscent + pMetric->mnDescent)); + nCJKExtLeading -= pMetric->mnExtLeading; + pMetric->mnExtLeading = (nCJKExtLeading > 0) ? nCJKExtLeading : 0; + + pMetric->mnAscent += nHalfTmpExtLeading; + pMetric->mnDescent += nOtherHalfTmpExtLeading; + + // #109280# HACK korean only: increase descent for wavelines and impr + // YD win9x only + } + +} + +// ----------------------------------------------------------------------- + +ULONG Os2SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs ) +{ + DBG_ASSERT( sizeof( KERNINGPAIRS ) == sizeof( ImplKernPairData ), + "Os2SalGraphics::GetKernPairs(): KERNINGPAIRS != ImplKernPairData" ); + + if ( mbFontKernInit ) + { + if( mpFontKernPairs ) + { + delete[] mpFontKernPairs; + mpFontKernPairs = NULL; + } + mnFontKernPairCount = 0; + + { + KERNINGPAIRS* pPairs = NULL; + FONTMETRICS aOS2Metric; + Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ); + int nCount = aOS2Metric.sKerningPairs; + if( nCount ) + { +#ifdef GCP_KERN_HACK + pPairs = new KERNINGPAIRS[ nCount+1 ]; + mpFontKernPairs = pPairs; + mnFontKernPairCount = nCount; + Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs ); +#else // GCP_KERN_HACK + pPairs = (KERNINGPAIRS*)pKernPairs; + nCount = (nCount < nPairs) ? nCount : nPairs; + Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs ); + return nCount; +#endif // GCP_KERN_HACK + } + } + + mbFontKernInit = FALSE; + + std::sort( mpFontKernPairs, mpFontKernPairs + mnFontKernPairCount, ImplCmpKernData ); + } + + if( !pKernPairs ) + return mnFontKernPairCount; + else if( mpFontKernPairs ) + { + if ( nPairs < mnFontKernPairCount ) + nPairs = mnFontKernPairCount; + memcpy( pKernPairs, mpFontKernPairs, + nPairs*sizeof( ImplKernPairData ) ); + return nPairs; + } + + return 0; +} + + +// ----------------------------------------------------------------------- + +static ImplFontCharMap* pOs2DefaultImplFontCharMap = NULL; +static const sal_uInt32 pOs2DefaultRangeCodes[] = {0x0020,0x00FF}; + +ImplFontCharMap* Os2SalGraphics::GetImplFontCharMap() const +{ + if( !mpOs2FontData[0] ) + return ImplFontCharMap::GetDefaultMap(); + return mpOs2FontData[0]->GetImplFontCharMap(); +} + +// ----------------------------------------------------------------------- + +bool Os2SalGraphics::AddTempDevFont( ImplDevFontList* pFontList, + const String& rFontFileURL, const String& rFontName ) +{ +#if OSL_DEBUG_LEVEL>0 + debug_printf("Os2SalGraphics::AddTempDevFont\n"); +#endif + return false; +} + +// ----------------------------------------------------------------------- + +void Os2SalGraphics::GetDevFontList( ImplDevFontList* pList ) +{ + PFONTMETRICS pFontMetrics; + ULONG nFontMetricCount; + SalData* pSalData; + +#if OSL_DEBUG_LEVEL>0 + debug_printf("Os2SalGraphics::GetDevFontList\n"); +#endif + + // install OpenSymbol + HMODULE hMod; + ULONG ObjNum, Offset, rc; + CHAR Buff[2*_MAX_PATH]; + char drive[_MAX_DRIVE], dir[_MAX_DIR]; + char fname[_MAX_FNAME], ext[_MAX_EXT]; + // get module handle (and name) + rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff, + &Offset, (ULONG)ImplSalGetUniString); + DosQueryModuleName(hMod, sizeof(Buff), Buff); + // replace module path with font path + char* slash = strrchr( Buff, '\\'); + *slash = '\0'; + slash = strrchr( Buff, '\\'); + *slash = '\0'; + strcat( Buff, "\\SHARE\\FONTS\\TRUETYPE\\OPENS___.TTF"); + rc = GpiLoadPublicFonts( GetSalData()->mhAB, Buff); + + if ( !mbPrinter ) + { + // Bei Bildschirm-Devices cachen wir die Liste global, da + // dies im unabhaengigen Teil auch so gemacht wird und wir + // ansonsten auf geloeschten Systemdaten arbeiten koennten + pSalData = GetSalData(); + nFontMetricCount = pSalData->mnFontMetricCount; + pFontMetrics = pSalData->mpFontMetrics; + // Bei Bildschirm-Devices holen wir uns die Fontliste jedesmal neu + if ( pFontMetrics ) + { + delete pFontMetrics; + pFontMetrics = NULL; + nFontMetricCount = 0; + } + } + else + { + nFontMetricCount = mnFontMetricCount; + pFontMetrics = mpFontMetrics; + } + + // do we have to create the cached font list first? + if ( !pFontMetrics ) + { + // query the number of fonts available + LONG nTemp = 0; + nFontMetricCount = Ft2QueryFonts( mhPS, + QF_PUBLIC | QF_PRIVATE, + NULL, &nTemp, + sizeof( FONTMETRICS ), NULL ); + + // procede only if at least one is available! + if ( nFontMetricCount ) + { + // allocate memory for font list + pFontMetrics = new FONTMETRICS[nFontMetricCount]; + + // query font list + Ft2QueryFonts( mhPS, + QF_PUBLIC | QF_PRIVATE, + NULL, + (PLONG)&nFontMetricCount, + (LONG) sizeof( FONTMETRICS ), + pFontMetrics ); + } + + if ( !mbPrinter ) + { + pSalData->mnFontMetricCount = nFontMetricCount; + pSalData->mpFontMetrics = pFontMetrics; + } + else + { + mnFontMetricCount = nFontMetricCount; + mpFontMetrics = pFontMetrics; + } + } + + // copy data from the font list + for( ULONG i = 0; i < nFontMetricCount; i++ ) + { + PFONTMETRICS pFontMetric = &pFontMetrics[i]; + + // skip font starting with '@', this is an alias internally + // used by truetype engine. + if (pFontMetric->szFacename[0] == '@') + continue; + + // skip bitmap fonts (but keep WarpSans) + if ( (pFontMetric->fsDefn & FM_DEFN_OUTLINE) == 0 + && strncmp( pFontMetric->szFacename, "WarpSans", 8) ) + // Font nicht aufnehmen + continue; + + // replace '-' in facename with ' ' (for ft2lib) + char* dash = pFontMetric->szFacename; + while( (dash=strchr( dash, '-'))) + *dash++ = ' '; + + // create new font list element + ImplOs2FontData* pData = new ImplOs2FontData( pFontMetric, 0, 0 ); + + // add font list element to font list + pList->Add( pData ); + + } +} + +// ---------------------------------------------------------------------------- + +void Os2SalGraphics::GetDevFontSubstList( OutputDevice* pOutDev ) +{ +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalGraphics::GetGlyphBoundRect( long nIndex, Rectangle& rRect ) +{ + // use unity matrix + MAT2 aMat; + aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 ); + aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 ); + + UINT nGGOFlags = GGO_METRICS; + if( !(nIndex & GF_ISCHAR) ) + nGGOFlags |= GGO_GLYPH_INDEX; + nIndex &= GF_IDXMASK; + + GLYPHMETRICS aGM; + DWORD nSize = FT2_ERROR; + nSize = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGM, 0, NULL, &aMat ); + if( nSize == FT2_ERROR ) + return false; + + rRect = Rectangle( Point( +aGM.gmptGlyphOrigin.x, -aGM.gmptGlyphOrigin.y ), + Size( aGM.gmBlackBoxX, aGM.gmBlackBoxY ) ); + rRect.Left() = static_cast<int>( mfFontScale * rRect.Left() ); + rRect.Right() = static_cast<int>( mfFontScale * rRect.Right() ); + rRect.Top() = static_cast<int>( mfFontScale * rRect.Top() ); + rRect.Bottom() = static_cast<int>( mfFontScale * rRect.Bottom() ); + return true; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalGraphics::GetGlyphOutline( long nIndex, ::basegfx::B2DPolyPolygon& rB2DPolyPoly ) +{ +#if OSL_DEBUG_LEVEL>0 + debug_printf("Os2SalGraphics::GetGlyphOutline\n"); +#endif + rB2DPolyPoly.clear(); + + BOOL bRet = FALSE; + + // use unity matrix + MAT2 aMat; + aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 ); + aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 ); + + UINT nGGOFlags = GGO_NATIVE; + if( !(nIndex & GF_ISCHAR) ) + nGGOFlags |= GGO_GLYPH_INDEX; + nIndex &= GF_IDXMASK; + + GLYPHMETRICS aGlyphMetrics; + DWORD nSize1 = FT2_ERROR; + nSize1 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGlyphMetrics, 0, NULL, &aMat ); + + if( !nSize1 ) // blank glyphs are ok + bRet = TRUE; + else if( nSize1 != FT2_ERROR ) + { + BYTE* pData = new BYTE[ nSize1 ]; + ULONG nTotalCount = 0; + DWORD nSize2; + nSize2 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, + &aGlyphMetrics, nSize1, pData, &aMat ); + + if( nSize1 == nSize2 ) + { + bRet = TRUE; + + int nPtSize = 512; + Point* pPoints = new Point[ nPtSize ]; + BYTE* pFlags = new BYTE[ nPtSize ]; + + TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pData; + while( (BYTE*)pHeader < pData+nSize2 ) + { + // only outline data is interesting + if( pHeader->dwType != TT_POLYGON_TYPE ) + break; + + // get start point; next start points are end points + // of previous segment + int nPnt = 0; + + long nX = IntTimes256FromFixed( pHeader->pfxStart.x ); + long nY = IntTimes256FromFixed( pHeader->pfxStart.y ); + pPoints[ nPnt ] = Point( nX, nY ); + pFlags[ nPnt++ ] = POLY_NORMAL; + + bool bHasOfflinePoints = false; + TTPOLYCURVE* pCurve = (TTPOLYCURVE*)( pHeader + 1 ); + pHeader = (TTPOLYGONHEADER*)( (BYTE*)pHeader + pHeader->cb ); + while( (BYTE*)pCurve < (BYTE*)pHeader ) + { + int nNeededSize = nPnt + 16 + 3 * pCurve->cpfx; + if( nPtSize < nNeededSize ) + { + Point* pOldPoints = pPoints; + BYTE* pOldFlags = pFlags; + nPtSize = 2 * nNeededSize; + pPoints = new Point[ nPtSize ]; + pFlags = new BYTE[ nPtSize ]; + for( int i = 0; i < nPnt; ++i ) + { + pPoints[ i ] = pOldPoints[ i ]; + pFlags[ i ] = pOldFlags[ i ]; + } + delete[] pOldPoints; + delete[] pOldFlags; + } + + int i = 0; + if( TT_PRIM_LINE == pCurve->wType ) + { + while( i < pCurve->cpfx ) + { + nX = IntTimes256FromFixed( pCurve->apfx[ i ].x ); + nY = IntTimes256FromFixed( pCurve->apfx[ i ].y ); + ++i; + pPoints[ nPnt ] = Point( nX, nY ); + pFlags[ nPnt ] = POLY_NORMAL; + ++nPnt; + } + } + else if( TT_PRIM_QSPLINE == pCurve->wType ) + { + bHasOfflinePoints = true; + while( i < pCurve->cpfx ) + { + // get control point of quadratic bezier spline + nX = IntTimes256FromFixed( pCurve->apfx[ i ].x ); + nY = IntTimes256FromFixed( pCurve->apfx[ i ].y ); + ++i; + Point aControlP( nX, nY ); + + // calculate first cubic control point + // P0 = 1/3 * (PBeg + 2 * PQControl) + nX = pPoints[ nPnt-1 ].X() + 2 * aControlP.X(); + nY = pPoints[ nPnt-1 ].Y() + 2 * aControlP.Y(); + pPoints[ nPnt+0 ] = Point( (2*nX+3)/6, (2*nY+3)/6 ); + pFlags[ nPnt+0 ] = POLY_CONTROL; + + // calculate endpoint of segment + nX = IntTimes256FromFixed( pCurve->apfx[ i ].x ); + nY = IntTimes256FromFixed( pCurve->apfx[ i ].y ); + + if ( i+1 >= pCurve->cpfx ) + { + // endpoint is either last point in segment => advance + ++i; + } + else + { + // or endpoint is the middle of two control points + nX += IntTimes256FromFixed( pCurve->apfx[ i-1 ].x ); + nY += IntTimes256FromFixed( pCurve->apfx[ i-1 ].y ); + nX = (nX + 1) / 2; + nY = (nY + 1) / 2; + // no need to advance, because the current point + // is the control point in next bezier spline + } + + pPoints[ nPnt+2 ] = Point( nX, nY ); + pFlags[ nPnt+2 ] = POLY_NORMAL; + + // calculate second cubic control point + // P1 = 1/3 * (PEnd + 2 * PQControl) + nX = pPoints[ nPnt+2 ].X() + 2 * aControlP.X(); + nY = pPoints[ nPnt+2 ].Y() + 2 * aControlP.Y(); + pPoints[ nPnt+1 ] = Point( (2*nX+3)/6, (2*nY+3)/6 ); + pFlags[ nPnt+1 ] = POLY_CONTROL; + + nPnt += 3; + } + } + + // next curve segment + pCurve = (TTPOLYCURVE*)&pCurve->apfx[ i ]; + } + + // end point is start point for closed contour + // disabled, because Polygon class closes the contour itself + // pPoints[nPnt++] = pPoints[0]; + // #i35928# + // Added again, but add only when not yet closed + if(pPoints[nPnt - 1] != pPoints[0]) + { + if( bHasOfflinePoints ) + pFlags[nPnt] = pFlags[0]; + + pPoints[nPnt++] = pPoints[0]; + } + + // convert y-coordinates W32 -> VCL + for( int i = 0; i < nPnt; ++i ) + pPoints[i].Y() = -pPoints[i].Y(); + + // insert into polypolygon + Polygon aPoly( nPnt, pPoints, (bHasOfflinePoints ? pFlags : NULL) ); + // convert to B2DPolyPolygon + // TODO: get rid of the intermediate PolyPolygon + rB2DPolyPoly.append( aPoly.getB2DPolygon() ); + } + + delete[] pPoints; + delete[] pFlags; + } + + delete[] pData; + } + + // rescaling needed for the PolyPolygon conversion + if( rB2DPolyPoly.count() ) + { + const double fFactor((1.0/256) * mfFontScale); + rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fFactor, fFactor)); + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +// TODO: Replace this class with boost::scoped_array +class ScopedCharArray +{ +public: + inline explicit ScopedCharArray(char * pArray): m_pArray(pArray) {} + + inline ~ScopedCharArray() { delete[] m_pArray; } + + inline char * get() const { return m_pArray; } + +private: + char * m_pArray; +}; + +class ScopedFont +{ +public: + explicit ScopedFont(Os2SalGraphics & rData); + + ~ScopedFont(); + +private: + Os2SalGraphics & m_rData; + ULONG m_hOrigFont; +}; + +ScopedFont::ScopedFont(Os2SalGraphics & rData): m_rData(rData) +{ +#if 0 + m_hOrigFont = m_rData.mhFonts[0]; + m_rData.mhFonts[0] = 0; // avoid deletion of current font +#endif +} + +ScopedFont::~ScopedFont() +{ +#if 0 + if( m_hOrigFont ) + { + // restore original font, destroy temporary font + HFONT hTempFont = m_rData.mhFonts[0]; + m_rData.mhFonts[0] = m_hOrigFont; + SelectObject( m_rData.mhDC, m_hOrigFont ); + DeleteObject( hTempFont ); + } +#endif +} + +class ScopedTrueTypeFont +{ +public: + inline ScopedTrueTypeFont(): m_pFont(0) {} + + ~ScopedTrueTypeFont(); + + int open(void * pBuffer, sal_uInt32 nLen, sal_uInt32 nFaceNum); + + inline TrueTypeFont * get() const { return m_pFont; } + +private: + TrueTypeFont * m_pFont; +}; + +ScopedTrueTypeFont::~ScopedTrueTypeFont() +{ + if (m_pFont != 0) + CloseTTFont(m_pFont); +} + +int ScopedTrueTypeFont::open(void * pBuffer, sal_uInt32 nLen, + sal_uInt32 nFaceNum) +{ + OSL_ENSURE(m_pFont == 0, "already open"); + return OpenTTFontBuffer(pBuffer, nLen, nFaceNum, &m_pFont); +} + +BOOL Os2SalGraphics::CreateFontSubset( const rtl::OUString& rToFile, + const ImplFontData* pFont, long* pGlyphIDs, sal_uInt8* pEncoding, + sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo ) +{ + // create matching ImplFontSelectData + // we need just enough to get to the font file data + // use height=1000 for easier debugging (to match psprint's font units) + ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false ); + + // TODO: much better solution: move SetFont and restoration of old font to caller + ScopedFont aOldFont(*this); + SetFont( &aIFSD, 0 ); + +#if OSL_DEBUG_LEVEL > 100 + // get font metrics + TEXTMETRICA aWinMetric; + if( !::GetTextMetricsA( mhDC, &aWinMetric ) ) + return FALSE; + + DBG_ASSERT( !(aWinMetric.tmPitchAndFamily & TMPF_DEVICE), "cannot subset device font" ); + DBG_ASSERT( aWinMetric.tmPitchAndFamily & TMPF_TRUETYPE, "can only subset TT font" ); +#endif + + // get raw font file data + DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 ); + if( nFontSize1 == FT2_ERROR ) + return FALSE; + ScopedCharArray xRawFontData(new char[ nFontSize1 ]); + DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, (void*)xRawFontData.get(), nFontSize1 ); + if( nFontSize1 != nFontSize2 ) + return FALSE; + + // open font file + sal_uInt32 nFaceNum = 0; + if( !*xRawFontData.get() ) // TTC candidate + nFaceNum = ~0U; // indicate "TTC font extracts only" + + ScopedTrueTypeFont aSftTTF; + int nRC = aSftTTF.open( xRawFontData.get(), nFontSize1, nFaceNum ); + if( nRC != SF_OK ) + return FALSE; + + TTGlobalFontInfo aTTInfo; + ::GetTTGlobalFontInfo( aSftTTF.get(), &aTTInfo ); + rInfo.m_nFontType = SAL_FONTSUBSETINFO_TYPE_TRUETYPE; + rInfo.m_aPSName = ImplSalGetUniString( aTTInfo.psname ); + rInfo.m_nAscent = +aTTInfo.winAscent; + rInfo.m_nDescent = -aTTInfo.winDescent; + rInfo.m_aFontBBox = Rectangle( Point( aTTInfo.xMin, aTTInfo.yMin ), + Point( aTTInfo.xMax, aTTInfo.yMax ) ); + rInfo.m_nCapHeight = aTTInfo.yMax; // Well ... + + // subset glyphs and get their properties + // take care that subset fonts require the NotDef glyph in pos 0 + int nOrigCount = nGlyphCount; + USHORT aShortIDs[ 256 ]; + sal_uInt8 aTempEncs[ 256 ]; + + int nNotDef=-1, i; + for( i = 0; i < nGlyphCount; ++i ) + { + aTempEncs[i] = pEncoding[i]; + sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; + if( pGlyphIDs[i] & GF_ISCHAR ) + { + bool bVertical = (pGlyphIDs[i] & GF_ROTMASK) != 0; + nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical ); + if( nGlyphIdx == 0 && pFont->IsSymbolFont() ) + { + // #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX + nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; + nGlyphIdx = (nGlyphIdx & 0xF000) ? (nGlyphIdx & 0x00FF) : (nGlyphIdx | 0xF000 ); + nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical ); + } + } + aShortIDs[i] = static_cast<USHORT>( nGlyphIdx ); + if( !nGlyphIdx ) + if( nNotDef < 0 ) + nNotDef = i; // first NotDef glyph found + } + + if( nNotDef != 0 ) + { + // add fake NotDef glyph if needed + if( nNotDef < 0 ) + nNotDef = nGlyphCount++; + + // NotDef glyph must be in pos 0 => swap glyphids + aShortIDs[ nNotDef ] = aShortIDs[0]; + aTempEncs[ nNotDef ] = aTempEncs[0]; + aShortIDs[0] = 0; + aTempEncs[0] = 0; + } + DBG_ASSERT( nGlyphCount < 257, "too many glyphs for subsetting" ); + + // fill pWidth array + TTSimpleGlyphMetrics* pMetrics = + ::GetTTSimpleGlyphMetrics( aSftTTF.get(), aShortIDs, nGlyphCount, aIFSD.mbVertical ); + if( !pMetrics ) + return FALSE; + sal_uInt16 nNotDefAdv = pMetrics[0].adv; + pMetrics[0].adv = pMetrics[nNotDef].adv; + pMetrics[nNotDef].adv = nNotDefAdv; + for( i = 0; i < nOrigCount; ++i ) + pGlyphWidths[i] = pMetrics[i].adv; + free( pMetrics ); + + // write subset into destination file + rtl::OUString aSysPath; + if( osl_File_E_None != osl_getSystemPathFromFileURL( rToFile.pData, &aSysPath.pData ) ) + return FALSE; + rtl_TextEncoding aThreadEncoding = osl_getThreadTextEncoding(); + ByteString aToFile( rtl::OUStringToOString( aSysPath, aThreadEncoding ) ); + nRC = ::CreateTTFromTTGlyphs( aSftTTF.get(), aToFile.GetBuffer(), aShortIDs, + aTempEncs, nGlyphCount, 0, NULL, 0 ); + return nRC == SF_OK; +} + +//-------------------------------------------------------------------------- + +const void* Os2SalGraphics::GetEmbedFontData( const ImplFontData* pFont, + const sal_Ucs* pUnicodes, sal_Int32* pCharWidths, + FontSubsetInfo& rInfo, long* pDataLen ) +{ + // create matching ImplFontSelectData + // we need just enough to get to the font file data + ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false ); + + // TODO: much better solution: move SetFont and restoration of old font to caller + ScopedFont aOldFont(*this); + SetFont( &aIFSD, 0 ); + + // get the raw font file data + DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 ); + if( nFontSize1 == FT2_ERROR || nFontSize1 <= 0 ) + return NULL; + *pDataLen = nFontSize1; + void* pData = reinterpret_cast<void*>(new char[ nFontSize1 ]); + DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, pData, nFontSize1 ); + if( nFontSize1 != nFontSize2 ) + *pDataLen = 0; + + // get important font properties + FONTMETRICS aOS2Metric; + if (Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ) == GPI_ERROR) + *pDataLen = 0; + rInfo.m_nFontType = SAL_FONTSUBSETINFO_TYPE_TYPE1; + rInfo.m_aPSName = ImplSalGetUniString( aOS2Metric.szFacename ); + rInfo.m_nAscent = +aOS2Metric.lMaxAscender; + rInfo.m_nDescent = -aOS2Metric.lMaxDescender; + rInfo.m_aFontBBox = Rectangle( Point( 0, -aOS2Metric.lMaxDescender ), + Point( aOS2Metric.lMaxCharInc, aOS2Metric.lMaxAscender+aOS2Metric.lExternalLeading ) ); + rInfo.m_nCapHeight = aOS2Metric.lMaxAscender; // Well ... + + // get individual character widths + for( int i = 0; i < 256; ++i ) + { + LONG nCharWidth = 0; + const sal_Ucs cChar = pUnicodes[i]; + if( !Ft2QueryStringWidthW( mhPS, (LPWSTR)&cChar, 1, &nCharWidth ) ) + *pDataLen = 0; + pCharWidths[i] = nCharWidth; + } + + if( !*pDataLen ) + { + FreeEmbedFontData( pData, nFontSize1 ); + pData = NULL; + } + + return pData; +} + +//-------------------------------------------------------------------------- + +void Os2SalGraphics::FreeEmbedFontData( const void* pData, long /*nLen*/ ) +{ + delete[] reinterpret_cast<char*>(const_cast<void*>(pData)); +} + +const Ucs2SIntMap* Os2SalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded ) +{ + // TODO: even for builtin fonts we get here... why? + if( !pFont->IsEmbeddable() ) + return NULL; + + // fill the encoding vector + Ucs2SIntMap& rMap = *new Ucs2SIntMap; +#if 0 + // TODO: get correct encoding vector + ImplWinFontData* pWinFontData = reinterpret_cast<ImplWinFontData*>(pFont); + + GLYPHSET aGlyphSet; + aGlyphSet.cbThis = sizeof(aGlyphSet); + DWORD aW = ::GetFontUnicodeRanges( mhDC, &aGlyphSet); +#else + for( sal_Unicode i = 32; i < 256; ++i ) + rMap[i] = i; + if( pNonEncoded ) + *pNonEncoded = NULL; +#endif + + return &rMap; +} + +//-------------------------------------------------------------------------- + +void Os2SalGraphics::GetGlyphWidths( const ImplFontData* pFont, + bool bVertical, + Int32Vector& rWidths, + Ucs2UIntMap& rUnicodeEnc ) +{ + // create matching ImplFontSelectData + // we need just enough to get to the font file data + ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false ); + + // TODO: much better solution: move SetFont and restoration of old font to caller + ScopedFont aOldFont(*this); + + float fScale = 0.0; + ImplDoSetFont( &aIFSD, fScale, 0); + + if( pFont->IsSubsettable() ) + { + // get raw font file data + DWORD nFontSize1 = ::Ft2GetFontData( mhPS, 0, 0, NULL, 0 ); + if( nFontSize1 == FT2_ERROR ) + return; + ScopedCharArray xRawFontData(new char[ nFontSize1 ]); + DWORD nFontSize2 = ::Ft2GetFontData( mhPS, 0, 0, (void*)xRawFontData.get(), nFontSize1 ); + if( nFontSize1 != nFontSize2 ) + return; + + // open font file + sal_uInt32 nFaceNum = 0; + if( !*xRawFontData.get() ) // TTC candidate + nFaceNum = ~0U; // indicate "TTC font extracts only" + + ScopedTrueTypeFont aSftTTF; + int nRC = aSftTTF.open( xRawFontData.get(), nFontSize1, nFaceNum ); + if( nRC != SF_OK ) + return; + + int nGlyphs = GetTTGlyphCount( aSftTTF.get() ); + if( nGlyphs > 0 ) + { + rWidths.resize(nGlyphs); + std::vector<sal_uInt16> aGlyphIds(nGlyphs); + for( int i = 0; i < nGlyphs; i++ ) + aGlyphIds[i] = sal_uInt16(i); + TTSimpleGlyphMetrics* pMetrics = ::GetTTSimpleGlyphMetrics( aSftTTF.get(), + &aGlyphIds[0], + nGlyphs, + bVertical ? 1 : 0 ); + if( pMetrics ) + { + for( int i = 0; i< nGlyphs; i++ ) + rWidths[i] = pMetrics[i].adv; + free( pMetrics ); + rUnicodeEnc.clear(); + } + const ImplOs2FontData* pWinFont = static_cast<const ImplOs2FontData*>(pFont); + ImplFontCharMap* pMap = pWinFont->GetImplFontCharMap(); + DBG_ASSERT( pMap && pMap->GetCharCount(), "no map" ); + + int nCharCount = pMap->GetCharCount(); + sal_uInt32 nChar = pMap->GetFirstChar(); + for( int i = 0; i < nCharCount; i++ ) + { + if( nChar < 0x00010000 ) + { + sal_uInt16 nGlyph = ::MapChar( aSftTTF.get(), + static_cast<sal_uInt16>(nChar), + bVertical ? 1 : 0 ); + if( nGlyph ) + rUnicodeEnc[ static_cast<sal_Unicode>(nChar) ] = nGlyph; + } + nChar = pMap->GetNextChar( nChar ); + } + } + } + else if( pFont->IsEmbeddable() ) + { + // get individual character widths + rWidths.clear(); + rUnicodeEnc.clear(); + rWidths.reserve( 224 ); + for( sal_Unicode i = 32; i < 256; ++i ) + { + int nCharWidth = 0; + if( Ft2QueryStringWidthW( mhPS, (LPWSTR)&i, 1, (LONG*)&nCharWidth ) ) + { + rUnicodeEnc[ i ] = rWidths.size(); + rWidths.push_back( nCharWidth ); + } + } + } +} + +//-------------------------------------------------------------------------- + +void Os2SalGraphics::DrawServerFontLayout( const ServerFontLayout& ) +{} + +//-------------------------------------------------------------------------- + +SystemFontData Os2SalGraphics::GetSysFontData( int nFallbacklevel ) const +{ + SystemFontData aSysFontData; + + if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1; + if (nFallbacklevel < 0 ) nFallbacklevel = 0; + + aSysFontData.nSize = sizeof( SystemFontData ); + aSysFontData.hFont = mhFonts[nFallbacklevel]; + aSysFontData.bFakeBold = false; + aSysFontData.bFakeItalic = false; + aSysFontData.bAntialias = true; + aSysFontData.bVerticalCharacterType = false; + + return aSysFontData; +} + +//-------------------------------------------------------------------------- diff --git a/vcl/os2/source/gdi/salprn.cxx b/vcl/os2/source/gdi/salprn.cxx new file mode 100644 index 000000000000..a31a4bb779f8 --- /dev/null +++ b/vcl/os2/source/gdi/salprn.cxx @@ -0,0 +1,1836 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salprn.cxx,v $ + * $Revision: 1.6 $ + * + * 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. + * + ************************************************************************/ + +// use this define to disable the DJP support +// #define NO_DJP + +#define INCL_DOSMODULEMGR +#define INCL_DEV +#define INCL_SPL +#define INCL_SPLERRORS +#define INCL_SPLDOSPRINT +#define INCL_DEVDJP + +#define INCL_GPI +#define INCL_DOSSEMAPHORES +#define INCL_PM +#include <svpm.h> +#include <pmdjp.h> + +#include <string.h> + +#define _SV_SALPRN_CXX +#include <tools/debug.hxx> +#include <saldata.hxx> +#include <salinst.h> +#include <salgdi.h> +#include <salframe.h> +#include <vcl/salptype.hxx> +#include <salprn.h> +#include <vcl/print.h> +#include <vcl/jobset.h> + +#ifndef __H_FT2LIB +#include <wingdi.h> +#include <ft2lib.h> +#endif + +// ======================================================================= + +// ----------------------- +// - struct ImplFormInfo - +// ----------------------- + +struct ImplFormInfo +{ + long mnPaperWidth; + long mnPaperHeight; +#ifndef NO_DJP + DJPT_PAPERSIZE mnId; +#endif +}; + +// ======================================================================= + +// ----------------------- +// - struct ImplTrayInfo - +// ----------------------- + +struct ImplTrayInfo +{ + CHAR maName[32]; + CHAR maDisplayName[64]; + DJPT_TRAYTYPE mnId; + + ImplTrayInfo( const char* pTrayName, + const char* pTrayDisplayName ) + { + strcpy( maName, pTrayName); + strcpy( maDisplayName, pTrayDisplayName); + } +}; + +// ======================================================================= + +struct ImplQueueSalSysData +{ + ByteString maPrinterName; // pszPrinters + ByteString maName; // pszName bzw. LogAddress + ByteString maOrgDriverName; // pszDriverName (maDriverName.maDeviceName) + ByteString maDriverName; // pszDriverName bis . + ByteString maDeviceName; // pszDriverName nach . + PDRIVDATA mpDrivData; + + ImplQueueSalSysData( const ByteString& rPrinterName, + const ByteString& rName, + const ByteString& rDriverName, + const ByteString& rDeviceName, + const ByteString& rOrgDriverName, + PDRIVDATA pDrivData ); + ~ImplQueueSalSysData(); +}; + +// ----------------------------------------------------------------------- + +ImplQueueSalSysData::ImplQueueSalSysData( const ByteString& rPrinterName, + const ByteString& rName, + const ByteString& rOrgDriverName, + const ByteString& rDriverName, + const ByteString& rDeviceName, + PDRIVDATA pDrivData ) : + maPrinterName( rPrinterName ), + maName( rName ), + maOrgDriverName( rName ), + maDriverName( rDriverName ), + maDeviceName( rDeviceName ) +{ + if ( pDrivData ) + { + mpDrivData = (PDRIVDATA)new BYTE[pDrivData->cb]; + memcpy( mpDrivData, pDrivData, pDrivData->cb ); + } + else + mpDrivData = NULL; +} + +// ----------------------------------------------------------------------- + +ImplQueueSalSysData::~ImplQueueSalSysData() +{ + delete mpDrivData; +} + +// ======================================================================= + +static ULONG ImplPMQueueStatusToSal( USHORT nPMStatus ) +{ + ULONG nStatus = 0; + if ( nPMStatus & PRQ3_PAUSED ) + nStatus |= QUEUE_STATUS_PAUSED; + if ( nPMStatus & PRQ3_PENDING ) + nStatus |= QUEUE_STATUS_PENDING_DELETION; + if ( !nStatus ) + nStatus |= QUEUE_STATUS_READY; + return nStatus; +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList ) +{ + APIRET rc; + ULONG nNeeded; + ULONG nReturned; + ULONG nTotal; + + // query needed size of the buffer for the QueueInfo + rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL ); + if( nNeeded == 0 ) + return; + + // create the buffer for the QueueInfo + PCHAR pQueueData = new CHAR[nNeeded]; + + // query QueueInfos + rc = SplEnumQueue( (PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL ); + + PPRQINFO3 pPrqInfo = (PPRQINFO3)pQueueData; + for ( int i = 0; i < nReturned; i++ ) + { + // create entry for the QueueInfo array + SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo; + + ByteString aOrgDriverName( pPrqInfo->pszDriverName); + ByteString aName( pPrqInfo->pszName); + pInfo->maDriver = ::rtl::OStringToOUString (aOrgDriverName, gsl_getSystemTextEncoding()); + pInfo->maPrinterName = ::rtl::OStringToOUString (pPrqInfo->pszComment, gsl_getSystemTextEncoding()); + pInfo->maLocation = ::rtl::OStringToOUString (aName, gsl_getSystemTextEncoding()); + pInfo->mnStatus = ImplPMQueueStatusToSal( pPrqInfo->fsStatus ); + pInfo->mnJobs = pPrqInfo->cJobs; + // pInfo->maComment = !!! + + // Feststellen, ob Name doppelt + PPRQINFO3 pTempPrqInfo = (PPRQINFO3)pQueueData; + for ( int j = 0; j < nReturned; j++ ) + { + // Wenn Name doppelt, erweitern wir diesen um die Location + if ( (j != i) && + (strcmp( pPrqInfo->pszComment, pTempPrqInfo->pszComment ) == 0) ) + { + pInfo->maPrinterName += ';'; + pInfo->maPrinterName += pInfo->maLocation; + } + pTempPrqInfo++; + } + + // pszDriver in DriverName (bis .) und DeviceName (nach .) aufsplitten + PSZ pDriverName; + PSZ pDeviceName; + if ( (pDriverName = strchr( pPrqInfo->pszDriverName, '.' )) != 0 ) + { + *pDriverName = 0; + pDeviceName = pDriverName + 1; + } + else + pDeviceName = NULL; + + // Alle Bytes hinter dem DeviceNamen auf 0 initialisieren, damit + // ein memcmp vom JobSetup auch funktioniert + if ( pPrqInfo->pDriverData && + (pPrqInfo->pDriverData->cb >= sizeof( pPrqInfo->pDriverData )) ) + { + int nDeviceNameLen = strlen( pPrqInfo->pDriverData->szDeviceName ); + memset( pPrqInfo->pDriverData->szDeviceName+nDeviceNameLen, + 0, + sizeof( pPrqInfo->pDriverData->szDeviceName )-nDeviceNameLen ); + } + + // save driver data and driver names + ByteString aPrinterName( pPrqInfo->pszPrinters); + ByteString aDriverName( pPrqInfo->pszDriverName); + ByteString aDeviceName; + if ( pDeviceName ) + aDeviceName = pDeviceName; + pInfo->mpSysData = new ImplQueueSalSysData( aPrinterName, aName, + aOrgDriverName, + aDriverName, aDeviceName, + pPrqInfo->pDriverData ); + + // add queue to the list + pList->Add( pInfo ); + + // increment to next element of the QueueInfo array + pPrqInfo++; + } + + delete [] pQueueData; +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo ) +{ + APIRET rc; + ULONG nNeeded; + ULONG nReturned; + ULONG nTotal; + + // query needed size of the buffer for the QueueInfo + rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL ); + if( nNeeded == 0 ) + return; + + // create the buffer for the QueueInfo + PCHAR pQueueData = new CHAR[nNeeded]; + + // query QueueInfos + rc = SplEnumQueue( (PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL ); + + PPRQINFO3 pPrqInfo = (PPRQINFO3)pQueueData; + for ( int i = 0; i < nReturned; i++ ) + { + ImplQueueSalSysData* pSysData = (ImplQueueSalSysData*)(pInfo->mpSysData); + if ( pSysData->maPrinterName.Equals( pPrqInfo->pszPrinters ) && + pSysData->maName.Equals( pPrqInfo->pszName ) && + pSysData->maOrgDriverName.Equals( pPrqInfo->pszDriverName ) ) + { + pInfo->mnStatus = ImplPMQueueStatusToSal( pPrqInfo->fsStatus ); + pInfo->mnJobs = pPrqInfo->cJobs; + break; + } + + // increment to next element of the QueueInfo array + pPrqInfo++; + } + + delete [] pQueueData; +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) +{ + delete ((ImplQueueSalSysData*)(pInfo->mpSysData)); + delete pInfo; +} + +// ----------------------------------------------------------------------- + +XubString Os2SalInstance::GetDefaultPrinter() +{ + APIRET rc; + ULONG nNeeded; + ULONG nReturned; + ULONG nTotal; + char szQueueName[255]; + XubString aDefaultName; + + // query default queue + if ( !PrfQueryProfileString( HINI_PROFILE, SPL_INI_SPOOLER, "QUEUE", 0, szQueueName, sizeof( szQueueName ) ) ) + return aDefaultName; + + // extract first queue name + PSZ pStr; + if ( (pStr = strchr( szQueueName, ';' )) != 0 ) + *pStr = 0; + + // query needed size of the buffer for the QueueInfo + rc = SplEnumQueue( (PSZ)NULL, 3, NULL, 0, &nReturned, &nTotal, &nNeeded, NULL ); + if ( nNeeded == 0 ) + return aDefaultName; + + // create the buffer for the QueueInfo + PCHAR pQueueData = new CHAR[ nNeeded ]; + + // query QueueInfos + rc = SplEnumQueue ((PSZ)NULL, 3, pQueueData, nNeeded, &nReturned, &nTotal, &nNeeded, NULL ); + + // find printer name for default queue + PPRQINFO3 pPrqInfo = (PPRQINFO3) pQueueData; + for ( int i = 0; i < nReturned; i++ ) + { + if ( strcmp( pPrqInfo->pszName, szQueueName ) == 0 ) + { + aDefaultName = ::rtl::OStringToOUString (pPrqInfo->pszComment, gsl_getSystemTextEncoding()); + + // Feststellen, ob Name doppelt + PPRQINFO3 pTempPrqInfo = (PPRQINFO3)pQueueData; + for ( int j = 0; j < nReturned; j++ ) + { + // Wenn Name doppelt, erweitern wir diesen um die Location + if ( (j != i) && + (strcmp( pPrqInfo->pszComment, pTempPrqInfo->pszComment ) == 0) ) + { + String pszName( ::rtl::OStringToOUString (pPrqInfo->pszName, gsl_getSystemTextEncoding())); + aDefaultName += ';'; + aDefaultName += pszName; + } + pTempPrqInfo++; + } + break; + } + + // increment to next element of the QueueInfo array + pPrqInfo++; + } + + delete [] pQueueData; + + return aDefaultName; +} + +// ======================================================================= + +static void* ImplAllocPrnMemory( size_t n ) +{ + return calloc( n, 1); +} + +// ----------------------------------------------------------------------- + +inline void ImplFreePrnMemory( void* p ) +{ + free( p ); +} + +// ----------------------------------------------------------------------- + +static PDRIVDATA ImplPrnDrivData( const ImplJobSetup* pSetupData ) +{ + // Diese Funktion wird eingesetzt, damit Druckertreiber nicht auf + // unseren Daten arbeiten, da es durch Konfigurationsprobleme + // sein kann, das der Druckertreiber bei uns Daten ueberschreibt. + // Durch diese vorgehensweise werden einige Abstuerze vermieden, bzw. + // sind dadurch leichter zu finden + + if ( !pSetupData->mpDriverData ) + return NULL; + + DBG_ASSERT( ((PDRIVDATA)(pSetupData->mpDriverData))->cb == pSetupData->mnDriverDataLen, + "ImplPrnDrivData() - SetupDataLen != DriverDataLen" ); + + PDRIVDATA pDrivData = (PDRIVDATA)ImplAllocPrnMemory( pSetupData->mnDriverDataLen ); + memcpy( pDrivData, pSetupData->mpDriverData, pSetupData->mnDriverDataLen ); + return pDrivData; +} + +// ----------------------------------------------------------------------- + +static void ImplUpdateSetupData( const PDRIVDATA pDrivData, ImplJobSetup* pSetupData ) +{ + // Diese Funktion wird eingesetzt, damit Druckertreiber nicht auf + // unseren Daten arbeiten, da es durch Konfigurationsprobleme + // sein kann, das der Druckertreiber bei uns Daten ueberschreibt. + // Durch diese vorgehensweise werden einige Abstuerze vermieden, bzw. + // sind dadurch leichter zu finden + + if ( !pDrivData || !pDrivData->cb ) + { + if ( pSetupData->mpDriverData ) + rtl_freeMemory( pSetupData->mpDriverData ); + pSetupData->mpDriverData = NULL; + pSetupData->mnDriverDataLen = 0; + } + else + { + // Alle Bytes hinter dem DeviceNamen auf 0 initialisieren, damit + // ein memcmp vom JobSetup auch funktioniert + if ( pDrivData->cb >= sizeof( pDrivData ) ) + { + int nDeviceNameLen = strlen( pDrivData->szDeviceName ); + memset( pDrivData->szDeviceName+nDeviceNameLen, + 0, + sizeof( pDrivData->szDeviceName )-nDeviceNameLen ); + } + + if ( pSetupData->mpDriverData ) + { + if ( pSetupData->mnDriverDataLen != pDrivData->cb ) + rtl_freeMemory( pSetupData->mpDriverData ); + pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDrivData->cb); + } + else + pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDrivData->cb); + pSetupData->mnDriverDataLen = pDrivData->cb; + memcpy( pSetupData->mpDriverData, pDrivData, pDrivData->cb ); + } + + if ( pDrivData ) + ImplFreePrnMemory( pDrivData ); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplPaperSizeEqual( long nPaperWidth1, long nPaperHeight1, + long nPaperWidth2, long nPaperHeight2 ) +{ + return (((nPaperWidth1 >= nPaperWidth2-1) && (nPaperWidth1 <= nPaperWidth2+1)) && + ((nPaperHeight1 >= nPaperHeight2-1) && (nPaperHeight1 <= nPaperHeight2+1))); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplIsDriverDJPEnabled( HDC hDC ) +{ +#ifdef NO_DJP + return FALSE; +#else + // Ueber OS2-Ini kann DJP disablte werden + if ( !PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_USEDJP, 1 ) ) + return FALSE; + + // Testen, ob DJP-Interface am Drucker vorhanden + LONG lQuery; + APIRET rc; + + lQuery = DEVESC_QUERYSIZE; + rc = DevEscape( hDC, + DEVESC_QUERYESCSUPPORT, + sizeof( lQuery ), + (PBYTE)&lQuery, + 0, + (PBYTE)NULL ); + if ( DEV_OK != rc ) + return FALSE; + + lQuery = DEVESC_QUERYJOBPROPERTIES; + rc = DevEscape( hDC, + DEVESC_QUERYESCSUPPORT, + sizeof( lQuery ), + (PBYTE)&lQuery, + 0, + (PBYTE)NULL ); + if ( DEV_OK != rc ) + return FALSE; + + lQuery = DEVESC_SETJOBPROPERTIES; + rc = DevEscape( hDC, + DEVESC_QUERYESCSUPPORT, + sizeof( lQuery ), + (PBYTE)&lQuery, + 0, + (PBYTE)NULL ); + if ( DEV_OK != rc ) + return FALSE; + + return TRUE; +#endif +} + +// ----------------------------------------------------------------------- + +static void ImplFormatInputList( PDJP_ITEM pDJP, PQUERYTUPLE pTuple ) +{ + // Loop through the query elements + BOOL fContinue = TRUE; + do + { + pDJP->cb = sizeof (DJP_ITEM); + pDJP->ulProperty = pTuple->ulProperty; + pDJP->lType = pTuple->lType; + pDJP->ulNumReturned = 0; + pDJP->ulValue = DJP_NONE; + + // at EOL? + fContinue = DJP_NONE != pTuple->ulProperty; + + // Move to next item structure and tuplet + pDJP++; + pTuple++; + } + while ( fContinue ); +} + +// ----------------------------------------------------------------------- + +static void ImplFreeFormAndTrayList( Os2SalInfoPrinter* pOs2SalInfoPrinter ) +{ + if ( pOs2SalInfoPrinter->mnFormCount ) + { + for ( USHORT i = 0; i < pOs2SalInfoPrinter->mnFormCount; i++ ) + delete pOs2SalInfoPrinter->mpFormArray[i]; + delete [] pOs2SalInfoPrinter->mpFormArray; + pOs2SalInfoPrinter->mnFormCount = 0; + } + + if ( pOs2SalInfoPrinter->mnTrayCount ) + { + for ( USHORT i = 0; i < pOs2SalInfoPrinter->mnTrayCount; i++ ) + delete pOs2SalInfoPrinter->mpTrayArray[i]; + delete [] pOs2SalInfoPrinter->mpTrayArray; + pOs2SalInfoPrinter->mnTrayCount = 0; + } +} + +// ----------------------------------------------------------------------- + +static void ImplGetFormAndTrayList( Os2SalInfoPrinter* pOs2SalInfoPrinter, const ImplJobSetup* pSetupData ) +{ + ImplFreeFormAndTrayList( pOs2SalInfoPrinter ); + + LONG alQuery[] = + { + 0, 0, // First two members of QUERYSIZE + DJP_CJ_FORM, DJP_ALL, + DJP_CJ_TRAYNAME, DJP_ALL, + DJP_NONE, DJP_NONE // EOL marker + }; + + APIRET rc; + PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery; + PBYTE pBuffer = NULL; + LONG nAlloc = 0; + PDRIVDATA pCopyDrivData = ImplPrnDrivData( pSetupData ); + LONG nDrivDataSize = pCopyDrivData->cb; + PBYTE pDrivData = (PBYTE)pCopyDrivData; + + // find out how many bytes to allocate + pQuerySize->cb = sizeof( alQuery ); + rc = DevEscape( pOs2SalInfoPrinter->mhDC, + DEVESC_QUERYSIZE, + sizeof( alQuery ), + (PBYTE)pQuerySize, + &nDrivDataSize, + pDrivData ); + if ( DEV_OK != rc ) + { + ImplFreePrnMemory( pCopyDrivData ); + return; + } + + // allocate the memory + nAlloc = pQuerySize->ulSizeNeeded; + pBuffer = (PBYTE)new BYTE[nAlloc]; + + // set up the input + PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer; + ImplFormatInputList( pDJP, pQuerySize->aTuples ); + + // do it! + rc = DevEscape( pOs2SalInfoPrinter->mhDC, + DEVESC_QUERYJOBPROPERTIES, + nAlloc, + pBuffer, + &nDrivDataSize, + pDrivData ); + ImplFreePrnMemory( pCopyDrivData ); + + if ( (DEV_OK == rc) || (DEV_WARNING == rc) ) + { + // Loop through the query elements + PQUERYTUPLE pTuple = pQuerySize->aTuples; + while ( DJP_NONE != pTuple->ulProperty ) + { + if ( pDJP->ulProperty == DJP_CJ_FORM ) + { + if ( pDJP->ulNumReturned ) + { + PDJPT_FORM pElm = DJP_ELEMENTP( *pDJP, DJPT_FORM ); + + pOs2SalInfoPrinter->mnFormCount = pDJP->ulNumReturned; + pOs2SalInfoPrinter->mpFormArray = new PIMPLFORMINFO[pOs2SalInfoPrinter->mnFormCount]; + for( int i = 0; i < pDJP->ulNumReturned; i++, pElm++ ) + { + ImplFormInfo* pInfo = new ImplFormInfo; + pInfo->mnPaperWidth = pElm->hcInfo.cx; + pInfo->mnPaperHeight = pElm->hcInfo.cy; + pInfo->mnId = pElm->djppsFormID; + pOs2SalInfoPrinter->mpFormArray[i] = pInfo; + } + } + } + else if ( pDJP->ulProperty == DJP_CJ_TRAYNAME ) + { + if ( pDJP->ulNumReturned ) + { + PDJPT_TRAYNAME pElm = DJP_ELEMENTP( *pDJP, DJPT_TRAYNAME ); + + pOs2SalInfoPrinter->mnTrayCount = pDJP->ulNumReturned; + pOs2SalInfoPrinter->mpTrayArray = new PIMPLTRAYINFO[pOs2SalInfoPrinter->mnTrayCount]; + for( int i = 0; i < pDJP->ulNumReturned; i++, pElm++ ) + { + ImplTrayInfo* pInfo = new ImplTrayInfo( pElm->szTrayname, pElm->szDisplayTrayname ); + pInfo->mnId = pElm->djpttTrayID; + pOs2SalInfoPrinter->mpTrayArray[i] = pInfo; + } + } + } + + pDJP = DJP_NEXT_STRUCTP( pDJP ); + pTuple++; + } + } + + delete [] pBuffer; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplGetCurrentSettings( Os2SalInfoPrinter* pOs2SalInfoPrinter, ImplJobSetup* pSetupData ) +{ + // Um den aktuellen Tray zu ermitteln, brauchen wir auch die Listen dazu + if ( !pOs2SalInfoPrinter->mnFormCount ) + ImplGetFormAndTrayList( pOs2SalInfoPrinter, pSetupData ); + + LONG alQuery[] = + { + 0, 0, // First two members of QUERYSIZE + DJP_SJ_ORIENTATION, DJP_CURRENT, + DJP_CJ_FORM, DJP_CURRENT, + DJP_NONE, DJP_NONE // EOL marker + }; + + APIRET rc; + PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery; + PBYTE pBuffer = NULL; + LONG nAlloc = 0; + PDRIVDATA pCopyDrivData = ImplPrnDrivData( pSetupData ); + LONG nDrivDataSize = pCopyDrivData->cb; + PBYTE pDrivData = (PBYTE)pCopyDrivData; + BOOL bResult; + + // find out how many bytes to allocate + pQuerySize->cb = sizeof( alQuery ); + rc = DevEscape( pOs2SalInfoPrinter->mhDC, + DEVESC_QUERYSIZE, + sizeof( alQuery ), + (PBYTE)pQuerySize, + &nDrivDataSize, + pDrivData ); + if ( DEV_OK != rc ) + { + ImplFreePrnMemory( pCopyDrivData ); + return FALSE; + } + + // allocate the memory + nAlloc = pQuerySize->ulSizeNeeded; + pBuffer = (PBYTE)new BYTE[nAlloc]; + + // set up the input + PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer; + ImplFormatInputList( pDJP, pQuerySize->aTuples ); + + rc = DevEscape( pOs2SalInfoPrinter->mhDC, + DEVESC_QUERYJOBPROPERTIES, + nAlloc, + pBuffer, + &nDrivDataSize, + pDrivData ); + if ( (DEV_OK == rc) || (DEV_WARNING == rc) ) + { + // aktuelle Setup-Daten uebernehmen + ImplUpdateSetupData( pCopyDrivData, pSetupData ); + + // Loop through the query elements + PQUERYTUPLE pTuple = pQuerySize->aTuples; + while ( DJP_NONE != pTuple->ulProperty ) + { + if ( pDJP->ulProperty == DJP_SJ_ORIENTATION ) + { + if ( pDJP->ulNumReturned ) + { + PDJPT_ORIENTATION pElm = DJP_ELEMENTP( *pDJP, DJPT_ORIENTATION ); + if ( (DJP_ORI_PORTRAIT == *pElm) || (DJP_ORI_REV_PORTRAIT == *pElm) ) + pSetupData->meOrientation = ORIENTATION_PORTRAIT; + else + pSetupData->meOrientation = ORIENTATION_LANDSCAPE; + } + } + else if ( pDJP->ulProperty == DJP_CJ_FORM ) + { + if ( pDJP->ulNumReturned ) + { + PDJPT_FORM pElm = DJP_ELEMENTP( *pDJP, DJPT_FORM ); + + pSetupData->mnPaperWidth = pElm->hcInfo.cx*100; + pSetupData->mnPaperHeight = pElm->hcInfo.cy*100; + switch( pElm->djppsFormID ) + { + case DJP_PSI_A3: + pSetupData->mePaperFormat = PAPER_A3; + break; + + case DJP_PSI_A4: + pSetupData->mePaperFormat = PAPER_A4; + break; + + case DJP_PSI_A5: + pSetupData->mePaperFormat = PAPER_A5; + break; + + case DJP_PSI_B4: + pSetupData->mePaperFormat = PAPER_B4; + break; + + case DJP_PSI_B5: + pSetupData->mePaperFormat = PAPER_B5; + break; + + case DJP_PSI_LETTER: + pSetupData->mePaperFormat = PAPER_LETTER; + break; + + case DJP_PSI_LEGAL: + pSetupData->mePaperFormat = PAPER_LEGAL; + break; + + case DJP_PSI_TABLOID: + pSetupData->mePaperFormat = PAPER_TABLOID; + break; + + default: + pSetupData->mePaperFormat = PAPER_USER; + break; + } + + // Wir suchen zuerst ueber den Namen/Id und dann ueber die Id + BOOL bTrayFound = FALSE; + USHORT j; + for ( j = 0; j < pOs2SalInfoPrinter->mnTrayCount; j++ ) + { + if ( (pOs2SalInfoPrinter->mpTrayArray[j]->mnId == pElm->djpttTrayID) && + (pOs2SalInfoPrinter->mpTrayArray[j]->maName == pElm->szTrayname) ) + { + pSetupData->mnPaperBin = j; + bTrayFound = TRUE; + break; + } + } + if ( !bTrayFound ) + { + for ( j = 0; j < pOs2SalInfoPrinter->mnTrayCount; j++ ) + { + if ( pOs2SalInfoPrinter->mpTrayArray[j]->mnId == pElm->djpttTrayID ) + { + pSetupData->mnPaperBin = j; + bTrayFound = TRUE; + break; + } + } + } + // Wenn wir Ihn immer noch nicht gefunden haben, setzen + // wir ihn auf DontKnow + if ( !bTrayFound ) + pSetupData->mnPaperBin = 0xFFFF; + } + } + + pDJP = DJP_NEXT_STRUCTP( pDJP ); + pTuple++; + } + + bResult = TRUE; + } + else + { + ImplFreePrnMemory( pCopyDrivData ); + bResult = FALSE; + } + + delete [] pBuffer; + + return bResult; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplSetOrientation( HDC hPrinterDC, PDRIVDATA pDriverData, + Orientation eOrientation ) +{ + LONG alQuery[] = + { + 0, 0, // First two members of QUERYSIZE + DJP_SJ_ORIENTATION, DJP_CURRENT, + DJP_NONE, DJP_NONE // EOL marker + }; + + APIRET rc; + PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery; + PBYTE pBuffer = NULL; + LONG nAlloc = 0; + LONG nDrivDataSize = pDriverData->cb; + + // find out how many bytes to allocate + pQuerySize->cb = sizeof( alQuery ); + rc = DevEscape( hPrinterDC, + DEVESC_QUERYSIZE, + sizeof( alQuery ), + (PBYTE)pQuerySize, + &nDrivDataSize, + (PBYTE)pDriverData ); + if ( DEV_OK != rc ) + return FALSE; + + // allocate the memory + nAlloc = pQuerySize->ulSizeNeeded; + pBuffer = (PBYTE)new BYTE[nAlloc]; + + // set up the input + PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer; + ImplFormatInputList( pDJP, pQuerySize->aTuples ); + + pDJP->cb = sizeof( DJP_ITEM ); + pDJP->ulProperty = DJP_SJ_ORIENTATION; + pDJP->lType = DJP_CURRENT; + pDJP->ulValue = (eOrientation == ORIENTATION_PORTRAIT) + ? DJP_ORI_PORTRAIT + : DJP_ORI_LANDSCAPE; + + // do it! + rc = DevEscape( hPrinterDC, + DEVESC_SETJOBPROPERTIES, + nAlloc, + pBuffer, + &nDrivDataSize, + (PBYTE)pDriverData ); + + delete [] pBuffer; + + return ((DEV_OK == rc) || (DEV_WARNING == rc)); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplSetPaperSize( HDC hPrinterDC, PDRIVDATA pDriverData, + DJPT_PAPERSIZE nOS2PaperFormat ) +{ + LONG alQuery[] = + { + 0, 0, // First two members of QUERYSIZE + DJP_SJ_PAPERSIZE, DJP_CURRENT, + DJP_NONE, DJP_NONE // EOL marker + }; + + APIRET rc; + PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery; + PBYTE pBuffer = NULL; + LONG nAlloc = 0; + LONG nDrivDataSize = pDriverData->cb; + + // find out how many bytes to allocate + pQuerySize->cb = sizeof( alQuery ); + rc = DevEscape( hPrinterDC, + DEVESC_QUERYSIZE, + sizeof( alQuery ), + (PBYTE)pQuerySize, + &nDrivDataSize, + (PBYTE)pDriverData ); + if ( DEV_OK != rc ) + return FALSE; + + // allocate the memory + nAlloc = pQuerySize->ulSizeNeeded; + pBuffer = (PBYTE)new BYTE[nAlloc]; + + // set up the input + PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer; + PDJP_ITEM pStartDJP = pDJP; + ImplFormatInputList( pDJP, pQuerySize->aTuples ); + + // Neue Daten zuweisen + pDJP->cb = sizeof( DJP_ITEM ); + pDJP->ulProperty = DJP_SJ_PAPERSIZE; + pDJP->lType = DJP_CURRENT; + pDJP->ulValue = nOS2PaperFormat; + + // und setzen + rc = DevEscape( hPrinterDC, + DEVESC_SETJOBPROPERTIES, + nAlloc, + pBuffer, + &nDrivDataSize, + (PBYTE)pDriverData ); + + delete [] pBuffer; + + return ((DEV_OK == rc) || (DEV_WARNING == rc)); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplSetPaperBin( HDC hPrinterDC, PDRIVDATA pDriverData, + ImplTrayInfo* pTrayInfo ) +{ + LONG alQuery[] = + { + 0, 0, // First two members of QUERYSIZE + DJP_SJ_TRAYTYPE, DJP_CURRENT, + DJP_NONE, DJP_NONE // EOL marker + }; + + APIRET rc; + PQUERYSIZE pQuerySize = (PQUERYSIZE)alQuery; + PBYTE pBuffer = NULL; + LONG nAlloc = 0; + LONG nDrivDataSize = pDriverData->cb; + + // find out how many bytes to allocate + pQuerySize->cb = sizeof( alQuery ); + rc = DevEscape( hPrinterDC, + DEVESC_QUERYSIZE, + sizeof( alQuery ), + (PBYTE)pQuerySize, + &nDrivDataSize, + (PBYTE)pDriverData ); + if ( DEV_OK != rc ) + return FALSE; + + // allocate the memory + nAlloc = pQuerySize->ulSizeNeeded; + pBuffer = (PBYTE)new BYTE[nAlloc]; + + // set up the input + PDJP_ITEM pDJP = (PDJP_ITEM)pBuffer; + ImplFormatInputList( pDJP, pQuerySize->aTuples ); + + // Neue Daten zuweisen + pDJP->cb = sizeof( DJP_ITEM ); + pDJP->ulProperty = DJP_SJ_TRAYTYPE; + pDJP->lType = DJP_CURRENT; + pDJP->ulValue = pTrayInfo->mnId; + + // und setzen + rc = DevEscape( hPrinterDC, + DEVESC_SETJOBPROPERTIES, + nAlloc, + pBuffer, + &nDrivDataSize, + (PBYTE)pDriverData ); + + delete [] pBuffer; + + return ((DEV_OK == rc) || (DEV_WARNING == rc)); +} + +// ======================================================================= + +static BOOL ImplSalCreateInfoPrn( Os2SalInfoPrinter* pPrinter, PDRIVDATA pDriverData, + HDC& rDC, HPS& rPS ) +{ + SalData* pSalData = GetSalData(); + + // create info context + DEVOPENSTRUC devOpenStruc; + memset( &devOpenStruc, 0, sizeof( devOpenStruc ) ); + devOpenStruc.pszLogAddress = (char*)pPrinter->maName.GetBuffer(); + devOpenStruc.pszDriverName = (char*)pPrinter->maDriverName.GetBuffer(); + devOpenStruc.pdriv = pDriverData; + devOpenStruc.pszDataType = "PM_Q_STD"; + + HDC hDC = DevOpenDC( pSalData->mhAB, OD_INFO, "*", + 4, (PDEVOPENDATA)&devOpenStruc, (HDC)NULL); + if ( !hDC ) + return FALSE; + + // create presentation space + SIZEL sizel; + sizel.cx = 0; + sizel.cy = 0; + HPS hPS = Ft2CreatePS( pSalData->mhAB, hDC, &sizel, GPIA_ASSOC | GPIT_MICRO | PU_PELS ); + if ( !hPS ) + { + DevCloseDC( hDC ); + return FALSE; + } + + rDC = hDC; + rPS = hPS; + return TRUE; +} + +// ----------------------------------------------------------------------- + +static void ImplSalDestroyInfoPrn( Os2SalInfoPrinter* pPrinter ) +{ + ImplSalDeInitGraphics( pPrinter->mpGraphics); + Ft2Associate( pPrinter->mhPS, 0 ); + Ft2DestroyPS( pPrinter->mhPS ); + DevCloseDC( pPrinter->mhDC ); +} + +// ======================================================================= + +SalInfoPrinter* Os2SalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, + ImplJobSetup* pSetupData ) +{ + ImplQueueSalSysData* pSysQueueData = (ImplQueueSalSysData*)(pQueueInfo->mpSysData); + Os2SalInfoPrinter* pPrinter = new Os2SalInfoPrinter; + pPrinter->maPrinterName = pSysQueueData->maPrinterName; + pPrinter->maName = pSysQueueData->maName; + pPrinter->maDriverName = pSysQueueData->maDriverName; + pPrinter->maDeviceName = pSysQueueData->maDeviceName; + + // Nur Setup-Daten uebernehmen, wenn Treiber und Laenge der Treiberdaten + // uebereinstimmt + PDRIVDATA pDriverData; + BOOL bUpdateDriverData; + if ( pSetupData->mpDriverData && pSysQueueData->mpDrivData && + (pSetupData->mnSystem == JOBSETUP_SYSTEM_OS2) && + (pSetupData->mnDriverDataLen == pSysQueueData->mpDrivData->cb) && + (strcmp( ((PDRIVDATA)pSetupData->mpDriverData)->szDeviceName, + pSysQueueData->mpDrivData->szDeviceName ) == 0) ) + { + pDriverData = PDRIVDATA( pSetupData->mpDriverData ); + bUpdateDriverData = FALSE; + } + else + { + pDriverData = pSysQueueData->mpDrivData; + bUpdateDriverData = TRUE; + } + if ( pDriverData ) + pPrinter->maJobSetupDeviceName = pDriverData->szDeviceName; + + if ( !ImplSalCreateInfoPrn( pPrinter, pDriverData, + pPrinter->mhDC, + pPrinter->mhPS ) ) + { + delete pPrinter; + return NULL; + } + + // create graphics object for output + Os2SalGraphics* pGraphics = new Os2SalGraphics; + pGraphics->mhDC = pPrinter->mhDC; + pGraphics->mhPS = pPrinter->mhPS; + pGraphics->mhWnd = 0; + pGraphics->mbPrinter = TRUE; + pGraphics->mbVirDev = FALSE; + pGraphics->mbWindow = FALSE; + pGraphics->mbScreen = FALSE; + + ImplSalInitGraphics( pGraphics ); + pPrinter->mpGraphics = pGraphics; + + // check printer driver for DJP support + pPrinter->mbDJPSupported = ImplIsDriverDJPEnabled( pPrinter->mhDC ); + + if ( bUpdateDriverData ) + { + if ( pSetupData->mpDriverData ) + rtl_freeMemory( pSetupData->mpDriverData); + pSetupData->mpDriverData = (BYTE*)rtl_allocateMemory( pDriverData->cb); + memcpy( pSetupData->mpDriverData, pDriverData, pDriverData->cb ); + pSetupData->mnDriverDataLen = pDriverData->cb; + } + + // retrieve current settings from printer driver and store them to system independend data! + if ( pPrinter->mbDJPSupported ) + ImplGetCurrentSettings( pPrinter, pSetupData ); + pSetupData->mnSystem = JOBSETUP_SYSTEM_OS2; + + return pPrinter; +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) +{ + delete pPrinter; +} + +// ======================================================================= + +Os2SalInfoPrinter::Os2SalInfoPrinter() +{ + mhDC = 0; + mhPS = 0; + mpGraphics = NULL; + mbGraphics = FALSE; + mbDJPSupported = FALSE; + mnFormCount = 0; + mpFormArray = NULL; + mnTrayCount = 0; + mpTrayArray = NULL; +} + +// ----------------------------------------------------------------------- + +Os2SalInfoPrinter::~Os2SalInfoPrinter() +{ + if ( mpGraphics ) + { + ImplSalDestroyInfoPrn( this ); + delete mpGraphics; + } + + ImplFreeFormAndTrayList( this ); +} + +// ----------------------------------------------------------------------- + +SalGraphics* Os2SalInfoPrinter::GetGraphics() +{ + if ( mbGraphics ) + return NULL; + + if ( mpGraphics ) + mbGraphics = TRUE; + + return mpGraphics; +} + +// ----------------------------------------------------------------------- + +void Os2SalInfoPrinter::ReleaseGraphics( SalGraphics* ) +{ + mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData ) +{ + PDRIVDATA pDrivData = ImplPrnDrivData( pSetupData ); + if ( !pDrivData ) + return FALSE; + + APIRET rc = DevPostDeviceModes( GetSalData()->mhAB, pDrivData, + maDriverName.GetBuffer(), + maDeviceName.GetBuffer(), + maPrinterName.GetBuffer(), + DPDM_POSTJOBPROP ); + if ( rc == DEV_OK ) + { + ImplUpdateSetupData( pDrivData, pSetupData ); + + // update DC and PS + HDC hDC; + HPS hPS; + if ( !ImplSalCreateInfoPrn( this, (PDRIVDATA)(pSetupData->mpDriverData), hDC, hPS ) ) + return FALSE; + + // Alten Printer DC/PS zerstoeren + ImplSalDestroyInfoPrn( this ); + + // Neue Daten setzen und initialisieren + mhDC = hDC; + mhPS = hPS; + mpGraphics->mhDC = mhDC; + mpGraphics->mhPS = mhPS; + ImplSalInitGraphics( mpGraphics ); + + // retrieve current settings from printer driver and store them to system independend data! + ImplFreeFormAndTrayList( this ); + if ( mbDJPSupported ) + ImplGetCurrentSettings( this, pSetupData ); + + return TRUE; + } + else + { + ImplFreePrnMemory( pDrivData ); + return FALSE; + } +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData ) +{ + // Wir koennen nur Treiberdaten von OS2 setzen + if ( pSetupData->mnSystem != JOBSETUP_SYSTEM_OS2 ) + return FALSE; + + PDRIVDATA pNewDrivData = (PDRIVDATA)(pSetupData->mpDriverData); + if ( !pNewDrivData ) + return FALSE; + + // Testen, ob Printerdaten fuer den gleichen Printer uebergeben werden, + // da einige Treiber zu Abstuerzen neigen, wenn Daten von einem anderen + // Printer gesetzt werden + if ( !maJobSetupDeviceName.Equals( pNewDrivData->szDeviceName )) + return FALSE; + + // update DC and PS + HDC hDC; + HPS hPS; + if ( !ImplSalCreateInfoPrn( this, pNewDrivData, hDC, hPS ) ) + return FALSE; + + // Alten Printer DC/PS zerstoeren + ImplSalDestroyInfoPrn( this ); + + // Neue Daten setzen und initialisieren + mhDC = hDC; + mhPS = hPS; + mpGraphics->mhDC = mhDC; + mpGraphics->mhPS = mhPS; + ImplSalInitGraphics( mpGraphics ); + + // retrieve current settings from printer driver and store them to system independend data! + ImplFreeFormAndTrayList( this ); + if ( mbDJPSupported ) + ImplGetCurrentSettings( this, pSetupData ); + + return TRUE; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalInfoPrinter::SetData( ULONG nFlags, ImplJobSetup* pSetupData ) +{ + // needs DJP support + if ( !mbDJPSupported ) + return FALSE; + + PDRIVDATA pDrivData = ImplPrnDrivData( pSetupData ); + + if ( !pDrivData ) + return FALSE; + + BOOL bOK = FALSE; + + // set orientation + if ( nFlags & SAL_JOBSET_ORIENTATION ) + { + if ( ImplSetOrientation( mhDC, pDrivData, pSetupData->meOrientation ) ) + bOK = TRUE; + } + + // set paper size + if ( nFlags & SAL_JOBSET_PAPERSIZE ) + { + // Papierformat ermitteln + DJPT_PAPERSIZE nOS2PaperFormat; + switch ( pSetupData->mePaperFormat ) + { + case PAPER_A3: + nOS2PaperFormat = DJP_PSI_A3; + break; + + case PAPER_A4: + nOS2PaperFormat = DJP_PSI_A4; + break; + + case PAPER_A5: + nOS2PaperFormat = DJP_PSI_A5; + break; + + case PAPER_B4: + nOS2PaperFormat = DJP_PSI_B4; + break; + + case PAPER_B5: + nOS2PaperFormat = DJP_PSI_B5; + break; + + case PAPER_LETTER: + nOS2PaperFormat = DJP_PSI_LETTER; + break; + + case PAPER_LEGAL: + nOS2PaperFormat = DJP_PSI_LEGAL; + break; + + case PAPER_TABLOID: + nOS2PaperFormat = DJP_PSI_TABLOID; + break; + + default: + { + nOS2PaperFormat = DJP_PSI_NONE; + // OS2 rechnet in Millimetern + long nPaperWidth = pSetupData->mnPaperWidth / 100; + long nPaperHeight = pSetupData->mnPaperHeight / 100; + // Ansonsten ueber die Papiergroesse suchen + for( int i = 0; i < mnFormCount; i++ ) + { + ImplFormInfo* pFormInfo = mpFormArray[i]; + if ( ImplPaperSizeEqual( nPaperWidth, nPaperHeight, + pFormInfo->mnPaperWidth, pFormInfo->mnPaperHeight ) ) + { + nOS2PaperFormat = pFormInfo->mnId; + break; + } + } + } + break; + } + + if ( nOS2PaperFormat != DJP_PSI_NONE ) + { + if ( ImplSetPaperSize( mhDC, pDrivData, nOS2PaperFormat ) ) + bOK = TRUE; + } + } + + // set paper tray + if ( (nFlags & SAL_JOBSET_PAPERBIN) && (pSetupData->mnPaperBin < mnTrayCount) ) + { + if ( ImplSetPaperBin( mhDC, pDrivData, + mpTrayArray[pSetupData->mnPaperBin] ) ) + bOK = TRUE; + } + + if ( bOK ) + { + ImplUpdateSetupData( pDrivData, pSetupData ); + + // query current driver settings + ImplFreeFormAndTrayList( this ); + if ( ImplGetCurrentSettings( this, pSetupData ) ) + { + // update DC and PS + HDC hDC; + HPS hPS; + if ( ImplSalCreateInfoPrn( this, (PDRIVDATA)(pSetupData->mpDriverData), hDC, hPS ) ) + { + // Alten Printer DC/PS zerstoeren + ImplSalDestroyInfoPrn( this ); + + // Neue Daten setzen und initialisieren + mhDC = hDC; + mhPS = hPS; + mpGraphics->mhDC = mhDC; + mpGraphics->mhPS = mhPS; + ImplSalInitGraphics( mpGraphics ); + } + else + bOK = FALSE; + } + else + bOK = FALSE; + } + + return bOK; +} + +// ----------------------------------------------------------------------- + +ULONG Os2SalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pJobSetup ) +{ + if ( !mbDJPSupported ) + return 1; + + // init paperbinlist if empty + if ( !mnTrayCount ) + ImplGetFormAndTrayList( this, pJobSetup ); + + // Wir haben immer einen PaperTray und wenn, das eben einen ohne + // Namen + if ( !mnTrayCount ) + return 1; + else + return mnTrayCount; +} + +// ----------------------------------------------------------------------- + +XubString Os2SalInfoPrinter::GetPaperBinName( const ImplJobSetup* pJobSetup, + ULONG nPaperBin ) +{ + XubString aPaperBinName; + + if ( mbDJPSupported ) + { + // init paperbinlist if empty + if ( !mnTrayCount ) + ImplGetFormAndTrayList( this, pJobSetup ); + + if ( nPaperBin < mnTrayCount ) + aPaperBinName = ::rtl::OStringToOUString (mpTrayArray[nPaperBin]->maDisplayName, gsl_getSystemTextEncoding()); + } + + return aPaperBinName; +} + +// ----------------------------------------------------------------------- + +ULONG Os2SalInfoPrinter::GetCapabilities( const ImplJobSetup*, USHORT nType ) +{ + switch ( nType ) + { + case PRINTER_CAPABILITIES_SUPPORTDIALOG: + return TRUE; + case PRINTER_CAPABILITIES_COPIES: + return 0xFFFF; + case PRINTER_CAPABILITIES_COLLATECOPIES: + return 0; + case PRINTER_CAPABILITIES_SETORIENTATION: + case PRINTER_CAPABILITIES_SETPAPERBIN: + case PRINTER_CAPABILITIES_SETPAPERSIZE: + case PRINTER_CAPABILITIES_SETPAPER: + return mbDJPSupported; + } + + return 0; +} + +// ----------------------------------------------------------------------- + +void Os2SalInfoPrinter::GetPageInfo( const ImplJobSetup*, + long& rOutWidth, long& rOutHeight, + long& rPageOffX, long& rPageOffY, + long& rPageWidth, long& rPageHeight ) +{ + HDC hDC = mhDC; + + // search current form + HCINFO aInfo; + int nForms = DevQueryHardcopyCaps( hDC, 0, 0, &aInfo ); + for( int i = 0; i < nForms; i++ ) + { + if ( DevQueryHardcopyCaps( hDC, i, 1, &aInfo ) >= 0 ) + { + if ( aInfo.flAttributes & HCAPS_CURRENT ) + { + // query resolution + long nXResolution; + long nYResolution; + DevQueryCaps( hDC, CAPS_HORIZONTAL_RESOLUTION, 1, &nXResolution ); + DevQueryCaps( hDC, CAPS_VERTICAL_RESOLUTION, 1, &nYResolution ); + rPageOffX = aInfo.xLeftClip * nXResolution / 1000; + rPageOffY = (aInfo.cy-aInfo.yTopClip) * nYResolution / 1000; + rPageWidth = aInfo.cx * nXResolution / 1000; + rPageHeight = aInfo.cy * nYResolution / 1000; + rOutWidth = aInfo.xPels; + rOutHeight = aInfo.yPels; + return; + } + } + } + + // use device caps if no form selected/found + long lCapsWidth = 0; + long lCapsHeight = 0; + DevQueryCaps( hDC, CAPS_WIDTH, 1L, &lCapsWidth ); + DevQueryCaps( hDC, CAPS_HEIGHT, 1L, &lCapsHeight ); + rPageOffX = 0; + rPageOffY = 0; + rOutWidth = lCapsWidth; + rOutHeight = lCapsHeight; + rPageWidth = rOutWidth; + rPageHeight = rOutHeight; +} + +// ======================================================================= + +static BOOL ImplIsDriverPrintDJPEnabled( HDC hDC ) +{ +#ifdef NO_DJP + return FALSE; +#else + // Ueber OS2-Ini kann DJP disablte werden + if ( !PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_PRINTDJP, 1 ) ) + return FALSE; + + // Testen, ob DJP-Interface am Drucker vorhanden + LONG lQuery; + APIRET rc; + + lQuery = DEVESC_QUERYSIZE; + rc = DevEscape( hDC, + DEVESC_QUERYESCSUPPORT, + sizeof( lQuery ), + (PBYTE)&lQuery, + 0, + (PBYTE)NULL ); + if ( DEV_OK != rc ) + return FALSE; + + return TRUE; +#endif +} + +// ======================================================================= + +SalPrinter* Os2SalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter ) +{ + Os2SalPrinter* pPrinter = new Os2SalPrinter; + pPrinter->mpInfoPrinter = static_cast<Os2SalInfoPrinter*>(pInfoPrinter); + return pPrinter; +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::DestroyPrinter( SalPrinter* pPrinter ) +{ + delete pPrinter; +} + +// ======================================================================= + +Os2SalPrinter::Os2SalPrinter() +{ + mhDC = 0; + mhPS = 0; + mpGraphics = NULL; + mbAbort = FALSE; + mbPrintDJPSupported = FALSE; +} + +// ----------------------------------------------------------------------- + +Os2SalPrinter::~Os2SalPrinter() +{ +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalPrinter::StartJob( const XubString* pFileName, + const XubString& rJobName, + const XubString& rAppName, + ULONG nCopies, + bool bCollate, + bool bDirect, + ImplJobSetup* pSetupData ) +{ + DEVOPENSTRUC aDevOpenStruc; + LONG lType; + APIRET rc; + + // prepare queue information + memset( &aDevOpenStruc, 0, sizeof( aDevOpenStruc ) ); + aDevOpenStruc.pszDriverName = (PSZ)(mpInfoPrinter->maDriverName.GetBuffer()); + + // print into file? + if ( pFileName ) + { + aDevOpenStruc.pszLogAddress = (PSZ)pFileName->GetBuffer(); + aDevOpenStruc.pszDataType = "PM_Q_RAW"; + lType = OD_DIRECT; + } + else + { + aDevOpenStruc.pszLogAddress = (PSZ)(mpInfoPrinter->maName.GetBuffer()); + if ( PrfQueryProfileInt( HINI_PROFILE, SAL_PROFILE_APPNAME, SAL_PROFILE_PRINTRAW, 0 ) ) + aDevOpenStruc.pszDataType = "PM_Q_RAW"; + else + aDevOpenStruc.pszDataType = "PM_Q_STD"; + lType = OD_QUEUED; + } + +#if 0 // YD FIXME + // Set comment (AppName nur bis zum 1. Space-Zeichen nehmen) + const xub_Unicode* pComment = rAppName; + USHORT nCommentLen = 0; + memset( maCommentBuf, 0, sizeof( maCommentBuf ) ); + while ( (nCommentLen < 32) && + (((*pComment >= 'a') && (*pComment <= 'z')) || + ((*pComment >= 'A') && (*pComment <= 'Z')) || + ((*pComment >= '0') && (*pComment <= '9')) || + (*pComment == '-'))) + { + maCommentBuf[nCommentLen] = (char)(*pComment); + nCommentLen++; + pComment++; + } + aDevOpenStruc.pszComment = (PSZ)maCommentBuf; +#endif + ByteString jobName( rJobName, gsl_getSystemTextEncoding()); + aDevOpenStruc.pszComment = (PSZ)jobName.GetBuffer(); + + // Kopien + if ( nCopies > 1 ) + { + // OS2 kann maximal 999 Kopien + if ( nCopies > 999 ) + nCopies = 999; + sprintf( maCopyBuf, "COP=%d", nCopies); + aDevOpenStruc.pszQueueProcParams = (PSZ)maCopyBuf; + } + + // open device context + SalData* pSalData = GetSalData(); + HAB hAB = pSalData->mhAB; + aDevOpenStruc.pdriv = (PDRIVDATA)pSetupData->mpDriverData; + mhDC = DevOpenDC( hAB, + lType, + "*", + 7, + (PDEVOPENDATA)&aDevOpenStruc, + 0 ); + if ( mhDC == 0 ) + { + ERRORID nLastError = WinGetLastError( hAB ); + if ( (nLastError & 0xFFFF) == PMERR_SPL_PRINT_ABORT ) + mnError = SAL_PRINTER_ERROR_ABORT; + else + mnError = SAL_PRINTER_ERROR_GENERALERROR; + return FALSE; + } + + // open presentation space + SIZEL sizel; + sizel.cx = 0; + sizel.cy = 0; + mhPS = Ft2CreatePS( hAB, mhDC, &sizel, GPIA_ASSOC | GPIT_MICRO | PU_PELS ); + if ( !mhPS ) + { + DevCloseDC( mhDC ); + mnError = SAL_PRINTER_ERROR_GENERALERROR; + return NULL; + } + + // Can we print with DJP + mbPrintDJPSupported = ImplIsDriverPrintDJPEnabled( mhDC ); + + // JobName ermitteln und Job starten + PSZ pszJobName = NULL; + int nJobNameLen = 0; + if ( jobName.Len() > 0 ) + { + pszJobName = (PSZ)jobName.GetBuffer(); + nJobNameLen = jobName.Len(); + } + rc = DevEscape( mhDC, + DEVESC_STARTDOC, + nJobNameLen, (PBYTE)pszJobName, + 0, (PBYTE)NULL ); + + if ( rc != DEV_OK ) + { + ERRORID nLastError = WinGetLastError( hAB ); + if ( (nLastError & 0xFFFF) == PMERR_SPL_PRINT_ABORT ) + mnError = SAL_PRINTER_ERROR_ABORT; + else + mnError = SAL_PRINTER_ERROR_GENERALERROR; + Ft2Associate( mhPS, NULL ); + Ft2DestroyPS( mhPS ); + DevCloseDC( mhDC ); + return FALSE; + } + + // init for first page + mbFirstPage = TRUE; + mnError = 0; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalPrinter::EndJob() +{ + APIRET rc; + rc = DevEscape( mhDC, + DEVESC_ENDDOC, + 0, NULL, + 0, NULL); + + // destroy presentation space and device context + Ft2Associate( mhPS, NULL ); + Ft2DestroyPS( mhPS ); + DevCloseDC( mhDC ); + return TRUE; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalPrinter::AbortJob() +{ + APIRET rc; + + rc = DevEscape( mhDC, + DEVESC_ABORTDOC, + 0, NULL, + 0, NULL ); + + // destroy SalGraphics + if ( mpGraphics ) + { + ImplSalDeInitGraphics( mpGraphics ); + delete mpGraphics; + mpGraphics = NULL; + } + + // destroy presentation space and device context + Ft2Associate( mhPS, NULL ); + Ft2DestroyPS( mhPS ); + DevCloseDC( mhDC ); + return TRUE; +} + +// ----------------------------------------------------------------------- + +SalGraphics* Os2SalPrinter::StartPage( ImplJobSetup* pSetupData, BOOL bNewJobSetup ) +{ + APIRET rc; + + if ( mbFirstPage ) + mbFirstPage = FALSE; + else + { + PBYTE pJobData; + LONG nJobDataSize; + LONG nEscape; + if ( mbPrintDJPSupported && bNewJobSetup ) + { + nEscape = DEVESC_NEWFRAME_WPROP; + nJobDataSize = ((PDRIVDATA)(pSetupData->mpDriverData))->cb; + pJobData = (PBYTE)(pSetupData->mpDriverData); + } + else + { + nEscape = DEVESC_NEWFRAME; + nJobDataSize = 0; + pJobData = NULL; + } + rc = DevEscape( mhDC, + nEscape, + 0, NULL, + &nJobDataSize, pJobData ); + + if ( rc != DEV_OK ) + { + DevEscape( mhDC, DEVESC_ENDDOC, 0, NULL, 0, NULL); + Ft2Associate( mhPS, NULL ); + Ft2DestroyPS( mhPS ); + DevCloseDC( mhDC ); + mnError = SAL_PRINTER_ERROR_GENERALERROR; + return NULL; + } + } + + // create SalGraphics with copy of hPS + Os2SalGraphics* pGraphics = new Os2SalGraphics; + pGraphics->mhDC = mhDC; + pGraphics->mhPS = mhPS; + pGraphics->mhWnd = 0; + pGraphics->mbPrinter = TRUE; + pGraphics->mbVirDev = FALSE; + pGraphics->mbWindow = FALSE; + pGraphics->mbScreen = FALSE; + pGraphics->mnHeight = 0; + // search current form for actual page height + HCINFO aInfo; + int nForms = DevQueryHardcopyCaps( mhDC, 0, 0, &aInfo ); + for( int i = 0; i < nForms; i++ ) + { + if ( DevQueryHardcopyCaps( mhDC, i, 1, &aInfo ) >= 0 ) + { + if ( aInfo.flAttributes & HCAPS_CURRENT ) + pGraphics->mnHeight = aInfo.yPels; + } + } + // use device caps if no form selected/found + if ( !pGraphics->mnHeight ) + DevQueryCaps( mhDC, CAPS_HEIGHT, 1L, &pGraphics->mnHeight ); + + ImplSalInitGraphics( pGraphics ); + mpGraphics = pGraphics; + + return pGraphics; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalPrinter::EndPage() +{ + if ( mpGraphics ) + { + // destroy SalGraphics + ImplSalDeInitGraphics( mpGraphics ); + delete mpGraphics; + mpGraphics = NULL; + } + + return TRUE; +} + +// ----------------------------------------------------------------------- + +ULONG Os2SalPrinter::GetErrorCode() +{ + return mnError; +} + +void Os2SalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData ) +{ + printf("Os2SalInfoPrinter::InitPaperFormats\n"); +} +int Os2SalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData ) +{ + printf("Os2SalInfoPrinter::GetLandscapeAngle\n"); + return 0; +} + diff --git a/vcl/os2/source/gdi/salvd.cxx b/vcl/os2/source/gdi/salvd.cxx new file mode 100644 index 000000000000..d497128a8069 --- /dev/null +++ b/vcl/os2/source/gdi/salvd.cxx @@ -0,0 +1,203 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salvd.cxx,v $ + * $Revision: 1.5 $ + * + * 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> + +#include <svpm.h> + +#define _SV_SALVD_CXX +#include <saldata.hxx> +#include <salinst.h> +#include <salgdi.h> +#include <salvd.h> + +#ifndef __H_FT2LIB +#include <wingdi.h> +#include <ft2lib.h> +#endif + +// ======================================================================= + +HBITMAP ImplCreateVirDevBitmap( HDC hDC, HPS hPS, long nDX, long nDY, + USHORT nBitCount ) +{ + if( !nBitCount ) + { + LONG nDevBitCount; + DevQueryCaps( hDC, CAPS_COLOR_BITCOUNT, 1, &nDevBitCount ); + nBitCount = nDevBitCount; + } + + LONG nPlanes; + DevQueryCaps( hDC, CAPS_COLOR_PLANES, 1, &nPlanes ); + + // entsprechende Bitmap zum OutputDevice erzeugen + HBITMAP hBitmap; + BITMAPINFOHEADER2 aBitmapInfo; + memset( &aBitmapInfo, 0, sizeof( BITMAPINFOHEADER2 ) ); + aBitmapInfo.cbFix = sizeof( BITMAPINFOHEADER2 ); + aBitmapInfo.cx = nDX; + aBitmapInfo.cy = nDY; + aBitmapInfo.cPlanes = nPlanes; + aBitmapInfo.cBitCount = (nBitCount < 4) ? 4 : nBitCount; + hBitmap = GpiCreateBitmap( hPS, &aBitmapInfo, 0, NULL, NULL ); + return hBitmap; +} + +// ----------------------------------------------------------------------- + +SalVirtualDevice* Os2SalInstance::CreateVirtualDevice( SalGraphics* pSGraphics, + long nDX, long nDY, + USHORT nBitCount, + const SystemGraphicsData* pData ) +{ + Os2SalGraphics* pGraphics = static_cast<Os2SalGraphics*>(pSGraphics); + HAB hAB = GetSalData()->mhAB; + SIZEL size; + + // create device context (at this time allways display compatible) + DEVOPENSTRUC aDevOpenStruc = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + HDC hDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5, (PDEVOPENDATA)&aDevOpenStruc, 0 ); + if ( !hDC ) + return NULL; + + // create presentation space + size.cx = nDX; + size.cy = nDY; + HPS hPS = Ft2CreatePS( hAB, hDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS ); + if ( !hPS ) + { + DevCloseDC( hDC ); + return NULL; + } + + // create bitmap for the virtual device + HBITMAP hBmp = ImplCreateVirDevBitmap( hDC, hPS, nDX, nDY, nBitCount ); + if ( !hBmp ) + { + Ft2DestroyPS( hPS ); + DevCloseDC( hDC ); + return NULL; + } + + // init data + Os2SalVirtualDevice* pVDev = new Os2SalVirtualDevice; + Os2SalGraphics* pVirGraphics = new Os2SalGraphics; + + pVirGraphics->mhDC = hDC; + pVirGraphics->mhPS = hPS; + pVirGraphics->mhWnd = 0; + pVirGraphics->mnHeight = nDY; + pVirGraphics->mbPrinter = FALSE; + pVirGraphics->mbVirDev = TRUE; + pVirGraphics->mbWindow = FALSE; + pVirGraphics->mbScreen = pGraphics->mbScreen; + ImplSalInitGraphics( pVirGraphics ); + + pVDev->mhDC = hDC; + pVDev->mhPS = hPS; + pVDev->mhBmp = hBmp; + pVDev->mhDefBmp = Ft2SetBitmap( hPS, hBmp ); + pVDev->mpGraphics = pVirGraphics; + pVDev->mnBitCount = nBitCount; + pVDev->mbGraphics = FALSE; + return pVDev; +} + +// ----------------------------------------------------------------------- + +void Os2SalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice ) +{ + delete pDevice; +} + +// ======================================================================= + +Os2SalVirtualDevice::Os2SalVirtualDevice() +{ +} + +// ----------------------------------------------------------------------- + +Os2SalVirtualDevice::~Os2SalVirtualDevice() +{ + ImplSalDeInitGraphics( mpGraphics ); + + Ft2SetBitmap( mpGraphics->mhPS, mhDefBmp ); + GpiDeleteBitmap( mhBmp ); + Ft2DestroyPS( mpGraphics->mhPS ); + DevCloseDC( mpGraphics->mhDC ); + delete mpGraphics; +} + +// ----------------------------------------------------------------------- + +SalGraphics* Os2SalVirtualDevice::GetGraphics() +{ + if ( mbGraphics ) + return NULL; + + if ( mpGraphics ) + mbGraphics = TRUE; + + return mpGraphics; +} + +// ----------------------------------------------------------------------- + +void Os2SalVirtualDevice::ReleaseGraphics( SalGraphics* ) +{ + mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL Os2SalVirtualDevice::SetSize( long nDX, long nDY ) +{ + HBITMAP hNewBmp = ImplCreateVirDevBitmap( mhDC, + mhPS, nDX, nDY, + mnBitCount ); + if ( hNewBmp ) + { + Ft2SetBitmap( mhPS, hNewBmp ); + GpiDeleteBitmap( mhBmp ); + mhBmp = hNewBmp; + mpGraphics->mnHeight = nDY; + return TRUE; + } + else + return FALSE; +} + +void Os2SalVirtualDevice::GetSize( long& rWidth, long& rHeight ) +{ + DevQueryCaps( mpGraphics->mhDC, CAPS_WIDTH, CAPS_WIDTH, (LONG*)rWidth ); + DevQueryCaps( mpGraphics->mhDC, CAPS_HEIGHT, CAPS_HEIGHT, (LONG*)rHeight ); +} diff --git a/vcl/os2/source/src/airbrush.ptr b/vcl/os2/source/src/airbrush.ptr Binary files differnew file mode 100644 index 000000000000..89a99d763d94 --- /dev/null +++ b/vcl/os2/source/src/airbrush.ptr diff --git a/vcl/os2/source/src/ase.ptr b/vcl/os2/source/src/ase.ptr Binary files differnew file mode 100755 index 000000000000..1f6c4e764901 --- /dev/null +++ b/vcl/os2/source/src/ase.ptr diff --git a/vcl/os2/source/src/asn.ptr b/vcl/os2/source/src/asn.ptr Binary files differnew file mode 100755 index 000000000000..b526c17a83e0 --- /dev/null +++ b/vcl/os2/source/src/asn.ptr diff --git a/vcl/os2/source/src/asne.ptr b/vcl/os2/source/src/asne.ptr Binary files differnew file mode 100755 index 000000000000..4ed44679918f --- /dev/null +++ b/vcl/os2/source/src/asne.ptr diff --git a/vcl/os2/source/src/asns.ptr b/vcl/os2/source/src/asns.ptr Binary files differnew file mode 100755 index 000000000000..12395e641b4f --- /dev/null +++ b/vcl/os2/source/src/asns.ptr diff --git a/vcl/os2/source/src/asnswe.ptr b/vcl/os2/source/src/asnswe.ptr Binary files differnew file mode 100755 index 000000000000..46f1f790b474 --- /dev/null +++ b/vcl/os2/source/src/asnswe.ptr diff --git a/vcl/os2/source/src/asnw.ptr b/vcl/os2/source/src/asnw.ptr Binary files differnew file mode 100755 index 000000000000..d934c3b69a79 --- /dev/null +++ b/vcl/os2/source/src/asnw.ptr diff --git a/vcl/os2/source/src/ass.ptr b/vcl/os2/source/src/ass.ptr Binary files differnew file mode 100755 index 000000000000..059ce40126cd --- /dev/null +++ b/vcl/os2/source/src/ass.ptr diff --git a/vcl/os2/source/src/asse.ptr b/vcl/os2/source/src/asse.ptr Binary files differnew file mode 100755 index 000000000000..78a1f7ff5c64 --- /dev/null +++ b/vcl/os2/source/src/asse.ptr diff --git a/vcl/os2/source/src/assw.ptr b/vcl/os2/source/src/assw.ptr Binary files differnew file mode 100755 index 000000000000..5adf85360e30 --- /dev/null +++ b/vcl/os2/source/src/assw.ptr diff --git a/vcl/os2/source/src/asw.ptr b/vcl/os2/source/src/asw.ptr Binary files differnew file mode 100755 index 000000000000..160a775abe22 --- /dev/null +++ b/vcl/os2/source/src/asw.ptr diff --git a/vcl/os2/source/src/aswe.ptr b/vcl/os2/source/src/aswe.ptr Binary files differnew file mode 100755 index 000000000000..b4e6580c560d --- /dev/null +++ b/vcl/os2/source/src/aswe.ptr diff --git a/vcl/os2/source/src/chain.ptr b/vcl/os2/source/src/chain.ptr Binary files differnew file mode 100644 index 000000000000..0e248b324daa --- /dev/null +++ b/vcl/os2/source/src/chain.ptr diff --git a/vcl/os2/source/src/chainnot.ptr b/vcl/os2/source/src/chainnot.ptr Binary files differnew file mode 100644 index 000000000000..0e248b324daa --- /dev/null +++ b/vcl/os2/source/src/chainnot.ptr diff --git a/vcl/os2/source/src/chart.ptr b/vcl/os2/source/src/chart.ptr Binary files differnew file mode 100644 index 000000000000..66c685d111c7 --- /dev/null +++ b/vcl/os2/source/src/chart.ptr diff --git a/vcl/os2/source/src/copydata.ptr b/vcl/os2/source/src/copydata.ptr Binary files differnew file mode 100644 index 000000000000..e7e7ccd17e41 --- /dev/null +++ b/vcl/os2/source/src/copydata.ptr diff --git a/vcl/os2/source/src/copydlnk.ptr b/vcl/os2/source/src/copydlnk.ptr Binary files differnew file mode 100644 index 000000000000..acbf27b3462e --- /dev/null +++ b/vcl/os2/source/src/copydlnk.ptr diff --git a/vcl/os2/source/src/copyf.ptr b/vcl/os2/source/src/copyf.ptr Binary files differnew file mode 100644 index 000000000000..8ebcbded233b --- /dev/null +++ b/vcl/os2/source/src/copyf.ptr diff --git a/vcl/os2/source/src/copyf2.ptr b/vcl/os2/source/src/copyf2.ptr Binary files differnew file mode 100644 index 000000000000..dcfa6c089c10 --- /dev/null +++ b/vcl/os2/source/src/copyf2.ptr diff --git a/vcl/os2/source/src/copyflnk.ptr b/vcl/os2/source/src/copyflnk.ptr Binary files differnew file mode 100644 index 000000000000..3bd6e9d4706e --- /dev/null +++ b/vcl/os2/source/src/copyflnk.ptr diff --git a/vcl/os2/source/src/crook.ptr b/vcl/os2/source/src/crook.ptr Binary files differnew file mode 100644 index 000000000000..0b639614ddb3 --- /dev/null +++ b/vcl/os2/source/src/crook.ptr diff --git a/vcl/os2/source/src/crop.ptr b/vcl/os2/source/src/crop.ptr Binary files differnew file mode 100644 index 000000000000..076e522e1b7f --- /dev/null +++ b/vcl/os2/source/src/crop.ptr diff --git a/vcl/os2/source/src/cross.ptr b/vcl/os2/source/src/cross.ptr Binary files differnew file mode 100644 index 000000000000..1a2cd8dae5f6 --- /dev/null +++ b/vcl/os2/source/src/cross.ptr diff --git a/vcl/os2/source/src/darc.ptr b/vcl/os2/source/src/darc.ptr Binary files differnew file mode 100644 index 000000000000..eba024e6a09a --- /dev/null +++ b/vcl/os2/source/src/darc.ptr diff --git a/vcl/os2/source/src/data.ptr b/vcl/os2/source/src/data.ptr Binary files differnew file mode 100644 index 000000000000..4c3c9eeb5e7a --- /dev/null +++ b/vcl/os2/source/src/data.ptr diff --git a/vcl/os2/source/src/dbezier.ptr b/vcl/os2/source/src/dbezier.ptr Binary files differnew file mode 100644 index 000000000000..8972b0007c13 --- /dev/null +++ b/vcl/os2/source/src/dbezier.ptr diff --git a/vcl/os2/source/src/dcapt.ptr b/vcl/os2/source/src/dcapt.ptr Binary files differnew file mode 100644 index 000000000000..b04b21bad1a7 --- /dev/null +++ b/vcl/os2/source/src/dcapt.ptr diff --git a/vcl/os2/source/src/dcirccut.ptr b/vcl/os2/source/src/dcirccut.ptr Binary files differnew file mode 100644 index 000000000000..936b337ebcc7 --- /dev/null +++ b/vcl/os2/source/src/dcirccut.ptr diff --git a/vcl/os2/source/src/dconnect.ptr b/vcl/os2/source/src/dconnect.ptr Binary files differnew file mode 100644 index 000000000000..f8bc2cf454aa --- /dev/null +++ b/vcl/os2/source/src/dconnect.ptr diff --git a/vcl/os2/source/src/dellipse.ptr b/vcl/os2/source/src/dellipse.ptr Binary files differnew file mode 100644 index 000000000000..388bc2f2b00c --- /dev/null +++ b/vcl/os2/source/src/dellipse.ptr diff --git a/vcl/os2/source/src/detectiv.ptr b/vcl/os2/source/src/detectiv.ptr Binary files differnew file mode 100644 index 000000000000..44ca1546a93b --- /dev/null +++ b/vcl/os2/source/src/detectiv.ptr diff --git a/vcl/os2/source/src/dfree.ptr b/vcl/os2/source/src/dfree.ptr Binary files differnew file mode 100644 index 000000000000..52d95d814d98 --- /dev/null +++ b/vcl/os2/source/src/dfree.ptr diff --git a/vcl/os2/source/src/dline.ptr b/vcl/os2/source/src/dline.ptr Binary files differnew file mode 100644 index 000000000000..e7b80ae56735 --- /dev/null +++ b/vcl/os2/source/src/dline.ptr diff --git a/vcl/os2/source/src/dpie.ptr b/vcl/os2/source/src/dpie.ptr Binary files differnew file mode 100644 index 000000000000..abd68b899f3a --- /dev/null +++ b/vcl/os2/source/src/dpie.ptr diff --git a/vcl/os2/source/src/dpolygon.ptr b/vcl/os2/source/src/dpolygon.ptr Binary files differnew file mode 100644 index 000000000000..94fa158b4186 --- /dev/null +++ b/vcl/os2/source/src/dpolygon.ptr diff --git a/vcl/os2/source/src/drect.ptr b/vcl/os2/source/src/drect.ptr Binary files differnew file mode 100644 index 000000000000..3ec044f267d6 --- /dev/null +++ b/vcl/os2/source/src/drect.ptr diff --git a/vcl/os2/source/src/dtext.ptr b/vcl/os2/source/src/dtext.ptr Binary files differnew file mode 100644 index 000000000000..8c221303b0b6 --- /dev/null +++ b/vcl/os2/source/src/dtext.ptr diff --git a/vcl/os2/source/src/fill.ptr b/vcl/os2/source/src/fill.ptr Binary files differnew file mode 100644 index 000000000000..e7247a6d107b --- /dev/null +++ b/vcl/os2/source/src/fill.ptr diff --git a/vcl/os2/source/src/hand.ptr b/vcl/os2/source/src/hand.ptr Binary files differnew file mode 100644 index 000000000000..b1d65c7f19d0 --- /dev/null +++ b/vcl/os2/source/src/hand.ptr diff --git a/vcl/os2/source/src/help.ptr b/vcl/os2/source/src/help.ptr Binary files differnew file mode 100644 index 000000000000..3df4d88bddc4 --- /dev/null +++ b/vcl/os2/source/src/help.ptr diff --git a/vcl/os2/source/src/hshear.ptr b/vcl/os2/source/src/hshear.ptr Binary files differnew file mode 100644 index 000000000000..76bbebba5865 --- /dev/null +++ b/vcl/os2/source/src/hshear.ptr diff --git a/vcl/os2/source/src/hsizebar.ptr b/vcl/os2/source/src/hsizebar.ptr Binary files differnew file mode 100644 index 000000000000..9b78ff9ee9a9 --- /dev/null +++ b/vcl/os2/source/src/hsizebar.ptr diff --git a/vcl/os2/source/src/hsplit.ptr b/vcl/os2/source/src/hsplit.ptr Binary files differnew file mode 100644 index 000000000000..62f3b590a414 --- /dev/null +++ b/vcl/os2/source/src/hsplit.ptr diff --git a/vcl/os2/source/src/linkdata.ptr b/vcl/os2/source/src/linkdata.ptr Binary files differnew file mode 100644 index 000000000000..e5e6ace59be3 --- /dev/null +++ b/vcl/os2/source/src/linkdata.ptr diff --git a/vcl/os2/source/src/linkf.ptr b/vcl/os2/source/src/linkf.ptr Binary files differnew file mode 100644 index 000000000000..62bf7e739e32 --- /dev/null +++ b/vcl/os2/source/src/linkf.ptr diff --git a/vcl/os2/source/src/magnify.ptr b/vcl/os2/source/src/magnify.ptr Binary files differnew file mode 100644 index 000000000000..1d9a0c149ebd --- /dev/null +++ b/vcl/os2/source/src/magnify.ptr diff --git a/vcl/os2/source/src/makefile.mk b/vcl/os2/source/src/makefile.mk new file mode 100644 index 000000000000..60aa376a19fe --- /dev/null +++ b/vcl/os2/source/src/makefile.mk @@ -0,0 +1,115 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=salsrc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile2.pmk + +# --- Files -------------------------------------------------------- + +RCDEPN= nullptr.ptr \ + help.ptr \ + cross.ptr \ + move.ptr \ + hsplit.ptr \ + vsplit.ptr \ + hsizebar.ptr \ + vsizebar.ptr \ + hand.ptr \ + refhand.ptr \ + pen.ptr \ + magnify.ptr \ + fill.ptr \ + rotate.ptr \ + hshear.ptr \ + vshear.ptr \ + mirror.ptr \ + crook.ptr \ + crop.ptr \ + movept.ptr \ + movebw.ptr \ + movedata.ptr \ + copydata.ptr \ + linkdata.ptr \ + movedlnk.ptr \ + copydlnk.ptr \ + movef.ptr \ + copyf.ptr \ + linkf.ptr \ + moveflnk.ptr \ + copyflnk.ptr \ + movef2.ptr \ + copyf2.ptr \ + dline.ptr \ + drect.ptr \ + dpolygon.ptr \ + dbezier.ptr \ + darc.ptr \ + dpie.ptr \ + dcirccut.ptr \ + dellipse.ptr \ + dfree.ptr \ + dconnect.ptr \ + dtext.ptr \ + dcapt.ptr \ + chart.ptr \ + detectiv.ptr \ + pivotcol.ptr \ + pivotrow.ptr \ + pivotfld.ptr \ + chain.ptr \ + chainnot.ptr \ + timemove.ptr \ + timesize.ptr \ + asn.ptr \ + ass.ptr \ + asw.ptr \ + ase.ptr \ + asnw.ptr \ + asne.ptr \ + assw.ptr \ + asse.ptr \ + asns.ptr \ + aswe.ptr \ + asnswe.ptr \ + sd.ico + +RCFILES= salsrc.rc + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/os2/source/src/mirror.ptr b/vcl/os2/source/src/mirror.ptr Binary files differnew file mode 100644 index 000000000000..9135331048c9 --- /dev/null +++ b/vcl/os2/source/src/mirror.ptr diff --git a/vcl/os2/source/src/move.ptr b/vcl/os2/source/src/move.ptr Binary files differnew file mode 100644 index 000000000000..6b5a11d31219 --- /dev/null +++ b/vcl/os2/source/src/move.ptr diff --git a/vcl/os2/source/src/movebw.ptr b/vcl/os2/source/src/movebw.ptr Binary files differnew file mode 100644 index 000000000000..e766b885db0a --- /dev/null +++ b/vcl/os2/source/src/movebw.ptr diff --git a/vcl/os2/source/src/movedata.ptr b/vcl/os2/source/src/movedata.ptr Binary files differnew file mode 100644 index 000000000000..689f38da772f --- /dev/null +++ b/vcl/os2/source/src/movedata.ptr diff --git a/vcl/os2/source/src/movedlnk.ptr b/vcl/os2/source/src/movedlnk.ptr Binary files differnew file mode 100644 index 000000000000..d533e7135ad0 --- /dev/null +++ b/vcl/os2/source/src/movedlnk.ptr diff --git a/vcl/os2/source/src/movef.ptr b/vcl/os2/source/src/movef.ptr Binary files differnew file mode 100644 index 000000000000..e9fabda359c8 --- /dev/null +++ b/vcl/os2/source/src/movef.ptr diff --git a/vcl/os2/source/src/movef2.ptr b/vcl/os2/source/src/movef2.ptr Binary files differnew file mode 100644 index 000000000000..9940890840cb --- /dev/null +++ b/vcl/os2/source/src/movef2.ptr diff --git a/vcl/os2/source/src/moveflnk.ptr b/vcl/os2/source/src/moveflnk.ptr Binary files differnew file mode 100644 index 000000000000..d651491ad001 --- /dev/null +++ b/vcl/os2/source/src/moveflnk.ptr diff --git a/vcl/os2/source/src/movept.ptr b/vcl/os2/source/src/movept.ptr Binary files differnew file mode 100644 index 000000000000..d34332dd89e5 --- /dev/null +++ b/vcl/os2/source/src/movept.ptr diff --git a/vcl/os2/source/src/nullptr.ptr b/vcl/os2/source/src/nullptr.ptr Binary files differnew file mode 100644 index 000000000000..f8b0f784ba7a --- /dev/null +++ b/vcl/os2/source/src/nullptr.ptr diff --git a/vcl/os2/source/src/pen.ptr b/vcl/os2/source/src/pen.ptr Binary files differnew file mode 100644 index 000000000000..3b4495697597 --- /dev/null +++ b/vcl/os2/source/src/pen.ptr diff --git a/vcl/os2/source/src/pivotcol.ptr b/vcl/os2/source/src/pivotcol.ptr Binary files differnew file mode 100644 index 000000000000..369fdeebf2d0 --- /dev/null +++ b/vcl/os2/source/src/pivotcol.ptr diff --git a/vcl/os2/source/src/pivotfld.ptr b/vcl/os2/source/src/pivotfld.ptr Binary files differnew file mode 100644 index 000000000000..047c45a711df --- /dev/null +++ b/vcl/os2/source/src/pivotfld.ptr diff --git a/vcl/os2/source/src/pivotrow.ptr b/vcl/os2/source/src/pivotrow.ptr Binary files differnew file mode 100644 index 000000000000..e66e752e51d0 --- /dev/null +++ b/vcl/os2/source/src/pivotrow.ptr diff --git a/vcl/os2/source/src/pntbrsh.ptr b/vcl/os2/source/src/pntbrsh.ptr Binary files differnew file mode 100644 index 000000000000..506965e6b52d --- /dev/null +++ b/vcl/os2/source/src/pntbrsh.ptr diff --git a/vcl/os2/source/src/refhand.ptr b/vcl/os2/source/src/refhand.ptr Binary files differnew file mode 100644 index 000000000000..33d613134cb5 --- /dev/null +++ b/vcl/os2/source/src/refhand.ptr diff --git a/vcl/os2/source/src/rotate.ptr b/vcl/os2/source/src/rotate.ptr Binary files differnew file mode 100644 index 000000000000..622b05346cfc --- /dev/null +++ b/vcl/os2/source/src/rotate.ptr diff --git a/vcl/os2/source/src/salsrc.rc b/vcl/os2/source/src/salsrc.rc new file mode 100644 index 000000000000..2654dcc7f2f9 --- /dev/null +++ b/vcl/os2/source/src/salsrc.rc @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salsrc.rc,v $ + * $Revision: 1.5 $ + * + * 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. + * + ************************************************************************/ + +#ifndef _SV_SALIDS_HRC +#include <salids.hrc> +#endif + +POINTER SAL_RESID_POINTER_NULL NULLPTR.PTR +POINTER SAL_RESID_POINTER_HELP HELP.PTR +POINTER SAL_RESID_POINTER_CROSS CROSS.PTR +POINTER SAL_RESID_POINTER_MOVE MOVE.PTR +POINTER SAL_RESID_POINTER_HSPLIT HSPLIT.PTR +POINTER SAL_RESID_POINTER_VSPLIT VSPLIT.PTR +POINTER SAL_RESID_POINTER_HSIZEBAR HSIZEBAR.PTR +POINTER SAL_RESID_POINTER_VSIZEBAR VSIZEBAR.PTR +POINTER SAL_RESID_POINTER_HAND HAND.PTR +POINTER SAL_RESID_POINTER_REFHAND REFHAND.PTR +POINTER SAL_RESID_POINTER_PEN PEN.PTR +POINTER SAL_RESID_POINTER_MAGNIFY MAGNIFY.PTR +POINTER SAL_RESID_POINTER_FILL FILL.PTR +POINTER SAL_RESID_POINTER_ROTATE ROTATE.PTR +POINTER SAL_RESID_POINTER_HSHEAR HSHEAR.PTR +POINTER SAL_RESID_POINTER_VSHEAR VSHEAR.PTR +POINTER SAL_RESID_POINTER_MIRROR MIRROR.PTR +POINTER SAL_RESID_POINTER_CROOK CROOK.PTR +POINTER SAL_RESID_POINTER_CROP CROP.PTR +POINTER SAL_RESID_POINTER_MOVEPOINT MOVEPT.PTR +POINTER SAL_RESID_POINTER_MOVEBEZIERWEIGHT MOVEBW.PTR +POINTER SAL_RESID_POINTER_MOVEDATA MOVEDATA.PTR +POINTER SAL_RESID_POINTER_COPYDATA COPYDATA.PTR +POINTER SAL_RESID_POINTER_LINKDATA LINKDATA.PTR +POINTER SAL_RESID_POINTER_MOVEDATALINK MOVEDLNK.PTR +POINTER SAL_RESID_POINTER_COPYDATALINK COPYDLNK.PTR +POINTER SAL_RESID_POINTER_MOVEFILE MOVEF.PTR +POINTER SAL_RESID_POINTER_COPYFILE COPYF.PTR +POINTER SAL_RESID_POINTER_LINKFILE LINKF.PTR +POINTER SAL_RESID_POINTER_MOVEFILELINK MOVEFLNK.PTR +POINTER SAL_RESID_POINTER_COPYFILELINK COPYFLNK.PTR +POINTER SAL_RESID_POINTER_MOVEFILES MOVEF2.PTR +POINTER SAL_RESID_POINTER_COPYFILES COPYF2.PTR +POINTER SAL_RESID_POINTER_DRAW_LINE DLINE.PTR +POINTER SAL_RESID_POINTER_DRAW_RECT DRECT.PTR +POINTER SAL_RESID_POINTER_DRAW_POLYGON DPOLYGON.PTR +POINTER SAL_RESID_POINTER_DRAW_BEZIER DBEZIER.PTR +POINTER SAL_RESID_POINTER_DRAW_ARC DARC.PTR +POINTER SAL_RESID_POINTER_DRAW_PIE DPIE.PTR +POINTER SAL_RESID_POINTER_DRAW_CIRCLECUT DCIRCCUT.PTR +POINTER SAL_RESID_POINTER_DRAW_ELLIPSE DELLIPSE.PTR +POINTER SAL_RESID_POINTER_DRAW_FREEHAND DFREE.PTR +POINTER SAL_RESID_POINTER_DRAW_CONNECT DCONNECT.PTR +POINTER SAL_RESID_POINTER_DRAW_TEXT DTEXT.PTR +POINTER SAL_RESID_POINTER_DRAW_CAPTION DCAPT.PTR +POINTER SAL_RESID_POINTER_CHART CHART.PTR +POINTER SAL_RESID_POINTER_DETECTIVE DETECTIV.PTR +POINTER SAL_RESID_POINTER_PIVOT_COL PIVOTCOL.PTR +POINTER SAL_RESID_POINTER_PIVOT_ROW PIVOTROW.PTR +POINTER SAL_RESID_POINTER_PIVOT_FIELD PIVOTFLD.PTR +POINTER SAL_RESID_POINTER_CHAIN CHAIN.PTR +POINTER SAL_RESID_POINTER_CHAIN_NOTALLOWED CHAINNOT.PTR +POINTER SAL_RESID_POINTER_TIMEEVENT_MOVE TIMEMOVE.PTR +POINTER SAL_RESID_POINTER_TIMEEVENT_SIZE TIMESIZE.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_N ASN.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_S ASS.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_W ASW.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_E ASE.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_NW ASNW.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_NE ASNE.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_SW ASSW.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_SE ASSE.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_NS ASNS.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_WE ASWE.PTR +POINTER SAL_RESID_POINTER_AUTOSCROLL_NSWE ASNSWE.PTR + +POINTER SAL_RESID_POINTER_AIRBRUSH AIRBRUSH.PTR +POINTER SAL_RESID_POINTER_TEXT_VERTICAL VTEXT.PTR +POINTER SAL_RESID_POINTER_TAB_SELECT_S TBLSELS.PTR +POINTER SAL_RESID_POINTER_TAB_SELECT_E TBLSELE.PTR +POINTER SAL_RESID_POINTER_TAB_SELECT_SE TBLSELSE.PTR +POINTER SAL_RESID_POINTER_TAB_SELECT_W TBLSELW.PTR +POINTER SAL_RESID_POINTER_TAB_SELECT_SW TBLSELSW.PTR +POINTER SAL_RESID_POINTER_PAINTBRUSH PNTBRSH.PTR + +ICON SAL_RESID_ICON_DEFAULT SD2.ICO + diff --git a/vcl/os2/source/src/sd.ico b/vcl/os2/source/src/sd.ico Binary files differnew file mode 100644 index 000000000000..22cb33630b85 --- /dev/null +++ b/vcl/os2/source/src/sd.ico diff --git a/vcl/os2/source/src/sd2.ico b/vcl/os2/source/src/sd2.ico Binary files differnew file mode 100644 index 000000000000..f7edd4524bc1 --- /dev/null +++ b/vcl/os2/source/src/sd2.ico diff --git a/vcl/os2/source/src/tblsele.ptr b/vcl/os2/source/src/tblsele.ptr Binary files differnew file mode 100644 index 000000000000..627c2f61662b --- /dev/null +++ b/vcl/os2/source/src/tblsele.ptr diff --git a/vcl/os2/source/src/tblsels.ptr b/vcl/os2/source/src/tblsels.ptr Binary files differnew file mode 100644 index 000000000000..3553c0d1f5ae --- /dev/null +++ b/vcl/os2/source/src/tblsels.ptr diff --git a/vcl/os2/source/src/tblselse.ptr b/vcl/os2/source/src/tblselse.ptr Binary files differnew file mode 100644 index 000000000000..355e5105f58f --- /dev/null +++ b/vcl/os2/source/src/tblselse.ptr diff --git a/vcl/os2/source/src/tblselsw.ptr b/vcl/os2/source/src/tblselsw.ptr Binary files differnew file mode 100644 index 000000000000..435dec00c3e1 --- /dev/null +++ b/vcl/os2/source/src/tblselsw.ptr diff --git a/vcl/os2/source/src/tblselw.ptr b/vcl/os2/source/src/tblselw.ptr Binary files differnew file mode 100644 index 000000000000..de64ad06d6a2 --- /dev/null +++ b/vcl/os2/source/src/tblselw.ptr diff --git a/vcl/os2/source/src/timemove.ptr b/vcl/os2/source/src/timemove.ptr Binary files differnew file mode 100755 index 000000000000..a9298cee867b --- /dev/null +++ b/vcl/os2/source/src/timemove.ptr diff --git a/vcl/os2/source/src/timesize.ptr b/vcl/os2/source/src/timesize.ptr Binary files differnew file mode 100755 index 000000000000..e543c1ff790c --- /dev/null +++ b/vcl/os2/source/src/timesize.ptr diff --git a/vcl/os2/source/src/vshear.ptr b/vcl/os2/source/src/vshear.ptr Binary files differnew file mode 100644 index 000000000000..f335d5ea949b --- /dev/null +++ b/vcl/os2/source/src/vshear.ptr diff --git a/vcl/os2/source/src/vsizebar.ptr b/vcl/os2/source/src/vsizebar.ptr Binary files differnew file mode 100644 index 000000000000..b238889c594c --- /dev/null +++ b/vcl/os2/source/src/vsizebar.ptr diff --git a/vcl/os2/source/src/vsplit.ptr b/vcl/os2/source/src/vsplit.ptr Binary files differnew file mode 100644 index 000000000000..662d760b0b2f --- /dev/null +++ b/vcl/os2/source/src/vsplit.ptr diff --git a/vcl/os2/source/src/vtext.ptr b/vcl/os2/source/src/vtext.ptr Binary files differnew file mode 100644 index 000000000000..a7f9901bdf68 --- /dev/null +++ b/vcl/os2/source/src/vtext.ptr diff --git a/vcl/os2/source/window/makefile b/vcl/os2/source/window/makefile new file mode 100644 index 000000000000..8fcf3e11eafb --- /dev/null +++ b/vcl/os2/source/window/makefile @@ -0,0 +1,57 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile,v $ +# +# $Revision: 1.4 $ +# +# 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. +# +#************************************************************************* + +PRJ=..\..\.. + +PRJNAME=SV +TARGET=salwin + +# --- Settings ----------------------------------------------------- + +!INCLUDE <svpre.mak> +!INCLUDE <settings.mak> +!INCLUDE <sv.mak> + +!IF "$(COM)"=="ICC" +ENVCFLAGS=$(ENVCFLAGS) -D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE +!ENDIF + +# --- Files -------------------------------------------------------- + +CXXFILES= salframe.cxx \ + salobj.cxx + +SLOFILES= $(SLO)\salframe.obj \ + $(SLO)\salobj.obj + +# --- Targets ------------------------------------------------------ + +!INCLUDE <target.mak> diff --git a/vcl/os2/source/window/makefile.mk b/vcl/os2/source/window/makefile.mk new file mode 100644 index 000000000000..59d2d8a58916 --- /dev/null +++ b/vcl/os2/source/window/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=SV +TARGET=salwin + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +CXXFILES__YD= salframe.cxx \ + salobj.cxx + +SLOFILES= $(SLO)$/salframe.obj \ + $(SLO)$/salobj.obj $(SLO)$/salmenu.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/os2/source/window/salframe.cxx b/vcl/os2/source/window/salframe.cxx new file mode 100644 index 000000000000..5e4b843c7cff --- /dev/null +++ b/vcl/os2/source/window/salframe.cxx @@ -0,0 +1,3780 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salframe.cxx,v $ + * $Revision: 1.7 $ + * + * 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(); + BOOL bCompBorder = (aStyleSettings.GetOptions() & (STYLE_OPTION_MACSTYLE | STYLE_OPTION_UNIXSTYLE)) == 0; + + // 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 ) ); + if ( bCompBorder ) + { + aStyleSettings.SetTitleHeight( WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) ); + } + + // Color settings + if ( bCompBorder ) + { + 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() ) ) + { + if ( bCompBorder ) + { + 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 long ImplHandleSizeMsg( HWND hWnd, MPARAM nMP2 ) +{ + long nRet; + + 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 ); + nRet = pFrame->CallCallback( SALEVENT_RESIZE, 0 ); + if ( WinIsWindowVisible( pFrame->mhWndFrame ) && !pFrame->mbInShow ) + WinUpdateWindow( pFrame->mhWndClient ); + } + return nRet; +} + +// ----------------------------------------------------------------------- + +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 ); +} + +// ----------------------------------------------------------------------- diff --git a/vcl/os2/source/window/salmenu.cxx b/vcl/os2/source/window/salmenu.cxx new file mode 100644 index 000000000000..2f61cd7cb2b9 --- /dev/null +++ b/vcl/os2/source/window/salmenu.cxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salmenu.cxx,v $ + * $Revision: 1.4 $ + * + * 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. + * + ************************************************************************/ + +#define INCL_DOS +#define INCL_PM +#define INCL_WIN +#include <svpm.h> +#include <saldata.hxx> +#include <salinst.h> +#include <salmenu.h> + + +// ======================================================================= + +// Os2SalInst factory methods + +SalMenu* Os2SalInstance::CreateMenu( BOOL bMenuBar ) +{ + return NULL; // no support for native menues +} + +void Os2SalInstance::DestroyMenu( SalMenu* pSalMenu ) +{ + delete pSalMenu; +} + + +SalMenuItem* Os2SalInstance::CreateMenuItem( const SalItemParams* pItemData ) +{ + return NULL; // no support for native menues +} + +void Os2SalInstance::DestroyMenuItem( SalMenuItem* pSalMenuItem ) +{ + delete pSalMenuItem; +} + + +// ======================================================================= + + +/* + * Os2SalMenu + */ + + +Os2SalMenu::~Os2SalMenu() +{ +} + +BOOL Os2SalMenu::VisibleMenuBar() +{ + return FALSE; +} + +void Os2SalMenu::SetFrame( const SalFrame *pFrame ) +{ +} + +void Os2SalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos ) +{ +} + +void Os2SalMenu::RemoveItem( unsigned nPos ) +{ +} + +void Os2SalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned nPos ) +{ +} + +void Os2SalMenu::CheckItem( unsigned nPos, BOOL bCheck ) +{ +} + +void Os2SalMenu::EnableItem( unsigned nPos, BOOL bEnable ) +{ +} + +void Os2SalMenu::SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage ) +{ +} + +void Os2SalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const XubString& rText ) +{ +} + +void Os2SalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const XubString& rKeyName ) +{ +} + +void Os2SalMenu::GetSystemMenuData( SystemMenuData* pData ) +{ +} + +// ======================================================================= + +/* + * SalMenuItem + */ + + +Os2SalMenuItem::~Os2SalMenuItem() +{ +} + +// ------------------------------------------------------------------- + diff --git a/vcl/os2/source/window/salobj.cxx b/vcl/os2/source/window/salobj.cxx new file mode 100644 index 000000000000..9f665506c5d3 --- /dev/null +++ b/vcl/os2/source/window/salobj.cxx @@ -0,0 +1,571 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: salobj.cxx,v $ + * $Revision: 1.5 $ + * + * 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 <svpm.h> + +#define _SV_SALOBJ_CXX +#include <saldata.hxx> +#include <salinst.h> +#include <salframe.h> +#include <salobj.h> + +// ======================================================================= + +static BOOL ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild ) +{ + if ( hWndParent == hWndChild ) + return TRUE; + + HWND hTempWnd = WinQueryWindow( hWndChild, QW_PARENT ); + while ( hTempWnd ) + { + if ( hTempWnd == hWndParent ) + return TRUE; + hTempWnd = WinQueryWindow( hTempWnd, QW_PARENT ); + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +static Os2SalObject* ImplFindOs2SalObject( HWND hWndChild ) +{ + SalData* pSalData = GetSalData(); + Os2SalObject* pObject = pSalData->mpFirstObject; + while ( pObject ) + { + if ( ImplIsSysWindowOrChild( pObject->mhWndChild, hWndChild ) ) + return pObject; + + pObject = pObject->mpNextObject; + } + + return NULL; +} + +// ======================================================================= + +BOOL EXPENTRY SalSysMsgProc( HAB /* hAB */, QMSG* pMsg, ULONG /* fs */ ) +{ + if ( (pMsg->msg == WM_BUTTON1DOWN) || + (pMsg->msg == WM_BUTTON2DOWN) || + (pMsg->msg == WM_BUTTON3DOWN) ) + { + SalData* pSalData = GetSalData(); + Os2SalObject* pObject = ImplFindOs2SalObject( pMsg->hwnd ); + if ( pObject ) + WinPostMsg( pObject->mhWnd, SALOBJ_MSG_TOTOP, 0, 0 ); + } + + // Focus fangen wir hier nicht ab, da wir erstmal davon ausgehen, + // das unser Os2SalObject-Fenster immer eine WM_FOCUSCHANGE-Message + // bekommt. + + return FALSE; +} + +// ----------------------------------------------------------------------- + +MRESULT EXPENTRY SalSysObjWndProc( HWND hWnd, ULONG nMsg, + MPARAM nMP1, MPARAM nMP2 ) +{ + Os2SalObject* pSysObj; + MRESULT nRet = 0; + int bDef = TRUE; + +#if OSL_DEBUG_LEVEL>0 + debug_printf( "SalSysObjWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); +#endif + + switch( nMsg ) + { + case WM_ERASEBACKGROUND: + nRet = (MRESULT)FALSE; + bDef = FALSE; + break; + case WM_PAINT: + { + HPS hPS; + RECTL aRect; + hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); + WinEndPaint( hPS ); + bDef = FALSE; + } + bDef = FALSE; + break; + + case WM_BUTTON1DOWN: + case WM_BUTTON2DOWN: + case WM_BUTTON3DOWN: + case SALOBJ_MSG_TOTOP: + if ( ImplSalYieldMutexTryToAcquire() ) + { + pSysObj = GetSalObjWindowPtr( hWnd ); + pSysObj->mpProc( pSysObj->mpInst, pSysObj, + SALOBJ_EVENT_TOTOP, 0 ); + ImplSalYieldMutexRelease(); + } + else + WinPostMsg( hWnd, SALOBJ_MSG_TOTOP, 0, 0 ); + break; + + case WM_FOCUSCHANGE: + case SALOBJ_MSG_POSTFOCUS: + if ( ImplSalYieldMutexTryToAcquire() ) + { + pSysObj = GetSalObjWindowPtr( hWnd ); + if ( SHORT1FROMMP( nMP2 ) ) + { + pSysObj->mhLastFocusWnd = WinQueryFocus( HWND_DESKTOP ); + pSysObj->mpProc( pSysObj->mpInst, pSysObj, + SALOBJ_EVENT_GETFOCUS, 0 ); + } + else + { + HWND hWndFocus = HWNDFROMMP( nMP1 ); + if ( !hWndFocus || !ImplIsSysWindowOrChild( hWnd, hWndFocus ) ) + { + pSysObj->mpProc( pSysObj->mpInst, pSysObj, + SALOBJ_EVENT_LOSEFOCUS, 0 ); + } + } + ImplSalYieldMutexRelease(); + } + else + WinPostMsg( hWnd, SALOBJ_MSG_POSTFOCUS, nMP1, nMP2 ); + break; + + case WM_SIZE: + { + pSysObj = GetSalObjWindowPtr( hWnd ); + pSysObj->mnHeight = (short)SHORT2FROMMP( nMP2 ); + WinSetWindowPos( pSysObj->mhWndChild, 0, + 0, 0, + (short)SHORT1FROMMP( nMP2 ), (short)SHORT2FROMMP( nMP2 ), + SWP_SIZE | SWP_MOVE ); + bDef = FALSE; + } + break; + + case WM_CREATE: + { + // Window-Instanz am Windowhandle speichern + CREATESTRUCT* pStruct = (CREATESTRUCT*)nMP2; + pSysObj = (Os2SalObject*)pStruct->pPresParams; + SetSalObjWindowPtr( hWnd, pSysObj ); + bDef = FALSE; + } + break; + } + + if ( bDef ) + nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); + return nRet; +} + +// ----------------------------------------------------------------------- + +MRESULT EXPENTRY SalSysObjChildWndProc( HWND hWnd, ULONG nMsg, + MPARAM nMP1, MPARAM nMP2 ) +{ + MRESULT nRet = 0; + int bDef = TRUE; + + debug_printf( "SalSysObjChildWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); + + switch( nMsg ) + { + case WM_ERASEBACKGROUND: + // Wegen PlugIn's loeschen wir erstmal den Hintergrund +/* + nRet = (MRESULT)FALSE; + bDef = FALSE; +*/ + break; + case WM_PAINT: + { + HPS hPS; + RECTL aRect; + hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); + WinEndPaint( hPS ); + bDef = FALSE; + } + break; + } + + if ( bDef ) + nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); + return nRet; +} + +// ----------------------------------------------------------------------- + +MRESULT EXPENTRY SalSysObjClipWndProc( HWND hWnd, ULONG nMsg, + MPARAM nMP1, MPARAM nMP2 ) +{ + MRESULT nRet = 0; + int bDef = TRUE; + + debug_printf( "SalSysObjClipWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); + + 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: + { + // Alle Events an den Frame weiterreichen, da diese Bereiche + // dem Frame gehoeren. Dazu muessen die Mouse-Koordinaaten + // entsprechend umgerechnet werden + HWND hWndParent = WinQueryWindow( hWnd, QW_PARENT ); // ergibt SysChild-Fenster + hWndParent = WinQueryWindow( hWndParent, QW_PARENT ); + short nX = (short)SHORT1FROMMP( nMP1 ); + short nY = (short)SHORT2FROMMP( nMP1 ); + POINTL aPos; + aPos.x = nX; + aPos.y = nY; + WinMapWindowPoints( hWnd, hWndParent, &aPos, 1 ); + nMP1 = MPFROM2SHORT( (short)aPos.x, (short)aPos.y ); + bDef = FALSE; + nRet = WinSendMsg( hWndParent, nMsg, nMP1, nMP2 ); + } + break; + + case WM_HITTEST: + // Damit im disablten Zustand die MouseKlicks immer noch + // an den Frame geschickt werden + // Dieser Code reicht leider nicht aus, deshalb wir unter + // OS2 immer das Child-Fenster disablen, im Gegensatz + // zu Windows, wo immer der Parent disablte wird, da + // sich das Fenster evtl. anders Darstellen koennte, + // wenn es disablte wird. Da dieser Fall uns bisher + // nicht bekannt ist, ignorieren wir das. + nRet = HT_NORMAL; + bDef = FALSE; + break; + + case WM_ERASEBACKGROUND: + nRet = (MRESULT)FALSE; + bDef = FALSE; + break; + case WM_PAINT: + { + HPS hPS; + RECTL aRect; + hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); + WinEndPaint( hPS ); + bDef = FALSE; + } + break; + } + + if ( bDef ) + nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); + return nRet; +} + +// ======================================================================= + +void ImplDestroyAllClipWindows( HWND hWndLast ) +{ + if ( hWndLast == HWND_TOP ) + return; + + HWND hWndPrev; + while ( hWndLast ) + { + hWndPrev = WinQueryWindow( hWndLast, QW_PREV ); + WinDestroyWindow( hWndLast ); + hWndLast = hWndPrev; + } +} + +// ======================================================================= + +SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent ) +{ + SalData* pSalData = GetSalData(); + + if ( !pSalData->mbObjClassInit ) + { + if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLASSNAME, + (PFNWP)SalSysObjWndProc, CS_MOVENOTIFY, + SAL_OBJECT_WNDEXTRA ) ) + { + if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLIPCLASSNAME, + (PFNWP)SalSysObjClipWndProc, CS_HITTEST | CS_MOVENOTIFY, 0 ) ) + { + if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CHILDCLASSNAME, + (PFNWP)SalSysObjChildWndProc, CS_HITTEST | CS_MOVENOTIFY, 32 ) ) + pSalData->mbObjClassInit = TRUE; + } + } + } + + if ( pSalData->mbObjClassInit ) + { + Os2SalObject* pObject = new Os2SalObject; + HWND hWnd = WinCreateWindow( pParent->mhWndClient, SAL_OBJECT_CLASSNAME, "", + 0, + 0, 0, 0, 0, + pParent->mhWndClient, HWND_TOP, + 0, NULL, (void*)pObject ); + HWND hWndChild = WinCreateWindow( hWnd, SAL_OBJECT_CHILDCLASSNAME, "", + WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, + 0, 0, 0, 0, + hWnd, HWND_TOP, + 0, NULL, NULL ); + + if ( !hWndChild ) + { + if ( hWnd ) + WinDestroyWindow( hWnd ); + delete pObject; + return NULL; + } + + if ( hWnd ) + { + debug_printf("ImplSalCreateObject hWndChild %x\n", hWndChild); + debug_printf("ImplSalCreateObject hWnd %x\n", hWnd); + pObject->mhWnd = hWnd; + pObject->mhWndChild = hWndChild; + pObject->maSysData.hWnd = hWndChild; + return pObject; + } + } + + return NULL; +} + +// ======================================================================= + +long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* ) +{ + return 0; +} + +// ======================================================================= + +Os2SalObject::Os2SalObject() +{ + SalData* pSalData = GetSalData(); + + mhLastClipWnd = HWND_TOP; + + mhWnd = 0; + mhWndChild = 0; + mhLastFocusWnd = 0; + maSysData.nSize = sizeof( SystemEnvData ); + mnHeight = 0; + mpInst = NULL; + mpProc = ImplSalObjCallbackDummy; + + // Hook installieren, wenn es das erste Os2SalObject ist + if ( !pSalData->mpFirstObject ) + { + WinSetHook( pSalData->mhAB, pSalData->mhMQ, + HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 ); + } + + // Insert object in objectlist + mpNextObject = pSalData->mpFirstObject; + pSalData->mpFirstObject = this; +} + +// ----------------------------------------------------------------------- + +Os2SalObject::~Os2SalObject() +{ + SalData* pSalData = GetSalData(); + + // remove frame from framelist + if ( this == pSalData->mpFirstObject ) + { + pSalData->mpFirstObject = mpNextObject; + + // Wenn letztes Os2SalObject, dann Hook wieder entfernen + if ( !pSalData->mpFirstObject ) + { + WinReleaseHook( pSalData->mhAB, pSalData->mhMQ, + HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 ); + } + } + else + { + Os2SalObject* pTempObject = pSalData->mpFirstObject; + while ( pTempObject->mpNextObject != this ) + pTempObject = pTempObject->mpNextObject; + + pTempObject->mpNextObject = mpNextObject; + } + + // Cache-Daten zerstoeren + ImplDestroyAllClipWindows( mhLastClipWnd ); + + if ( mhWndChild ) + WinDestroyWindow( mhWndChild ); + if ( mhWnd ) + WinDestroyWindow( mhWnd ); +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::ResetClipRegion() +{ + ImplDestroyAllClipWindows( mhLastClipWnd ); + mhLastClipWnd = HWND_TOP; +} + +// ----------------------------------------------------------------------- + +USHORT Os2SalObject::GetClipRegionType() +{ + return SAL_OBJECT_CLIP_EXCLUDERECTS; +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::BeginSetClipRegion( ULONG nRectCount ) +{ + mhOldLastClipWnd = mhLastClipWnd; +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + HWND hClipWnd = WinCreateWindow( mhWnd, SAL_OBJECT_CLIPCLASSNAME, "", + WS_VISIBLE, + nX, mnHeight-(nY+nHeight), nWidth, nHeight, + mhWnd, mhLastClipWnd, + 0, NULL, NULL ); + debug_printf("Os2SalObject::UnionClipRegion hClipWnd %x\n", hClipWnd); + mhLastClipWnd = hClipWnd; +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::EndSetClipRegion() +{ + ImplDestroyAllClipWindows( mhOldLastClipWnd ); +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) +{ + ULONG nStyle = 0; + BOOL bVisible = WinIsWindowVisible( mhWnd ); + if ( bVisible ) + { + WinShowWindow( mhWnd, FALSE ); + nStyle |= SWP_SHOW; + } + SWP aParentSWP; + WinQueryWindowPos( WinQueryWindow( mhWnd, QW_PARENT ), &aParentSWP ); + WinSetWindowPos( mhWnd, 0, nX, aParentSWP.cy-(nY+nHeight), nWidth, nHeight, + SWP_MOVE | SWP_SIZE | nStyle ); +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::Show( BOOL bVisible ) +{ + WinShowWindow( mhWnd, bVisible ); +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::Enable( BOOL bEnable ) +{ + // Im Gegensatz zu Windows disablen wir das Childfenster, + // da ansonsten unser Clippen nicht mehr funktioniert, da + // wir keine Events mehr bekommen. Dadurch kann sich evtl. + // das Fenster anders darstellen, was wir eigentlich nicht + // wollen. Aber da uns bisher kein Fall bekannt ist, + // ignorieren wir dies. Ansonsten muss ein Fenster dazwischen + // gezogen werden oder getestet werden, wie wir die + // Maustransparenz erreichen, wenn mhWnd + // disablte wird. + WinEnableWindow( mhWndChild, bEnable ); +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::GrabFocus() +{ + if ( mhLastFocusWnd && + WinIsWindow( GetSalData()->mhAB, mhLastFocusWnd ) && + ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) ) + WinSetFocus( HWND_DESKTOP, mhLastFocusWnd ); + else + WinSetFocus( HWND_DESKTOP, mhWndChild ); +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::SetBackground() +{ +} + +// ----------------------------------------------------------------------- + +void Os2SalObject::SetBackground( SalColor nSalColor ) +{ +} + +// ----------------------------------------------------------------------- + +const SystemChildData* Os2SalObject::GetSystemData() const +{ + return &maSysData; +} + +// ----------------------------------------------------------------------- +#if 0 +void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc ) +{ + mpInst = pInst; + if ( pProc ) + mpProc = pProc; + else + mpProc = ImplSalObjCallbackDummy; +} +#endif + |