diff options
Diffstat (limited to 'vcl/win/source')
89 files changed, 14057 insertions, 0 deletions
diff --git a/vcl/win/source/app/MAKEFILE.MK b/vcl/win/source/app/MAKEFILE.MK new file mode 100644 index 000000000000..f53f534b69a1 --- /dev/null +++ b/vcl/win/source/app/MAKEFILE.MK @@ -0,0 +1,40 @@ +#************************************************************************* +#* +#* $Workfile: makefile. $ +#* +#* Ersterstellung TH 01.04.97 +#* Letzte Aenderung $Author: hr $ $Date: 2000-09-18 17:05:49 $ +#* $Revision: 1.1.1.1 $ +#* +#* $Logfile: T:/sv2/win/source/app/makefile.__v $ +#* +#* Copyright (c) 1990 - 2000, STAR DIVISION +#* +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=salapp + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +OBJFILES= $(OBJ)$/salmain.obj + +SLOFILES= $(SLO)$/salshl.obj \ + $(SLO)$/saldata.obj \ + $(SLO)$/salinst.obj \ + $(SLO)$/saltimer.obj \ + $(SLO)$/salsound.obj \ + $(SLO)$/salinfo.obj \ + $(SLO)$/salsys.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/win/source/app/saldata.cxx b/vcl/win/source/app/saldata.cxx new file mode 100644 index 000000000000..7142badf3a20 --- /dev/null +++ b/vcl/win/source/app/saldata.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * $RCSfile: saldata.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALDATA_CXX + +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif + +// ======================================================================= + +rtl_TextEncoding ImplSalGetSystemEncoding() +{ + static UINT nOldAnsiCodePage = 0; + static rtl_TextEncoding eEncoding = RTL_TEXTENCODING_MS_1252; + + UINT nAnsiCodePage = GetACP(); + if ( nAnsiCodePage != nOldAnsiCodePage ) + { + switch ( nAnsiCodePage ) + { + case 1252: + eEncoding = RTL_TEXTENCODING_MS_1252; + break; + case 1250: + eEncoding = RTL_TEXTENCODING_MS_1250; + break; + case 1251: + eEncoding = RTL_TEXTENCODING_MS_1251; + break; + case 1253: + eEncoding = RTL_TEXTENCODING_MS_1253; + break; + case 1254: + eEncoding = RTL_TEXTENCODING_MS_1254; + break; + case 1255: + eEncoding = RTL_TEXTENCODING_MS_1255; + break; + case 1256: + eEncoding = RTL_TEXTENCODING_MS_1256; + break; + case 1257: + eEncoding = RTL_TEXTENCODING_MS_1257; + break; + case 1258: + eEncoding = RTL_TEXTENCODING_MS_1258; + break; + case 874: + eEncoding = RTL_TEXTENCODING_MS_874; + break; + case 932: + eEncoding = RTL_TEXTENCODING_MS_932; + break; + case 936: + eEncoding = RTL_TEXTENCODING_MS_936; + break; + case 949: + eEncoding = RTL_TEXTENCODING_MS_949; + break; + case 950: + eEncoding = RTL_TEXTENCODING_MS_950; + break; +// case 1381: +// eEncoding = RTL_TEXTENCODING_MS_1381; +// break; + } + } + + return eEncoding; +} + +// ----------------------------------------------------------------------- + +ByteString ImplSalGetWinAnsiString( const UniString& rStr, BOOL bFileName ) +{ + rtl_TextEncoding eEncoding = ImplSalGetSystemEncoding(); + if ( bFileName ) + { + return ByteString( rStr, eEncoding, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_UNDERLINE | + RTL_UNICODETOTEXT_FLAGS_INVALID_UNDERLINE | + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE | + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR | + RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 ); + } + else + { + return ByteString( rStr, eEncoding, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT | + RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT | + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE | + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR | + RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 ); + } +} + +// ----------------------------------------------------------------------- + +UniString ImplSalGetUniString( const sal_Char* pStr, xub_StrLen nLen ) +{ + return UniString( pStr, nLen, ImplSalGetSystemEncoding(), + RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT | + RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT | + RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT ); +} + +// ======================================================================= + +int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 ) +{ + int nRet; + wchar_t c1; + char c2; + do + { + // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln + c1 = *pStr1; + c2 = *pStr2; + if ( (c1 >= 65) && (c1 <= 90) ) + c1 += 32; + if ( (c2 >= 65) && (c2 <= 90) ) + c2 += 32; + nRet = ((sal_Int32)c1)-((sal_Int32)((unsigned char)c2)); + if ( nRet != 0 ) + break; + + pStr1++; + pStr2++; + } + while ( c2 ); + + return nRet; +} + +// ======================================================================= + +LONG ImplSetWindowLong( HWND hWnd, int nIndex, DWORD dwNewLong ) +{ + if ( aSalShlData.mbWNT ) + return SetWindowLongW( hWnd, nIndex, dwNewLong ); + else + return SetWindowLongA( hWnd, nIndex, dwNewLong ); +} + +// ----------------------------------------------------------------------- + +LONG ImplGetWindowLong( HWND hWnd, int nIndex ) +{ + if ( aSalShlData.mbWNT ) + return GetWindowLongW( hWnd, nIndex ); + else + return GetWindowLongA( hWnd, nIndex ); +} + +// ----------------------------------------------------------------------- + +WIN_BOOL ImplPostMessage( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + if ( aSalShlData.mbWNT ) + return PostMessageW( hWnd, nMsg, wParam, lParam ); + else + return PostMessageA( hWnd, nMsg, wParam, lParam ); +} + +// ----------------------------------------------------------------------- + +WIN_BOOL ImplSendMessage( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + if ( aSalShlData.mbWNT ) + return SendMessageW( hWnd, nMsg, wParam, lParam ); + else + return SendMessageA( hWnd, nMsg, wParam, lParam ); +} + +// ----------------------------------------------------------------------- + +WIN_BOOL ImplGetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax ) +{ + if ( aSalShlData.mbWNT ) + return GetMessageW( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax ); + else + return GetMessageA( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax ); +} + +// ----------------------------------------------------------------------- + +WIN_BOOL ImplPeekMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg ) +{ + if ( aSalShlData.mbWNT ) + return PeekMessageW( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg ); + else + return PeekMessageA( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg ); +} + +// ----------------------------------------------------------------------- + +LONG ImplDispatchMessage( CONST MSG *lpMsg ) +{ + if ( aSalShlData.mbWNT ) + return DispatchMessageW( lpMsg ); + else + return DispatchMessageA( lpMsg ); +} + diff --git a/vcl/win/source/app/salinfo.cxx b/vcl/win/source/app/salinfo.cxx new file mode 100644 index 000000000000..97a3b0c97e35 --- /dev/null +++ b/vcl/win/source/app/salinfo.cxx @@ -0,0 +1,884 @@ +/************************************************************************* + * + * $RCSfile: salinfo.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef ENABLEUNICODE + +#define VCL_NEED_BASETSD + +#include <tools/presys.h> +#include <windows.h> +#include <imagehlp.h> +#include <tools/postsys.h> + +#include <salsys.hxx> + +/* !!! UNICODE !!! */ +XubString SalSystem::GetSummarySystemInfos( ULONG nFlags ) +{ + return XubString(); +} + +#else + +#define VCL_NEED_BASETSD + +#include <tools/presys.h> +#include <windows.h> +#include <imagehlp.h> +#include <tools/postsys.h> + +#include <stdio.h> +#include <tools/string.hxx> +#include <salsys.hxx> + +// Wegen Stacktrace-Generierung +#pragma optimize ("", off) + +// #include <tlhelp32.h> +// ToolHelp32 +#define MAX_MODULE_NAME32 255 +#define TH32CS_SNAPMODULE 0x00000008 + +typedef struct tagMODULEENTRY32 +{ + DWORD dwSize; + DWORD th32ModuleID; // This module + DWORD th32ProcessID; // owning process + DWORD GlblcntUsage; // Global usage count on the module + DWORD ProccntUsage; // Module usage count in th32ProcessID's context + BYTE * modBaseAddr; // Base address of module in th32ProcessID's context + DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr + HMODULE hModule; // The hModule of this module in th32ProcessID's context + char szModule[MAX_MODULE_NAME32 + 1]; + char szExePath[MAX_PATH]; +} MODULEENTRY32; +typedef MODULEENTRY32 * PMODULEENTRY32; +typedef MODULEENTRY32 * LPMODULEENTRY32; + +// PSAPI functions - Windows NT only +typedef struct _MODULEINFO { + LPVOID lpBaseOfDll; + DWORD SizeOfImage; + LPVOID EntryPoint; +} MODULEINFO, *LPMODULEINFO; + + + +// PSAPI +typedef BOOL (WINAPI *ENUMPROCESSMODULESPROC)( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded ); +typedef BOOL (WINAPI *GETMODULEINFORMATIONPROC)( HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb ); +typedef DWORD (WINAPI *GETMODULEBASENAMEAPROC)( HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize ); +typedef DWORD (WINAPI *GETMODULEFILENAMEEXAPROC)( HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize ); +typedef HANDLE (WINAPI *CREATESNAPSHOTPROC)(DWORD dwFlags, DWORD th32ProcessID); +typedef BOOL (WINAPI *MODULE32FIRSTPROC)( HANDLE hSnapshot, LPMODULEENTRY32 lpme ); +typedef BOOL (WINAPI *MODULE32NEXTPROC)( HANDLE hSnapshot, LPMODULEENTRY32 lpme ); + + +// ImageHlp +typedef int (__stdcall *STACKWALKPROC) ( DWORD, HANDLE, HANDLE, LPSTACKFRAME, PVOID, PREAD_PROCESS_MEMORY_ROUTINE,PFUNCTION_TABLE_ACCESS_ROUTINE, PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE ); +typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)( HANDLE, DWORD ); +typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)( HANDLE, DWORD ); +typedef DWORD (__stdcall *SYMSETOPTIONSPROC ) (DWORD dwSymOptions); +typedef int (__stdcall *SYMINITIALIZEPROC ) ( HANDLE, LPSTR, int ); +typedef int (__stdcall *SYMCLEANUPPROC)( HANDLE ); +typedef DWORD (__stdcall WINAPI *UNDECORATESYMBOLNAMEPROC)( PCSTR, PSTR, DWORD, DWORD ); +typedef DWORD (__stdcall *SYMLOADMODULEPROC) ( HANDLE, HANDLE, LPSTR, LPSTR, DWORD, DWORD ); +typedef int (__stdcall *SYMGETSYMFROMADDR)( HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL ); + + +struct ModuleInfo +{ + struct ModuleInfo* pNext; + + char szModBaseName[MAX_PATH]; + char szModFileName[MAX_PATH]; + unsigned long nBaseAddress; + unsigned long nSize; +// unsigned long nEntryPoint; +// HANDLE nHandle; +// PIMAGE_DEBUG_INFORMATION pDebugInfos; +}; + +struct ModuleInfo* FindModuleContainingAddress( struct ModuleInfo* pStart, void* pAddr ); + + + +struct SystemInfos +{ + DWORD nCurrentProcessId; + HANDLE hCurrentProcess; + DWORD nCurrentThreadId; + HANDLE hCurrentThread; + + ModuleInfo* pModInfos; + + String aStack; + String aModules; + String aSystemVersion; + String aCPUType; + String aMemoryInfo; + String aLocalVolumes; + String aSystemDirs; + String aMouseInfo; + + SystemInfos() + { + nCurrentProcessId = 0; + hCurrentProcess = 0; + hCurrentThread = 0; + pModInfos = NULL; + } +}; + +void DebugThread( SystemInfos* pSysInfos ); + + +typedef struct _Thread +{ + DWORD dwThreadId; + HANDLE hThread; +} Thread; + + +struct ModuleInfo* WNT_CreateModuleInfos(); + +String ImplCreateToken( const String& rToken ) +{ + String aToken( '<' ); + aToken += rToken; + aToken += ' '; + while ( aToken.Len() < 25 ) + aToken += '-'; + aToken += '>'; + return aToken; +} + + + +String WNT_CreateModulePath( struct ModuleInfo* pModInfos ) +{ + String aPath; + struct ModuleInfo* pM = pModInfos; + while ( pM ) + { + String aTmpPath = pM->szModFileName; + USHORT n = aTmpPath.SearchBackward( '\\' ); + if ( n != STRING_NOTFOUND ) + aTmpPath.Erase( n ); + aTmpPath += ';'; + aTmpPath.ToLower(); + if ( aPath.Search( aTmpPath ) == STRING_NOTFOUND ) + aPath += aTmpPath; + + pM = pM->pNext; + } + return aPath; +} + + +struct ModuleInfo* WNT_CreateModuleInfos() +{ + struct ModuleInfo* pModInfos = NULL; + + OSVERSIONINFO aOSVersion; + aOSVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + if ( GetVersionEx( &aOSVersion ) ) + { + if ( aOSVersion.dwPlatformId == VER_PLATFORM_WIN32_NT ) + { + HINSTANCE hPSAPILib = LoadLibrary( "PSAPI.DLL" ); + if( hPSAPILib ) + { + ENUMPROCESSMODULESPROC _fpEnumProcessModules = (ENUMPROCESSMODULESPROC) GetProcAddress( hPSAPILib, "EnumProcessModules" ); + GETMODULEINFORMATIONPROC _fpGetModuleInformation = (GETMODULEINFORMATIONPROC) GetProcAddress( hPSAPILib, "GetModuleInformation" ); + GETMODULEBASENAMEAPROC _fpGetModuleBaseNameA = (GETMODULEBASENAMEAPROC) GetProcAddress( hPSAPILib, "GetModuleBaseNameA" ); + GETMODULEFILENAMEEXAPROC _fpGetModuleFileNameExA = (GETMODULEFILENAMEEXAPROC) GetProcAddress( hPSAPILib, "GetModuleFileNameExA" ); + + HANDLE hProcess = GetCurrentProcess(); + HMODULE hMods[1024]; + DWORD cbNeeded; + if( _fpEnumProcessModules( hProcess, hMods, sizeof(hMods), &cbNeeded ) ) + { + int nMods = cbNeeded / sizeof( HMODULE ); + int nArrSz = nMods * sizeof( struct ModuleInfo ); + pModInfos = (struct ModuleInfo*) malloc( nArrSz ); + memset( pModInfos, 0, nArrSz ); + + for ( int i = 0; i < nMods; i++ ) + { + pModInfos[i].pNext = 0; + if ( i ) + pModInfos[i-1].pNext = &pModInfos[i]; + + _fpGetModuleBaseNameA( hProcess, hMods[i], pModInfos[i].szModBaseName, sizeof( pModInfos[i].szModBaseName ) ); + _fpGetModuleFileNameExA( hProcess, hMods[i], pModInfos[i].szModFileName, sizeof( pModInfos[i].szModFileName ) ); + + MODULEINFO aInf; + if ( _fpGetModuleInformation( hProcess, hMods[i], &aInf, sizeof( aInf ) ) ) + { + pModInfos[i].nBaseAddress = (unsigned long) aInf.lpBaseOfDll; + pModInfos[i].nSize = aInf.SizeOfImage; + // pModInfos[i].nEntryPoint = (unsigned long) aInf.EntryPoint; + } + } + } + FreeLibrary( hPSAPILib ); + } + } + else if ( aOSVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) + { + HINSTANCE hToolHelpLib = LoadLibrary( "KERNEL32.DLL" ); + if( hToolHelpLib ) + { + CREATESNAPSHOTPROC _fpCreateSnapshot = (CREATESNAPSHOTPROC) GetProcAddress( hToolHelpLib, "CreateToolhelp32Snapshot" ); + MODULE32FIRSTPROC _fpModule32First = (MODULE32FIRSTPROC) GetProcAddress( hToolHelpLib, "Module32First" ); + MODULE32NEXTPROC _fpModule32Next = (MODULE32NEXTPROC) GetProcAddress( hToolHelpLib, "Module32Next" ); + + HANDLE hSnap = _fpCreateSnapshot( TH32CS_SNAPMODULE, 0 ); + if ( hSnap ) + { + MODULEENTRY32 aMod32Entry; + ZeroMemory( &aMod32Entry, sizeof( MODULEENTRY32 ) ); + aMod32Entry.dwSize = sizeof( MODULEENTRY32 ); + int nMods = 0; + BOOL bMod = _fpModule32First( hSnap, &aMod32Entry ); + while ( bMod ) + { + nMods++; + bMod = _fpModule32Next( hSnap, &aMod32Entry ); + } + + int nArrSz = nMods * sizeof( struct ModuleInfo ); + pModInfos = (struct ModuleInfo*) malloc( nArrSz ); + memset( pModInfos, 0, nArrSz ); + + int nMod = 0; + bMod = _fpModule32First( hSnap, &aMod32Entry ); + while ( bMod ) + { + pModInfos[nMod].pNext = 0; + if ( nMod ) + pModInfos[nMod-1].pNext = &pModInfos[nMod]; + + strcpy( pModInfos[nMod].szModBaseName, aMod32Entry.szModule ); + strcpy( pModInfos[nMod].szModFileName, aMod32Entry.szExePath ); + pModInfos[nMod].nBaseAddress = (unsigned long) aMod32Entry.modBaseAddr; + pModInfos[nMod].nSize = aMod32Entry.modBaseSize; +// pModInfos[nMod].nEntryPoint = 0xFFFFFFFF; + + bMod = _fpModule32Next( hSnap, &aMod32Entry ); + nMod++; + } + + CloseHandle( hSnap ); + } + + FreeLibrary( hToolHelpLib ); + } + } + } + return pModInfos; +} + +BOOL WNT_GetLogicalAddress( PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset ) +{ + MEMORY_BASIC_INFORMATION mbi; + + if( VirtualQuery( addr, &mbi, sizeof(mbi) ) && mbi.AllocationBase ) + { + DWORD hMod = (DWORD)mbi.AllocationBase; + + if ( !GetModuleFileName( (HMODULE)hMod, szModule, len ) ) + return FALSE; + + // Point to the DOS header in memory + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; + + // From the DOS header, find the NT (PE) header + PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew); + + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr ); + + DWORD rva = (DWORD)addr - hMod; // RVA is offset from module load address + + // Iterate through the section table, looking for the one that encompasses + // the linear address. + for ( unsigned i = 0; + i < pNtHdr->FileHeader.NumberOfSections; + i++, pSection++ ) + { + DWORD sectionStart = pSection->VirtualAddress; + DWORD sectionEnd = sectionStart + + max(pSection->SizeOfRawData, pSection->Misc.VirtualSize); + + // Is the address in this section??? + if ( (rva >= sectionStart) && (rva <= sectionEnd) ) + { + // Yes, address is in the section. Calculate section and offset, + // and store in the "section" & "offset" params, which were + // passed by reference. + section = i+1; + offset = rva - sectionStart; + return TRUE; + } + } + } + return FALSE; +} + + +struct ModuleInfo* FindModuleContainingAddress( struct ModuleInfo* pStart, void* pAddr ) +{ + struct ModuleInfo* pRet = NULL; + struct ModuleInfo* pM = pStart; + unsigned long nAddr = (unsigned long) pAddr; + + while ( pM && !pRet ) + { + if ( ( nAddr >= pM->nBaseAddress ) && + ( nAddr < ( pM->nBaseAddress + pM->nSize ) ) ) + { + pRet = pM; + } + else + { + pM = pM->pNext; + } + } + return pRet; +} + +String _OLD_GetStackInfo() +{ + // Try an other way... + String aTmpStack; + ModuleInfo* pMods = WNT_CreateModuleInfos(); + + ULONG* pBP; + __asm mov pBP, ebp; + char buffer[1024]; + + for ( int i = 0; i < 15; i++ ) + { + ULONG nIP = pBP[1]; + sprintf( buffer, "[%.2u] IP=%.8lx", i, nIP ); + aTmpStack += buffer; + + ModuleInfo* pI = FindModuleContainingAddress( pMods, (void*)nIP ); + if ( pI ) + { + sprintf( buffer, " (Rel=%.8lx) [%s, Base=%.8lx, Path=%s]", nIP-pI->nBaseAddress-0x1000, pI->szModBaseName, pI->nBaseAddress, pI->szModFileName ); + aTmpStack += buffer; + } + + if ( !pI || (pBP[0] & 3) || (ULONG)pBP > pBP[0] ) + { + aTmpStack += "\nError!\n"; + break; + } + + aTmpStack += '\n'; + pBP = (ULONG*) pBP[0]; + } + + // Modul-Infos zerstoeren... + return aTmpStack; +} + +String SalSystem::GetSummarySystemInfos( ULONG nFlags) +{ + SystemInfos aSysInfos; + HANDLE nCurrentThreadPseudo = GetCurrentThread(); + HANDLE nCurrentProcessPseudo = GetCurrentProcess(); + aSysInfos.nCurrentThreadId = GetCurrentThreadId(); + DuplicateHandle( nCurrentProcessPseudo, nCurrentThreadPseudo, nCurrentProcessPseudo, + &aSysInfos.hCurrentThread, PROCESS_ALL_ACCESS, TRUE, 0 ); + aSysInfos.nCurrentProcessId = GetCurrentProcessId(); + DuplicateHandle( nCurrentProcessPseudo, nCurrentProcessPseudo, nCurrentProcessPseudo, + &aSysInfos.hCurrentProcess, PROCESS_ALL_ACCESS, TRUE, 0 ); + + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_STACK ) + { + DWORD nDebugThreadId; + HANDLE hDebugThread = CreateThread( + NULL, 16000, + (LPTHREAD_START_ROUTINE)DebugThread, &aSysInfos, + 0, &nDebugThreadId ); + + WaitForSingleObject( hDebugThread, INFINITE ); + CloseHandle( hDebugThread ); + } + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_MODULES ) + { + aSysInfos.aModules = "<Modules>\n"; + char buffer[1024]; + if ( !aSysInfos.pModInfos ) + aSysInfos.pModInfos = WNT_CreateModuleInfos(); + struct ModuleInfo* pM = aSysInfos.pModInfos; + while ( pM ) + { + aSysInfos.aModules += " <Module name=\""; + aSysInfos.aModules += pM->szModBaseName; + aSysInfos.aModules += "\" path=\""; + aSysInfos.aModules += pM->szModFileName; + aSysInfos.aModules += "\" >\n"; + aSysInfos.aModules += " <ModuleInfo name=\"BASE\" value=\""; + sprintf( buffer, "%.8lx", pM->nBaseAddress ); + aSysInfos.aModules += buffer; + aSysInfos.aModules += "\" />\n"; + aSysInfos.aModules += " <ModuleInfo name=\"Size\" value=\""; + aSysInfos.aModules += pM->nSize; + aSysInfos.aModules += "\" />\n </Module>\n"; + pM = pM->pNext; + } + aSysInfos.aModules += "</Modules>"; + } + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_SYSTEMVERSION ) + { + aSysInfos.aSystemVersion = "<System name=\""; + OSVERSIONINFO aVersionInfos; + memset(&aVersionInfos, 0, sizeof( OSVERSIONINFO ) ); + aVersionInfos.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + GetVersionEx( &aVersionInfos ); + if ( aVersionInfos.dwPlatformId == VER_PLATFORM_WIN32s ) + aSysInfos.aSystemVersion += "Microsoft Win32s"; + else if ( aVersionInfos.dwPlatformId == VER_PLATFORM_WIN32_NT ) + aSysInfos.aSystemVersion += "Microsoft Windows NT"; + else if ( aVersionInfos.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) + { + if ( !aVersionInfos.dwMinorVersion ) + aSysInfos.aSystemVersion += "Microsoft Windows 95"; + else + aSysInfos.aSystemVersion += "Microsoft Windows 98"; + } + else + aSysInfos.aSystemVersion += "Unknown Windows"; + aSysInfos.aSystemVersion += "\" version=\""; + aSysInfos.aSystemVersion += aVersionInfos.dwMajorVersion; + aSysInfos.aSystemVersion += '.'; + aSysInfos.aSystemVersion += aVersionInfos.dwMinorVersion; + aSysInfos.aSystemVersion += "\" build=\""; + aSysInfos.aSystemVersion += aVersionInfos.dwBuildNumber&0xFFFF; + aSysInfos.aSystemVersion += "\" />"; + + // aSysInfos.aSystemVersion += aVersionInfos.szCSDVersion; + /* + Under both Windows NT and Windows 95, you can get the + language information in the FileVersionInfo of User.exe by + calling GetFileVersionInfo, and then + VerQueryValue (on \\VarFileInfo\\Translation") on the + VersionInfo block of the operating system's User.exe. + NOTE: This method is the most reliable. It works well under + both Windows NT and Windows 95. This method also works for + Windows 3.1 + */ +// DWORD nDefInputLanguage; +// if ( SystemParametersInfo( SPI_GETDEFAULTINPUTLANG, 0, &nDefInputLanguage, 0 ) ) +// { +// aSysInfos.aSystemVersion += " default input language = "; +// aSysInfos.aSystemVersion += nDefInputLanguage; +// } + } + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_CPUTYPE ) + { + SYSTEM_INFO aSystemInfo; + memset( &aSystemInfo, 0, sizeof( SYSTEM_INFO ) ); + GetSystemInfo( &aSystemInfo ); + aSysInfos.aCPUType = "<CPU count=\""; + aSysInfos.aCPUType += aSystemInfo.dwNumberOfProcessors; + aSysInfos.aCPUType += "\" type=\""; + if ( aSystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) + aSysInfos.aCPUType += "X86"; + else if ( aSystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) + aSysInfos.aCPUType += "MIPS"; + else if ( aSystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) + aSysInfos.aCPUType += "ALPHA"; + else if ( aSystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) + aSysInfos.aCPUType += "PPC"; + else + aSysInfos.aCPUType += "unknown"; + aSysInfos.aCPUType += "\"></CPU>"; + } + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_MEMORYINFO ) + { + MEMORYSTATUS aMemStatus; + memset( &aMemStatus, 0, sizeof( MEMORYSTATUS ) ); + GlobalMemoryStatus( &aMemStatus ); + aSysInfos.aMemoryInfo = "<Memory>\n"; + aSysInfos.aMemoryInfo += " <MemoryType name=\"Physical\" total=\""; + aSysInfos.aMemoryInfo += (aMemStatus.dwTotalPhys+512)/1024/1024+1; + aSysInfos.aMemoryInfo += " MB\" free=\""; + aSysInfos.aMemoryInfo += (aMemStatus.dwAvailPhys+512)/1024/1024+1; + aSysInfos.aMemoryInfo += " MB\" />\n"; + aSysInfos.aMemoryInfo += " <MemoryType name=\"Swap\" total=\""; + aSysInfos.aMemoryInfo += (aMemStatus.dwTotalPageFile+512)/1024/1024+1; + aSysInfos.aMemoryInfo += " MB\" free=\""; + aSysInfos.aMemoryInfo += (aMemStatus.dwAvailPageFile+512)/1024/1024+1; + aSysInfos.aMemoryInfo += " MB\" />\n"; + aSysInfos.aMemoryInfo += " <MemoryType name=\"Virtual\" total=\""; + aSysInfos.aMemoryInfo += (aMemStatus.dwTotalVirtual+512)/1024/1024+1; + aSysInfos.aMemoryInfo += " MB\" free=\""; + aSysInfos.aMemoryInfo += (aMemStatus.dwAvailVirtual+512)/1024/1024+1; + aSysInfos.aMemoryInfo += " MB\" />\n"; + aSysInfos.aMemoryInfo += "</Memory>"; + } + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_LOCALVOLUMES ) + { + aSysInfos.aLocalVolumes = "<LocalVolumes>\n"; + char aDriveStrings[4096]; + GetLogicalDriveStrings( 4096, aDriveStrings ); + LPTSTR pDriveStr = aDriveStrings; + while ( *pDriveStr ) + { + UINT nType = GetDriveType( pDriveStr ); + if ( nType != DRIVE_REMOTE ) + { + aSysInfos.aLocalVolumes += " <LocalVolume type=\""; + + switch ( nType ) + { + case DRIVE_REMOVABLE: aSysInfos.aLocalVolumes += "Removable"; break; + case DRIVE_FIXED: aSysInfos.aLocalVolumes += "Fixed"; break; + case DRIVE_REMOTE: aSysInfos.aLocalVolumes += "Remote"; break; + case DRIVE_CDROM: aSysInfos.aLocalVolumes += "CD-ROM"; break; + case DRIVE_RAMDISK: aSysInfos.aLocalVolumes += "RAM disk"; break; + default: aSysInfos.aLocalVolumes += "Unkown"; + } + aSysInfos.aLocalVolumes += "\" path=\""; + aSysInfos.aLocalVolumes += pDriveStr; + aSysInfos.aLocalVolumes += "\""; + if( nType == DRIVE_FIXED ) + { + DWORD nSectorsPerCluster; + DWORD nBytesPerSector; + DWORD nNumberFreeClusters; + DWORD nNumberTotalClusters; + if( GetDiskFreeSpace( pDriveStr, &nSectorsPerCluster, &nBytesPerSector, &nNumberFreeClusters, &nNumberTotalClusters ) ) + { + DWORD nUnitsPerCluster = nSectorsPerCluster*nBytesPerSector; + DWORD nUnitDivi = 1; + String aUnit = "bytes"; + if( ( nUnitsPerCluster % 1024 ) == 0 ) + { + aUnit = "KB"; + nUnitsPerCluster /= 1024; + } + else if( ( nUnitsPerCluster % 512 ) == 0 ) + { + aUnit = "KB"; + nUnitDivi = 1024; + } + DWORD nFree = nNumberFreeClusters*nUnitsPerCluster/nUnitDivi; + aSysInfos.aLocalVolumes += " free=\""; + aSysInfos.aLocalVolumes += nFree; + aSysInfos.aLocalVolumes += ' '; + aSysInfos.aLocalVolumes += aUnit; + aSysInfos.aLocalVolumes += "\""; + } + } + aSysInfos.aLocalVolumes += " />\n"; + } + while ( *pDriveStr ) + pDriveStr++; + pDriveStr++; + } + aSysInfos.aLocalVolumes += "</LocalVolumes>"; + } + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_SYSTEMDIRS ) + { + aSysInfos.aSystemDirs = "<SystemDirs>\n"; + char buffer[ MAX_PATH ]; + aSysInfos.aSystemDirs += " <SystemDir envname=\"Windows\" path=\""; + if( GetWindowsDirectory( buffer, MAX_PATH ) ) + aSysInfos.aSystemDirs += buffer; + aSysInfos.aSystemDirs += "\" />\n"; + + aSysInfos.aSystemDirs += " <SystemDir envname=\"System\" path=\""; + if( GetSystemDirectory( buffer, MAX_PATH ) ) + aSysInfos.aSystemDirs += buffer; + aSysInfos.aSystemDirs += "\" />\n"; + + aSysInfos.aSystemDirs += " <SystemDir envname=\"Current\" path=\""; + if( GetCurrentDirectory( MAX_PATH, buffer ) ) + aSysInfos.aSystemDirs += buffer; + aSysInfos.aSystemDirs += "\" />\n"; + + aSysInfos.aSystemDirs += " <SystemDir envname=\"Temp\" path=\""; + if( GetTempPath( MAX_PATH, buffer ) ) + aSysInfos.aSystemDirs += buffer; + aSysInfos.aSystemDirs += "\" />\n"; + aSysInfos.aSystemDirs += "</SystemDirs>"; + + } + if ( nFlags & SALSYSTEM_GETSYSTEMINFO_MOUSEINFO ) + { + aSysInfos.aMouseInfo = "<Mouse "; + int nRet = GetSystemMetrics( SM_CMOUSEBUTTONS ); + if ( nRet ) + { + aSysInfos.aMouseInfo += "buttons=\""; + aSysInfos.aMouseInfo += nRet; + aSysInfos.aMouseInfo += "\" description=\""; + if( GetSystemMetrics( 75 /*SM_MOUSEWHEELPRESENT - missing in SDK from MSVC4.2 */ ) ) + aSysInfos.aMouseInfo += "wheel mouse"; + else + aSysInfos.aMouseInfo += "standard mouse"; + aSysInfos.aMouseInfo += "\""; + } + else + { + aSysInfos.aMouseInfo += "description=\"Not installed.\""; + } + aSysInfos.aMouseInfo += " />"; + } + + CloseHandle( aSysInfos.hCurrentThread ); + CloseHandle( aSysInfos.hCurrentProcess ); + + String aInfos; + + aInfos += aSysInfos.aSystemVersion; + aInfos += "\n\n"; + + aInfos += aSysInfos.aCPUType; + aInfos += "\n\n"; + + aInfos += aSysInfos.aMouseInfo; + aInfos += "\n\n"; + + aInfos += aSysInfos.aMemoryInfo; + aInfos += "\n\n"; + + aInfos += aSysInfos.aStack; + aInfos += "\n\n"; + + aInfos += aSysInfos.aModules; + aInfos += "\n\n"; + + aInfos += aSysInfos.aLocalVolumes; + aInfos += "\n\n"; + + aInfos += aSysInfos.aSystemDirs; + aInfos += "\n\n"; + + return aInfos; +} + + + + +void DebugThread( SystemInfos* pSysInfos ) +{ + HINSTANCE hImageHelpLib = LoadLibrary( "IMAGEHLP.DLL" ); + if( hImageHelpLib ) + { + if ( SuspendThread( pSysInfos->hCurrentThread ) != 0xFFFFFFFF ) + { + STACKFRAME aStackFrame; + memset( &aStackFrame, 0, sizeof( aStackFrame ) ); + + CONTEXT aContext; + memset( &aContext, 0, sizeof( aContext ) ); + aContext.ContextFlags = CONTEXT_FULL; + if ( GetThreadContext( pSysInfos->hCurrentThread, &aContext ) ) + { + STACKWALKPROC _fpStackWalk = (STACKWALKPROC) GetProcAddress( hImageHelpLib, "StackWalk" ); + SYMFUNCTIONTABLEACCESSPROC _fpSymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC) GetProcAddress( hImageHelpLib, "SymFunctionTableAccess" ); + SYMGETMODULEBASEPROC _fpSymGetModuleBase = (SYMGETMODULEBASEPROC) GetProcAddress( hImageHelpLib, "SymGetModuleBase" ); + SYMSETOPTIONSPROC _fpSymSetOptionsProc = (SYMSETOPTIONSPROC) GetProcAddress( hImageHelpLib, "SymGetOptions" ); + SYMINITIALIZEPROC _fpSymInitializeProc = (SYMINITIALIZEPROC) GetProcAddress( hImageHelpLib, "SymInitialize" ); + SYMCLEANUPPROC _fpSymCleanup = (SYMCLEANUPPROC) GetProcAddress( hImageHelpLib, "SymCleanup" ); + UNDECORATESYMBOLNAMEPROC _fpUndecorateSymbolName = (UNDECORATESYMBOLNAMEPROC) GetProcAddress( hImageHelpLib, "UnDecorateSymbolName" ); + SYMLOADMODULEPROC _fpSymLoadModule = ( SYMLOADMODULEPROC) GetProcAddress( hImageHelpLib, "SymLoadModule" ); + SYMGETSYMFROMADDR _fpSymGetSymFromAddr = ( SYMGETSYMFROMADDR ) GetProcAddress( hImageHelpLib, "SymGetSymFromAddr" ); + + if ( !pSysInfos->pModInfos ) + pSysInfos->pModInfos = WNT_CreateModuleInfos(); + + _fpSymSetOptionsProc( SYMOPT_DEFERRED_LOADS ); + + char buffer[1024]; + + // Initialize the imagehlp symbol handler + BOOL bAutoLoad = FALSE; +// String aPath = WNT_CreateModulePath( pSysInfos->pModInfos ); +// USHORT nLen = aPath.Len(); +// memcpy( buffer, aPath.GetStr(), nLen ); +// buffer[nLen] = 0; +// BOOL bSymbols = _fpSymInitializeProc( pSysInfos->hCurrentProcess, NULL, bAutoLoad ); + // Path funktioniert nicht, also lade ich unten alle von Hand! + BOOL bSymbols = _fpSymInitializeProc( pSysInfos->hCurrentProcess, NULL, bAutoLoad ); + + // Load symbol modules for the current process + if ( bSymbols && !bAutoLoad ) + { + // LoadModuleSymbols( pSysInfos->nCurrentProcessId, pSysInfos->hCurrentProcess ); + struct ModuleInfo* pM = pSysInfos->pModInfos; + char buffer1[1024]; + char buffer2[1024]; + + while ( pM ) + { + strcpy( buffer1, pM->szModFileName ); + strcpy( buffer2, pM->szModBaseName ); + + BOOL bDone = _fpSymLoadModule( pSysInfos->hCurrentProcess, 0, buffer1, buffer2, pM->nBaseAddress, pM->nSize ); + + pM = pM->pNext; + } + } + + // Initialize the STACKFRAME structure for the first call. This is only + // necessary for Intel CPUs, and isn't mentioned in the documentation. + aStackFrame.AddrPC.Offset = aContext.Eip; + aStackFrame.AddrPC.Mode = AddrModeFlat; + aStackFrame.AddrStack.Offset = aContext.Esp; + aStackFrame.AddrStack.Mode = AddrModeFlat; + aStackFrame.AddrFrame.Offset = aContext.Ebp; + aStackFrame.AddrFrame.Mode = AddrModeFlat; + + + pSysInfos->aStack = "<Stack type=\"WIN32\" >\n"; + + for ( int nS = 0; nS < 20; nS++ ) + { + SetLastError( 0 ); + BOOL bStack = _fpStackWalk( IMAGE_FILE_MACHINE_I386, + pSysInfos->hCurrentProcess, + pSysInfos->hCurrentThread, + &aStackFrame, + &aContext, + NULL, // ReadProcessMemory, + _fpSymFunctionTableAccess, + _fpSymGetModuleBase, + NULL ); + + if ( !bStack || !aStackFrame.AddrReturn.Offset || !aStackFrame.AddrFrame.Offset ) + break; + + pSysInfos->aStack += " <StackInfo pos=\""; + pSysInfos->aStack += (USHORT)nS; + pSysInfos->aStack += "\" ip=\""; + ULONG nIP = aStackFrame.AddrReturn.Offset; + sprintf( buffer, "%.8lx", nIP ); + pSysInfos->aStack += buffer; + pSysInfos->aStack += "\""; + + TCHAR aModuleFileName[MAX_PATH]; + DWORD section, offset; + if ( WNT_GetLogicalAddress( (void*)nIP, aModuleFileName, MAX_PATH, section, offset ) ) + { + pSysInfos->aStack += " rel=\""; + sprintf( buffer, "%.8lx", offset ); + pSysInfos->aStack += buffer; + pSysInfos->aStack += "\" file=\""; + char* pModName = strrchr( aModuleFileName, '\\' ); + pSysInfos->aStack += pModName ? (pModName+1) : aModuleFileName; + pSysInfos->aStack += "\""; + } + else + { + pSysInfos->aStack += " rel=\"ERROR\""; + break; + } + + if ( bSymbols ) + { + + BYTE symbolBuffer[ sizeof(IMAGEHLP_SYMBOL) + 512 ]; + PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer; + memset( symbolBuffer, 0, sizeof(symbolBuffer) ); + pSymbol->SizeOfStruct = sizeof(symbolBuffer); + pSymbol->MaxNameLength = sizeof(symbolBuffer) - sizeof(IMAGEHLP_SYMBOL) + 1; + + DWORD symDisplacement = 0; // Displacement of the input address, + // relative to the start of the symbol + + if ( _fpSymGetSymFromAddr( pSysInfos->hCurrentProcess, aStackFrame.AddrReturn.Offset, + &symDisplacement, pSymbol ) ) + { + pSysInfos->aStack += " ordinal=\""; + _fpUndecorateSymbolName( pSymbol->Name, buffer, 1024, UNDNAME_NAME_ONLY ); + pSysInfos->aStack += buffer; + pSysInfos->aStack += "\""; + // aStackLine += '<'; + // _fpUndecorateSymbolName( pSymbol->Name, buffer, 1024, UNDNAME_COMPLETE ); + // aStackLine += buffer; + // aStackLine += '>'; + } + else // No symbol found. Print out the logical address instead. + { + pSysInfos->aStack += " ordinal=\"???\""; + } + } + + pSysInfos->aStack += " />\n"; + } + pSysInfos->aStack += "</Stack>"; + _fpSymCleanup( pSysInfos->hCurrentProcess ); + } + ResumeThread( pSysInfos->hCurrentThread ); + } + FreeLibrary( hImageHelpLib ); + } +} + +#endif diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx new file mode 100644 index 000000000000..bafb98e35bfa --- /dev/null +++ b/vcl/win/source/app/salinst.cxx @@ -0,0 +1,897 @@ +/************************************************************************* + * + * $RCSfile: salinst.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> +#include <tools/svwin.h> +#ifdef WNT +#include <process.h> +#endif + +#define _SV_SALINST_CXX + +#ifndef _VOS_MUTEX_HXX +#include <vos/mutex.hxx> +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALIDS_HRC +#include <salids.hrc> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALINST_HXX +#include <salinst.hxx> +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif +#ifndef _SV_SALOBJ_HXX +#include <salobj.hxx> +#endif +#ifndef _SV_SALSYS_HXX +#include <salsys.hxx> +#endif +#ifndef _SV_SALTIMER_HXX +#include <saltimer.hxx> +#endif +#ifndef _SV_SALSOUND_HXX +#include <salsound.hxx> +#endif +#ifndef _SV_SALATYPE_HXX +#include <salatype.hxx> +#endif +#ifndef _SV_SYSDATA_HXX +#include <sysdata.hxx> +#endif + +#ifndef _SV_TIMER_HXX +#include <timer.hxx> +#endif + +// ======================================================================= + +void SalAbort( const XubString& rErrorText ) +{ + ImplFreeSalGDI(); + + if ( !rErrorText.Len() ) + FatalAppExit( 0, "Application Error" ); + else + { + ByteString aErrorText( ImplSalGetWinAnsiString( rErrorText ) ); + FatalAppExit( 0, aErrorText.GetBuffer() ); + } +} + +// ======================================================================= + +LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ); +LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ); + +// ======================================================================= + +class SalYieldMutex : public NAMESPACE_VOS(OMutex) +{ +public: // for ImplSalYield() + SalInstanceData* mpInstData; + ULONG mnCount; + DWORD mnThreadId; + +public: + SalYieldMutex( SalInstanceData* pInstData ); + + virtual void SAL_CALL acquire(); + virtual void SAL_CALL release(); + virtual sal_Bool SAL_CALL tryToAcquire(); + + ULONG GetAcquireCount( ULONG nThreadId ); +}; + +// ----------------------------------------------------------------------- + +SalYieldMutex::SalYieldMutex( SalInstanceData* pInstData ) +{ + mpInstData = pInstData; + mnCount = 0; + mnThreadId = 0; +} + +// ----------------------------------------------------------------------- + +void SAL_CALL SalYieldMutex::acquire() +{ + OMutex::acquire(); + mnCount++; + mnThreadId = GetCurrentThreadId(); +} + +// ----------------------------------------------------------------------- + +void SAL_CALL SalYieldMutex::release() +{ + DWORD nThreadId = GetCurrentThreadId(); + if ( mnThreadId != nThreadId ) + OMutex::release(); + else + { + // If we don't call these message, the Output from the + // Java clients doesn't come in the right order + GdiFlush(); + + SalData* pSalData = GetSalData(); + if ( pSalData->mnAppThreadId != nThreadId ) + { + if ( mnCount == 1 ) + { + mpInstData->mpSalWaitMutex->acquire(); + if ( mpInstData->mnYieldWaitCount ) + ImplPostMessage( 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 SAL_CALL SalYieldMutex::tryToAcquire() +{ + if( OMutex::tryToAcquire() ) + { + mnCount++; + mnThreadId = GetCurrentThreadId(); + return True; + } + else + return False; +} + +// ----------------------------------------------------------------------- + +ULONG SalYieldMutex::GetAcquireCount( ULONG nThreadId ) +{ + if ( nThreadId == mnThreadId ) + return mnCount; + else + return 0; +} + +// ----------------------------------------------------------------------- + +void ImplSalYieldMutexAcquireWithWait() +{ + SalInstance* 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. + DWORD 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->maInstData.mpSalYieldMutex->tryToAcquire() ) + bAcquire = TRUE; + else + { + pInst->maInstData.mpSalWaitMutex->acquire(); + if ( pInst->maInstData.mpSalYieldMutex->tryToAcquire() ) + { + bAcquire = TRUE; + pInst->maInstData.mpSalWaitMutex->release(); + } + else + { + pInst->maInstData.mnYieldWaitCount++; + pInst->maInstData.mpSalWaitMutex->release(); + MSG aTmpMsg; + ImplGetMessage( &aTmpMsg, pInst->maInstData.mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD ); + pInst->maInstData.mnYieldWaitCount--; + if ( pInst->maInstData.mnYieldWaitCount ) + ImplPostMessage( pInst->maInstData.mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 ); + } + } + } + while ( !bAcquire ); + } + else + pInst->maInstData.mpSalYieldMutex->acquire(); +} + +// ----------------------------------------------------------------------- + +BOOL ImplSalYieldMutexTryToAcquire() +{ + SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst ) + return pInst->maInstData.mpSalYieldMutex->tryToAcquire(); + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +void ImplSalYieldMutexAcquire() +{ + SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst ) + pInst->maInstData.mpSalYieldMutex->acquire(); +} + +// ----------------------------------------------------------------------- + +void ImplSalYieldMutexRelease() +{ + SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst ) + pInst->maInstData.mpSalYieldMutex->release(); +} + +// ----------------------------------------------------------------------- + +ULONG ImplSalReleaseYieldMutex() +{ + SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( !pInst ) + return 0; + + SalYieldMutex* pYieldMutex = pInst->maInstData.mpSalYieldMutex; + ULONG nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() ); + ULONG n = nCount; + while ( n ) + { + pYieldMutex->release(); + n--; + } + + return nCount; +} + +// ----------------------------------------------------------------------- + +void ImplSalAcquireYieldMutex( ULONG nCount ) +{ + SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( !pInst ) + return; + + SalYieldMutex* pYieldMutex = pInst->maInstData.mpSalYieldMutex; + while ( nCount ) + { + pYieldMutex->acquire(); + nCount--; + } +} + +// ----------------------------------------------------------------------- + +#ifdef DBG_UTIL + +void ImplDbgTestSolarMutex() +{ + SalData* pSalData = GetSalData(); + DWORD nCurThreadId = GetCurrentThreadId(); + if ( pSalData->mnAppThreadId != nCurThreadId ) + { + if ( pSalData->mpFirstInstance ) + { + SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->maInstData.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->maInstData.mpSalYieldMutex; + if ( pYieldMutex->mnThreadId != nCurThreadId ) + { + DBG_ERROR( "SolarMutex not locked in the main thread" ); + } + } + } +} + +#endif + +// ======================================================================= + +static void InitSalShlData() +{ + aSalShlData.mnVKAdd = LOWORD( VkKeyScan( '+' ) ); + aSalShlData.mnVKSubtract = LOWORD( VkKeyScan( '-' ) ); + aSalShlData.mnVKMultiply = LOWORD( VkKeyScan( '*' ) ); + aSalShlData.mnVKDivide = LOWORD( VkKeyScan( '/' ) ); + aSalShlData.mnVKPoint = LOWORD( VkKeyScan( '.' ) ); + aSalShlData.mnVKComma = LOWORD( VkKeyScan( ',' ) ); + aSalShlData.mnVKLess = LOWORD( VkKeyScan( '<' ) ); + aSalShlData.mnVKGreater = LOWORD( VkKeyScan( '>' ) ); + aSalShlData.mnVKEqual = LOWORD( VkKeyScan( '=' ) ); +} + +// ======================================================================= + +void InitSalData() +{ + SalData* pSalData = new SalData; + memset( pSalData, 0, sizeof( SalData ) ); + SetSalData( pSalData ); + CoInitialize(0); +} + +// ----------------------------------------------------------------------- + +void DeInitSalData() +{ + CoUninitialize(); + SalData* pSalData = GetSalData(); + delete pSalData; + SetSalData( NULL ); +} + +// ----------------------------------------------------------------------- + +void SetFilterCallback( void* pCallback, void* pInst ) +{ + SalData* pSalData = GetSalData(); + + pSalData->mpFirstInstance->maInstData.mpFilterCallback = pCallback; + pSalData->mpFirstInstance->maInstData.mpFilterInst = pInst; +} + +// ----------------------------------------------------------------------- + +SalInstance* CreateSalInstance() +{ + SalData* pSalData = GetSalData(); + + // determine the windows version + WORD nVer = (WORD)GetVersion(); + aSalShlData.mnVersion = (((WORD)LOBYTE(nVer)) * 100) + HIBYTE(nVer); + if ( aSalShlData.mnVersion >= W95_VERSION ) + aSalShlData.mbW40 = 1; + OSVERSIONINFO aVerInfo; + aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo ); + if ( GetVersionEx( &aVerInfo ) ) + { + if ( aVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) + aSalShlData.mbWNT = 1; + } + + pSalData->mnAppThreadId = GetCurrentThreadId(); + + // register frame class + if ( !pSalData->mhPrevInst ) + { + if ( aSalShlData.mbWNT ) + { + WNDCLASSEXW aWndClassEx; + aWndClassEx.cbSize = sizeof( aWndClassEx ); + aWndClassEx.style = CS_OWNDC; + aWndClassEx.lpfnWndProc = SalFrameWndProcW; + aWndClassEx.cbClsExtra = 0; + aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA; + aWndClassEx.hInstance = pSalData->mhInst; + aWndClassEx.hCursor = 0; + aWndClassEx.hbrBackground = 0; + aWndClassEx.lpszMenuName = 0; + aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEW; + ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm ); + if ( !RegisterClassExW( &aWndClassEx ) ) + return NULL; + aWndClassEx.style |= CS_SAVEBITS; + aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAME_SBW; + if ( !RegisterClassExW( &aWndClassEx ) ) + return NULL; + + aWndClassEx.style = 0; + aWndClassEx.lpfnWndProc = SalComWndProcW; + aWndClassEx.cbWndExtra = 0; + aWndClassEx.hIcon = 0; + aWndClassEx.hIconSm = 0; + aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEW; + if ( !RegisterClassExW( &aWndClassEx ) ) + return NULL; + } + else + { + WNDCLASSEXA aWndClassEx; + aWndClassEx.cbSize = sizeof( aWndClassEx ); + aWndClassEx.style = CS_OWNDC; + aWndClassEx.lpfnWndProc = SalFrameWndProcA; + aWndClassEx.cbClsExtra = 0; + aWndClassEx.cbWndExtra = SAL_FRAME_WNDEXTRA; + aWndClassEx.hInstance = pSalData->mhInst; + aWndClassEx.hCursor = 0; + aWndClassEx.hbrBackground = 0; + aWndClassEx.lpszMenuName = 0; + aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAMEA; + ImplLoadSalIcon( SAL_RESID_ICON_DEFAULT, aWndClassEx.hIcon, aWndClassEx.hIconSm ); + if ( !RegisterClassExA( &aWndClassEx ) ) + return NULL; + aWndClassEx.style |= CS_SAVEBITS; + aWndClassEx.lpszClassName = SAL_FRAME_CLASSNAME_SBA; + if ( !RegisterClassExA( &aWndClassEx ) ) + return NULL; + + aWndClassEx.style = 0; + aWndClassEx.lpfnWndProc = SalComWndProcA; + aWndClassEx.cbWndExtra = 0; + aWndClassEx.hIcon = 0; + aWndClassEx.hIconSm = 0; + aWndClassEx.lpszClassName = SAL_COM_CLASSNAMEA; + if ( !RegisterClassExA( &aWndClassEx ) ) + return NULL; + } + } + + HWND hComWnd; + if ( aSalShlData.mbWNT ) + { + hComWnd = CreateWindowExW( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEW, + L"", WS_POPUP, 0, 0, 0, 0, 0, 0, + pSalData->mhInst, NULL ); + } + else + { + hComWnd = CreateWindowExA( WS_EX_TOOLWINDOW, SAL_COM_CLASSNAMEA, + "", WS_POPUP, 0, 0, 0, 0, 0, 0, + pSalData->mhInst, NULL ); + } + if ( !hComWnd ) + return NULL; + + SalInstance* pInst = new SalInstance; + + // init shl data + InitSalShlData(); + + // init instance (only one instance in this version !!!) + pSalData->mpFirstInstance = pInst; + pInst->maInstData.mhInst = pSalData->mhInst; + pInst->maInstData.mhComWnd = hComWnd; + + // init static GDI Data + ImplInitSalGDI(); + + return pInst; +} + +// ----------------------------------------------------------------------- + +void DestroySalInstance( SalInstance* pInst ) +{ + SalData* pSalData = GetSalData(); + + // (only one instance in this version !!!) + + ImplFreeSalGDI(); + + // reset instance + if ( pSalData->mpFirstInstance == pInst ) + pSalData->mpFirstInstance = NULL; + + delete pInst; +} + +// ----------------------------------------------------------------------- + +SalInstance::SalInstance() +{ + maInstData.mhComWnd = 0; + maInstData.mpFilterCallback = NULL; + maInstData.mpFilterInst = NULL; + maInstData.mpSalYieldMutex = new SalYieldMutex( &maInstData ); + maInstData.mpSalWaitMutex = new NAMESPACE_VOS(OMutex); + maInstData.mnYieldWaitCount = 0; + maInstData.mpSalYieldMutex->acquire(); +} + +// ----------------------------------------------------------------------- + +SalInstance::~SalInstance() +{ + maInstData.mpSalYieldMutex->release(); + delete maInstData.mpSalYieldMutex; + delete maInstData.mpSalWaitMutex; + DestroyWindow( maInstData.mhComWnd ); +} + +// ----------------------------------------------------------------------- + +#ifdef _VOS_NO_NAMESPACE +IMutex* SalInstance::GetYieldMutex() +#else +vos::IMutex* SalInstance::GetYieldMutex() +#endif +{ + return maInstData.mpSalYieldMutex; +} + +// ----------------------------------------------------------------------- + +ULONG SalInstance::ReleaseYieldMutex() +{ + return ImplSalReleaseYieldMutex(); +} + +// ----------------------------------------------------------------------- + +void SalInstance::AcquireYieldMutex( ULONG nCount ) +{ + ImplSalAcquireYieldMutex( nCount ); +} + +// ----------------------------------------------------------------------- + +static void ImplSalDispatchMessage( MSG* pMsg ) +{ + SalData* pSalData = GetSalData(); + if ( pSalData->mpFirstObject ) + { + if ( ImplSalPreDispatchMsg( pMsg ) ) + return; + } + LRESULT lResult = ImplDispatchMessage( pMsg ); + if ( pSalData->mpFirstObject ) + ImplSalPostDispatchMsg( pMsg, lResult ); +} + +// ----------------------------------------------------------------------- + +void ImplSalYield( BOOL bWait ) +{ + MSG aMsg; + + if ( bWait ) + { + if ( ImplGetMessage( &aMsg, 0, 0, 0 ) ) + { + TranslateMessage( &aMsg ); + ImplSalDispatchMessage( &aMsg ); + } + } + else + { + if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &aMsg ); + ImplSalDispatchMessage( &aMsg ); + } + } +} + +// ----------------------------------------------------------------------- + +void SalInstance::Yield( BOOL bWait ) +{ + SalYieldMutex* pYieldMutex = maInstData.mpSalYieldMutex; + SalData* pSalData = GetSalData(); + DWORD nCurThreadId = GetCurrentThreadId(); + ULONG nCount = pYieldMutex->GetAcquireCount( nCurThreadId ); + ULONG n = nCount; + while ( n ) + { + pYieldMutex->release(); + n--; + } + if ( pSalData->mnAppThreadId != nCurThreadId ) + { + ImplSendMessage( maInstData.mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)0 ); + n = nCount; + while ( n ) + { + pYieldMutex->acquire(); + n--; + } + } + else + { + ImplSalYield( bWait ); + + n = nCount; + while ( n ) + { + ImplSalYieldMutexAcquireWithWait(); + n--; + } + } +} + +// ----------------------------------------------------------------------- + +LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ) +{ + LRESULT nRet = 0; + + switch ( nMsg ) + { + case SAL_MSG_PRINTABORTJOB: + ImplSalPrinterAbortJobAsync( (HDC)wParam ); + rDef = FALSE; + break; + case SAL_MSG_THREADYIELD: + ImplSalYield( (BOOL)wParam ); + rDef = FALSE; + break; + // 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: + { + SalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst && pInst->maInstData.mnYieldWaitCount ) + ImplPostMessage( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam ); + } + rDef = FALSE; + break; + case SAL_MSG_STARTTIMER: + ImplSalStartTimer( (ULONG) lParam, FALSE ); + rDef = FALSE; + break; + case SAL_MSG_CREATEFRAME: + nRet = (LRESULT)ImplSalCreateFrame( GetSalData()->mpFirstInstance, (HWND)lParam, (ULONG)wParam ); + rDef = FALSE; + break; + case SAL_MSG_DESTROYFRAME: + delete (SalFrame*)lParam; + rDef = FALSE; + break; + case SAL_MSG_CREATEOBJECT: + nRet = (LRESULT)ImplSalCreateObject( GetSalData()->mpFirstInstance, (SalFrame*)lParam ); + rDef = FALSE; + break; + case SAL_MSG_DESTROYOBJECT: + delete (SalObject*)lParam; + rDef = FALSE; + break; + case SAL_MSG_CREATESOUND: + nRet = ((SalSound*)lParam)->ImplCreate(); + rDef = FALSE; + break; + case SAL_MSG_DESTROYSOUND: + ((SalSound*)lParam)->ImplDestroy(); + rDef = FALSE; + break; + } + + return nRet; +} + +LRESULT CALLBACK SalComWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + { + if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) ) + nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam ); + } + return nRet; +} + +LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalComWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + { + if ( !ImplHandleGlobalMsg( hWnd, nMsg, wParam, lParam, nRet ) ) + nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam ); + } + return nRet; +} + +// ----------------------------------------------------------------------- + +BOOL SalInstance::AnyInput( USHORT nType ) +{ + MSG aMsg; + + if ( (nType & (INPUT_ANY)) == (INPUT_ANY) ) + { + // Any Input + if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) ) + return TRUE; + } + else + { + if ( nType & INPUT_MOUSE ) + { + // Test auf Mouseinput + if ( ImplPeekMessage( &aMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST, + PM_NOREMOVE | PM_NOYIELD ) ) + return TRUE; + } + + if ( nType & INPUT_KEYBOARD ) + { + // Test auf Keyinput + if ( ImplPeekMessage( &aMsg, 0, WM_KEYDOWN, WM_KEYDOWN, + PM_NOREMOVE | PM_NOYIELD ) ) + { + if ( (aMsg.wParam == VK_SHIFT) || + (aMsg.wParam == VK_CONTROL) || + (aMsg.wParam == VK_MENU) ) + return FALSE; + else + return TRUE; + } + } + + if ( nType & INPUT_PAINT ) + { + // Test auf Paintinput + if ( ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT, + PM_NOREMOVE | PM_NOYIELD ) ) + return TRUE; + } + + if ( nType & INPUT_TIMER ) + { + // Test auf Timerinput + if ( ImplPeekMessage( &aMsg, 0, WM_TIMER, WM_TIMER, + PM_NOREMOVE | PM_NOYIELD ) ) + return TRUE; + } + + if ( nType & INPUT_OTHER ) + { + // Test auf sonstigen Input + if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD ) ) + return TRUE; + } + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +void SalTimer::Start( ULONG nMS ) +{ + // Um auf Main-Thread umzuschalten + SalData* pSalData = GetSalData(); + if ( pSalData->mpFirstInstance ) + { + if ( pSalData->mnAppThreadId != GetCurrentThreadId() ) + ImplPostMessage( pSalData->mpFirstInstance->maInstData.mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS ); + else + ImplSendMessage( pSalData->mpFirstInstance->maInstData.mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS ); + } + else + ImplSalStartTimer( nMS, FALSE ); +} + +// ----------------------------------------------------------------------- + +SalFrame* SalInstance::CreateChildFrame( SystemParentData* pSystemParentData, ULONG nSalFrameStyle ) +{ + // Um auf Main-Thread umzuschalten + return (SalFrame*)ImplSendMessage( maInstData.mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)pSystemParentData->hWnd ); +} + +// ----------------------------------------------------------------------- + +SalFrame* SalInstance::CreateFrame( SalFrame* pParent, ULONG nSalFrameStyle ) +{ + // Um auf Main-Thread umzuschalten + HWND hWndParent; + if ( pParent ) + hWndParent = pParent->maFrameData.mhWnd; + else + hWndParent = 0; + return (SalFrame*)ImplSendMessage( maInstData.mhComWnd, SAL_MSG_CREATEFRAME, nSalFrameStyle, (LPARAM)hWndParent ); +} + +// ----------------------------------------------------------------------- + +void SalInstance::DestroyFrame( SalFrame* pFrame ) +{ + ImplSendMessage( maInstData.mhComWnd, SAL_MSG_DESTROYFRAME, 0, (LPARAM)pFrame ); +} + +// ----------------------------------------------------------------------- + +SalObject* SalInstance::CreateObject( SalFrame* pParent ) +{ + // Um auf Main-Thread umzuschalten + return (SalObject*)ImplSendMessage( maInstData.mhComWnd, SAL_MSG_CREATEOBJECT, 0, (LPARAM)pParent ); +} + +// ----------------------------------------------------------------------- + +void SalInstance::DestroyObject( SalObject* pObject ) +{ + ImplSendMessage( maInstData.mhComWnd, SAL_MSG_DESTROYOBJECT, 0, (LPARAM)pObject ); +} diff --git a/vcl/win/source/app/salshl.cxx b/vcl/win/source/app/salshl.cxx new file mode 100644 index 000000000000..3c026c053906 --- /dev/null +++ b/vcl/win/source/app/salshl.cxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * $RCSfile: salshl.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALSHL_CXX + +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif + +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif + +// ======================================================================= + +SalShlData aSalShlData; + +// ======================================================================= + +#ifdef WIN + +extern "C" +{ + +int CALLBACK LibMain( HINSTANCE hInst, WORD, WORD nHeap, LPSTR ) +{ + if ( nHeap ) + UnlockData( 0 ); + + aSalShlData.mhInst = hInst; + + return 1; +} + +// ----------------------------------------------------------------------- + +int CALLBACK WEP( int ) +{ + return 1; +} + +} + +#endif + +// ======================================================================= + +#ifdef WNT + +extern "C" +{ + +#ifdef ICC +int _CRT_init(void); +#else +WIN_BOOL WINAPI _CRT_INIT( HINSTANCE hInst, DWORD nReason, LPVOID pReserved ); +#endif + +WIN_BOOL WINAPI LibMain( HINSTANCE hInst, DWORD nReason, LPVOID pReserved ) +{ + // Unsere DLL-Initialisierung + if ( nReason == DLL_PROCESS_ATTACH ) + aSalShlData.mhInst = hInst; + +#if !defined ( __BORLANDC__ ) +#ifdef ICC + if ( _CRT_init() == -1 ) +#else + if ( !_CRT_INIT( hInst, nReason, pReserved ) ) +#endif + return 0; +#endif + + return 1; +} + +} + +#endif + +// ======================================================================= + +HCURSOR ImplLoadSalCursor( int nId ) +{ + DBG_ASSERT( aSalShlData.mhInst, "no DLL instance handle" ); + + HCURSOR hCursor = LoadCursor( aSalShlData.mhInst, MAKEINTRESOURCE( nId ) ); + + DBG_ASSERT( hCursor, "cursor not found in sal resource" ); + + return hCursor; +} + +// ----------------------------------------------------------------------- + +HBITMAP ImplLoadSalBitmap( int nId ) +{ + DBG_ASSERT( aSalShlData.mhInst, "no DLL instance handle" ); + + HBITMAP hBitmap = LoadBitmap( aSalShlData.mhInst, MAKEINTRESOURCE( nId ) ); + + DBG_ASSERT( hBitmap, "bitmap not found in sal resource" ); + + return hBitmap; +} + +// ----------------------------------------------------------------------- + +BOOL ImplLoadSalIcon( int nId, HICON& rIcon, HICON& rSmallIcon ) +{ + DBG_ASSERT( aSalShlData.mhInst, "no DLL instance handle" ); + + // Try at first to load the icons from the application exe file + SalData* pSalData = GetSalData(); + rIcon = LoadIcon( pSalData->mhInst, MAKEINTRESOURCE( nId ) ); + if ( !rIcon ) + { + // If the application don't provide these icons, then we try + // to load the icon from the VCL resource + rIcon = LoadIcon( aSalShlData.mhInst, MAKEINTRESOURCE( nId ) ); + if ( rIcon ) + { + rSmallIcon = (HICON)LoadImage( aSalShlData.mhInst, MAKEINTRESOURCE( nId ), + IMAGE_ICON, 16, 16, 0 ); + } + else + rSmallIcon = 0; + } + else + { + rSmallIcon = (HICON)LoadImage( pSalData->mhInst, MAKEINTRESOURCE( nId ), + IMAGE_ICON, 16, 16, 0 ); + } + + return (rSmallIcon != 0); +} diff --git a/vcl/win/source/app/saltimer.cxx b/vcl/win/source/app/saltimer.cxx new file mode 100644 index 000000000000..b051c72110bf --- /dev/null +++ b/vcl/win/source/app/saltimer.cxx @@ -0,0 +1,152 @@ +/************************************************************************* + * + * $RCSfile: saltimer.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALTIMER_CXX + +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALTIMER_HXX +#include <saltimer.hxx> +#endif + +// ======================================================================= + +// Maximale Periode +#define MAX_SYSPERIOD 65533 + +// ======================================================================= + +void ImplSalStartTimer( ULONG nMS, BOOL bMutex ) +{ + SalData* pSalData = GetSalData(); + + // 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 ) + KillTimer( 0, pSalData->mnTimerId ); + + // Make a new timer with new period + pSalData->mnTimerId = SetTimer( 0, 0, (UINT)nMS, SalTimerProc ); +} + +// ----------------------------------------------------------------------- + +void SalTimer::Stop() +{ + SalData* pSalData = GetSalData(); + + // If we have a timer, than + if ( pSalData->mnTimerId ) + { + KillTimer( 0, pSalData->mnTimerId ); + pSalData->mnTimerId = 0; + } +} + +// ----------------------------------------------------------------------- + +void SalTimer::SetCallback( SALTIMERPROC pProc ) +{ + SalData* pSalData = GetSalData(); + pSalData->mpTimerProc = pProc; +} + +// ----------------------------------------------------------------------- + +void CALLBACK SalTimerProc( HWND, UINT, UINT, DWORD ) +{ + SalData* pSalData = GetSalData(); + + // Test for MouseLeave + SalTestMouseLeave(); + + if ( pSalData->mpTimerProc ) + { + // Try to aquire the mutex. If we don't get the mutex then we + // try this a short time later again. + if ( ImplSalYieldMutexTryToAcquire() ) + { + pSalData->mpTimerProc(); + 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/win/source/gdi/MAKEFILE.MK b/vcl/win/source/gdi/MAKEFILE.MK new file mode 100644 index 000000000000..c63a3cdd19f4 --- /dev/null +++ b/vcl/win/source/gdi/MAKEFILE.MK @@ -0,0 +1,52 @@ +#************************************************************************* +#* +#* $Workfile: makefile. $ +#* +#* Ersterstellung TH 01.04.97 +#* Letzte Aenderung $Author: hr $ $Date: 2000-09-18 17:05:49 $ +#* $Revision: 1.1.1.1 $ +#* +#* $Logfile: T:/sv2/win/source/gdi/makefile.__v $ +#* +#* Copyright (c) 1990 - 1997, STAR DIVISION +#* +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=salgdi + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +SLOFILES= $(SLO)$/salgdi.obj \ + $(SLO)$/salgdi2.obj \ + $(SLO)$/salgdi3.obj \ + $(SLO)$/salvd.obj \ + $(SLO)$/salprn.obj \ + $(SLO)$/salbmp.obj \ + $(SLO)$/salogl.obj + +.IF "$(GUI)" == "WNT" +SLOFILES+=$(SLO)$/wntgdi.obj +.ENDIF + +.IF "$(UPDATER)"=="YES" +OBJFILES= $(OBJ)$/salgdi.obj \ + $(OBJ)$/salgdi2.obj \ + $(OBJ)$/salgdi3.obj \ + $(OBJ)$/salvd.obj \ + $(OBJ)$/salprn.obj \ + $(OBJ)$/salbmp.obj \ + $(OBJ)$/salogl.obj +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/win/source/gdi/salbmp.cxx b/vcl/win/source/gdi/salbmp.cxx new file mode 100644 index 000000000000..ec0f9914b5ee --- /dev/null +++ b/vcl/win/source/gdi/salbmp.cxx @@ -0,0 +1,668 @@ +/************************************************************************* + * + * $RCSfile: salbmp.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALBMP_CXX + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALBTYPE_HXX +#include <salbtype.hxx> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALBMP_HXX +#include <salbmp.hxx> +#endif +#include <string.h> + +#ifdef WIN +#define BI_BITFIELDS 3 +#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 ) ); +} + +// ------------- +// - SalBitmap - +// ------------- + +SalBitmap::SalBitmap() : + mhDIB ( 0 ), + mhDDB ( 0 ), + mnBitCount ( 0 ) +{ +} + +// ------------------------------------------------------------------ + +SalBitmap::~SalBitmap() +{ + Destroy(); +} + +// ------------------------------------------------------------------ + +BOOL SalBitmap::Create( HANDLE hBitmap, BOOL bDIB, BOOL bCopyHandle ) +{ + BOOL bRet = TRUE; + + if( bDIB ) + mhDIB = (HGLOBAL) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, TRUE ) : hBitmap ); + else + mhDDB = (HBITMAP) ( bCopyHandle ? ImplCopyDIBOrDDB( hBitmap, FALSE ) : hBitmap ); + + if( mhDIB ) + { + PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) GlobalLock( mhDIB ); + + maSize = Size( pBIH->biWidth, pBIH->biHeight ); + mnBitCount = pBIH->biBitCount; + + if( mnBitCount ) + mnBitCount = ( mnBitCount <= 1 ) ? 1 : ( mnBitCount <= 4 ) ? 4 : ( mnBitCount <= 8 ) ? 8 : 24; + + GlobalUnlock( mhDIB ); + } + else if( mhDDB ) + { + BITMAP aDDBInfo; + + if( WIN_GetObject( mhDDB, sizeof( BITMAP ), &aDDBInfo ) ) + { + maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); + mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; + + if( mnBitCount ) + { + mnBitCount = ( mnBitCount <= 1 ) ? 1 : + ( mnBitCount <= 4 ) ? 4 : + ( mnBitCount <= 8 ) ? 8 : 24; + } + } + else + { + mhDDB = 0; + bRet = FALSE; + } + } + else + bRet = FALSE; + + return bRet; +} + +// ------------------------------------------------------------------ + +BOOL SalBitmap::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 SalBitmap::Create( const SalBitmap& rSalBitmap ) +{ + BOOL bRet = FALSE; + + if ( rSalBitmap.mhDIB || rSalBitmap.mhDDB ) + { + HANDLE hNewHdl = ImplCopyDIBOrDDB( rSalBitmap.mhDIB ? rSalBitmap.mhDIB : rSalBitmap.mhDDB, + rSalBitmap.mhDIB != 0 ); + + if ( hNewHdl ) + { + if( rSalBitmap.mhDIB ) + mhDIB = (HGLOBAL) hNewHdl; + else if( rSalBitmap.mhDDB ) + mhDDB = (HBITMAP) hNewHdl; + + maSize = rSalBitmap.maSize; + mnBitCount = rSalBitmap.mnBitCount; + + bRet = TRUE; + } + } + + return bRet; +} + +// ------------------------------------------------------------------ + +BOOL SalBitmap::Create( const SalBitmap& rSalBmp, SalGraphics* pGraphics ) +{ + BOOL bRet = FALSE; + + if( rSalBmp.mhDIB ) + { + PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( rSalBmp.mhDIB ); + PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; + HDC hDC = pGraphics->maGraphicsData.mhDC; + HBITMAP hNewDDB; + BITMAP aDDBInfo; + PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + + ImplGetDIBColorCount( rSalBmp.mhDIB ) * sizeof( RGBQUAD ); + + if( pBIH->biBitCount == 1 ) + { + hNewDDB = CreateBitmap( pBIH->biWidth, pBIH->biHeight, 1, 1, NULL ); + + if( hNewDDB ) + SetDIBits( hDC, hNewDDB, 0, pBIH->biHeight, pBits, pBI, DIB_RGB_COLORS ); + } + else + hNewDDB = CreateDIBitmap( hDC, (PBITMAPINFOHEADER) pBI, CBM_INIT, pBits, pBI, DIB_RGB_COLORS ); + + GlobalUnlock( rSalBmp.mhDIB ); + + if( hNewDDB && WIN_GetObject( hNewDDB, sizeof( BITMAP ), &aDDBInfo ) ) + { + mhDDB = hNewDDB; + maSize = Size( aDDBInfo.bmWidth, aDDBInfo.bmHeight ); + mnBitCount = aDDBInfo.bmPlanes * aDDBInfo.bmBitsPixel; + + if( mnBitCount ) + { + mnBitCount = ( mnBitCount <= 1 ) ? 1 : + ( mnBitCount <= 4 ) ? 4 : + ( mnBitCount <= 8 ) ? 8 : 24; + } + + bRet = TRUE; + } + else if( hNewDDB ) + DeleteObject( hNewDDB ); + } + + return bRet; +} + +// ------------------------------------------------------------------ + +BOOL SalBitmap::Create( const SalBitmap& rSalBmp, USHORT nNewBitCount ) +{ + BOOL bRet = FALSE; + + if( rSalBmp.mhDDB ) + { + mhDIB = ImplCreateDIB( rSalBmp.maSize, nNewBitCount, BitmapPalette() ); + + if( mhDIB ) + { + PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); + const int nLines = (int) rSalBmp.maSize.Height(); + HDC hDC = GetDC( 0 ); + PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + + ImplGetDIBColorCount( mhDIB ) * sizeof( RGBQUAD ); + SalData* pSalData = GetSalData(); + HPALETTE hOldPal = 0; + + if ( pSalData->mhDitherPal ) + { + hOldPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); + RealizePalette( hDC ); + } + + if( GetDIBits( hDC, rSalBmp.mhDDB, 0, nLines, pBits, pBI, DIB_RGB_COLORS ) == nLines ) + { + GlobalUnlock( mhDIB ); + maSize = rSalBmp.maSize; + mnBitCount = nNewBitCount; + bRet = TRUE; + } + else + { + GlobalUnlock( mhDIB ); + GlobalFree( mhDIB ); + mhDIB = 0; + } + + if( hOldPal ) + SelectPalette( hDC, hOldPal, TRUE ); + + ReleaseDC( 0, hDC ); + } + } + + return bRet; +} + +// ------------------------------------------------------------------ + +void SalBitmap::Destroy() +{ + if( mhDIB ) + GlobalFree( mhDIB ); + else if( mhDDB ) + DeleteObject( mhDDB ); + + maSize = Size(); + mnBitCount = 0; +} + +// ------------------------------------------------------------------ + +USHORT SalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB ) +{ + USHORT nColors = 0; + + if( hDIB ) + { + PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB ); + PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; + + if ( pBIH->biSize != sizeof( BITMAPCOREHEADER ) ) + { + if( pBIH->biBitCount <= 8 ) + { + if ( pBIH->biClrUsed ) + nColors = (USHORT) pBIH->biClrUsed; + else + nColors = 1 << pBIH->biBitCount; + } + } + else if( ( (PBITMAPCOREHEADER) pBI )->bcBitCount <= 8 ) + nColors = 1 << ( (PBITMAPCOREHEADER) pBI )->bcBitCount; + + GlobalUnlock( hDIB ); + } + + return nColors; +} + +// ------------------------------------------------------------------ + +HGLOBAL SalBitmap::ImplCreateDIB( const Size& rSize, USHORT nBits, const BitmapPalette& rPal ) +{ + DBG_ASSERT( nBits == 1 || nBits == 4 || nBits == 8 || nBits == 24, "Unsupported BitCount!" ); + + HGLOBAL 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 = GlobalAlloc( GHND, sizeof( BITMAPINFOHEADER ) + nColors * sizeof( RGBQUAD ) + nImageSize ); + + if( hDIB ) + { + PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDIB ); + PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; + + pBIH->biSize = sizeof( BITMAPINFOHEADER ); + pBIH->biWidth = rSize.Width(); + pBIH->biHeight = rSize.Height(); + pBIH->biPlanes = 1; + pBIH->biBitCount = nBits; + pBIH->biCompression = BI_RGB; + pBIH->biSizeImage = nImageSize; + pBIH->biXPelsPerMeter = 0; + pBIH->biYPelsPerMeter = 0; + pBIH->biClrUsed = 0; + pBIH->biClrImportant = 0; + + if ( nColors ) + { + const USHORT nMinCount = Min( nColors, rPal.GetEntryCount() ); + + if( nMinCount ) + HMEMCPY( pBI->bmiColors, rPal.ImplGetColorBuffer(), nMinCount * sizeof( RGBQUAD ) ); + } + + GlobalUnlock( hDIB ); + } + } + + return hDIB; +} + +// ------------------------------------------------------------------ + +HANDLE SalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl, BOOL bDIB ) +{ + HANDLE hCopy = 0; + + if ( bDIB && hHdl ) + { + const ULONG nSize = GlobalSize( hHdl ); + + if ( hCopy = GlobalAlloc( GHND, nSize ) ) + { + HMEMCPY( (LPSTR) GlobalLock( hCopy ), (LPSTR) GlobalLock( hHdl ), nSize ); + + GlobalUnlock( hCopy ); + GlobalUnlock( hHdl ); + } + } + else if ( hHdl ) + { + BITMAP aBmp; + + // Source-Bitmap nach Groesse befragen + WIN_GetObject( hHdl, sizeof( BITMAP ), (LPSTR) &aBmp ); + + // Destination-Bitmap erzeugen + if ( hCopy = CreateBitmapIndirect( &aBmp ) ) + { + HDC hBmpDC = CreateCompatibleDC( 0 ); + HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hHdl ); + HDC hCopyDC = CreateCompatibleDC( hBmpDC ); + HBITMAP hCopyOld = (HBITMAP) SelectObject( hCopyDC, hCopy ); + + BitBlt( hCopyDC, 0, 0, aBmp.bmWidth, aBmp.bmHeight, hBmpDC, 0, 0, SRCCOPY ); + + SelectObject( hCopyDC, hCopyOld ); + DeleteDC( hCopyDC ); + + SelectObject( hBmpDC, hBmpOld ); + DeleteDC( hBmpDC ); + } + } + + return hCopy; +} + +// ------------------------------------------------------------------ + +BitmapBuffer* SalBitmap::AcquireBuffer( BOOL bReadOnly ) +{ + BitmapBuffer* pBuffer = NULL; + + if( mhDIB ) + { + PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); + PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; + + if( ( pBIH->biCompression == BI_RLE4 ) || ( pBIH->biCompression == BI_RLE8 ) ) + { + Size aSizePix( pBIH->biWidth, pBIH->biHeight ); + HGLOBAL hNewDIB = ImplCreateDIB( aSizePix, pBIH->biBitCount, BitmapPalette() ); + + if( hNewDIB ) + { + PBITMAPINFO pNewBI = (PBITMAPINFO) GlobalLock( hNewDIB ); + PBITMAPINFOHEADER pNewBIH = (PBITMAPINFOHEADER) pNewBI; + const USHORT nColorCount = ImplGetDIBColorCount( hNewDIB ); + const ULONG nOffset = *(DWORD*) pBI + nColorCount * sizeof( RGBQUAD ); + BYTE* pOldBits = (PBYTE) pBI + nOffset; + BYTE* pNewBits = (PBYTE) pNewBI + nOffset; + + HMEMCPY( pNewBI, pBI, nOffset ); + pNewBIH->biCompression = 0; + ImplDecodeRLEBuffer( pOldBits, pNewBits, aSizePix, pBIH->biCompression == BI_RLE4 ); + + GlobalUnlock( mhDIB ); + GlobalFree( mhDIB ); + mhDIB = hNewDIB; + pBI = pNewBI; + pBIH = pNewBIH; + } + } + + if( pBIH->biPlanes == 1 ) + { + pBuffer = new BitmapBuffer; + + pBuffer->mnFormat = BMP_FORMAT_BOTTOM_UP | + ( pBIH->biBitCount == 1 ? BMP_FORMAT_1BIT_MSB_PAL : + pBIH->biBitCount == 4 ? BMP_FORMAT_4BIT_MSN_PAL : + pBIH->biBitCount == 8 ? BMP_FORMAT_8BIT_PAL : + pBIH->biBitCount == 16 ? BMP_FORMAT_16BIT_TC_MASK : + pBIH->biBitCount == 24 ? BMP_FORMAT_24BIT_TC_BGR : + pBIH->biBitCount == 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->biBitCount ); + pBuffer->mnBitCount = (USHORT) pBIH->biBitCount; + + if( pBuffer->mnBitCount <= 8 ) + { + const USHORT nPalCount = ImplGetDIBColorCount( mhDIB ); + + pBuffer->maPalette.SetEntryCount( nPalCount ); + HMEMCPY( pBuffer->maPalette.ImplGetColorBuffer(), pBI->bmiColors, nPalCount * sizeof( RGBQUAD ) ); + pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nPalCount * sizeof( RGBQUAD ); + } + else if( ( pBIH->biBitCount == 16 ) || ( pBIH->biBitCount == 32 ) ) + { + ULONG nOffset = 0UL; + + if( pBIH->biCompression == BI_BITFIELDS ) + { + nOffset = 3 * sizeof( RGBQUAD ); + pBuffer->maColorMask = ColorMask( *(UINT32*) &pBI->bmiColors[ 0 ], + *(UINT32*) &pBI->bmiColors[ 1 ], + *(UINT32*) &pBI->bmiColors[ 2 ] ); + } + else if( pBIH->biCompression == 16 ) + pBuffer->maColorMask = ColorMask( 0x00007c00UL, 0x000003e0UL, 0x0000001fUL ); + else + pBuffer->maColorMask = ColorMask( 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL ); + + pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI + nOffset; + } + else + pBuffer->mpBits = (PBYTE) pBI + *(DWORD*) pBI; + } + else + { + GlobalUnlock( mhDIB ); + delete pBuffer; + pBuffer = NULL; + } + } + else + GlobalUnlock( mhDIB ); + } + + return pBuffer; +} + +// ------------------------------------------------------------------ + +void SalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, BOOL bReadOnly ) +{ + if( pBuffer ) + { + if( mhDIB ) + { + if( !bReadOnly && !!pBuffer->maPalette ) + { + PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( mhDIB ); + const USHORT nCount = pBuffer->maPalette.GetEntryCount(); + + HMEMCPY( pBI->bmiColors, pBuffer->maPalette.ImplGetColorBuffer(), nCount * sizeof( RGBQUAD ) ); + GlobalUnlock( mhDIB ); + } + + GlobalUnlock( mhDIB ); + } + + delete pBuffer; + } +} + +// ------------------------------------------------------------------ + +void SalBitmap::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 + { + HMEMCPY( &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 ) ); + } +} diff --git a/vcl/win/source/gdi/salgdi.cxx b/vcl/win/source/gdi/salgdi.cxx new file mode 100644 index 000000000000..f8f5892add4e --- /dev/null +++ b/vcl/win/source/gdi/salgdi.cxx @@ -0,0 +1,1449 @@ +/************************************************************************* + * + * $RCSfile: salgdi.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <stdio.h> +#include <string.h> + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif +#define _SV_SALGDI_CXX + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif + +// ======================================================================= + +#define DITHER_PAL_DELTA 51 +#define DITHER_PAL_STEPS 6 +#define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS) +#define DITHER_MAX_SYSCOLOR 16 +#define DITHER_EXTRA_COLORS 1 +#define DMAP( _def_nVal, _def_nThres ) ((pDitherDiff[_def_nVal]>(_def_nThres))?pDitherHigh[_def_nVal]:pDitherLow[_def_nVal]) + +// ======================================================================= + +struct SysColorEntry +{ + DWORD nRGB; + SysColorEntry* pNext; +}; + +// ======================================================================= + +static SysColorEntry* pFirstSysColor = NULL; +static SysColorEntry* pActSysColor = NULL; + +// ----------------------------------------------------------------------------- + +// Blue7 +static PALETTEENTRY aImplExtraColor1 = +{ + 0, 184, 255, 0 +}; + +// ----------------------------------------------------------------------------- + +static PALETTEENTRY aImplSalSysPalEntryAry[ DITHER_MAX_SYSCOLOR ] = +{ +{ 0, 0, 0, 0 }, +{ 0, 0, 0x80, 0 }, +{ 0, 0x80, 0, 0 }, +{ 0, 0x80, 0x80, 0 }, +{ 0x80, 0, 0, 0 }, +{ 0x80, 0, 0x80, 0 }, +{ 0x80, 0x80, 0, 0 }, +{ 0x80, 0x80, 0x80, 0 }, +{ 0xC0, 0xC0, 0xC0, 0 }, +{ 0, 0, 0xFF, 0 }, +{ 0, 0xFF, 0, 0 }, +{ 0, 0xFF, 0xFF, 0 }, +{ 0xFF, 0, 0, 0 }, +{ 0xFF, 0, 0xFF, 0 }, +{ 0xFF, 0xFF, 0, 0 }, +{ 0xFF, 0xFF, 0xFF, 0 } +}; + +// ----------------------------------------------------------------------------- + +static BYTE aOrdDither8Bit[8][8] = +{ + 0, 38, 9, 48, 2, 40, 12, 50, + 25, 12, 35, 22, 28, 15, 37, 24, + 6, 44, 3, 41, 8, 47, 5, 44, + 32, 19, 28, 16, 34, 21, 31, 18, + 1, 40, 11, 49, 0, 39, 10, 48, + 27, 14, 36, 24, 26, 13, 36, 23, + 8, 46, 4, 43, 7, 45, 4, 42, + 33, 20, 30, 17, 32, 20, 29, 16 +}; + +// ----------------------------------------------------------------------------- + +static BYTE aOrdDither16Bit[8][8] = +{ + 0, 6, 1, 7, 0, 6, 1, 7, + 4, 2, 5, 3, 4, 2, 5, 3, + 1, 7, 0, 6, 1, 7, 0, 6, + 5, 3, 4, 2, 5, 3, 4, 2, + 0, 6, 1, 7, 0, 6, 1, 7, + 4, 2, 5, 3, 4, 2, 5, 3, + 1, 7, 0, 6, 1, 7, 0, 6, + 5, 3, 4, 2, 5, 3, 4, 2 +}; + +// ======================================================================= + +// Pens muessen wir mit 1 Pixel-Breite erzeugen, da ansonsten die S3-Karte +// viele Paintprobleme hat, wenn Polygone/PolyLines gezeichnet werden und +// eine komplexe ClipRegion gesetzt ist +#define GSL_PEN_WIDTH 1 + +// ======================================================================= + +#define SAL_POLYPOLYCOUNT_STACKBUF 8 +#define SAL_POLYPOLYPOINTS_STACKBUF 64 + +// ======================================================================= + +void ImplInitSalGDI() +{ + SalData* pSalData = GetSalData(); + + // init stock brushes + pSalData->maStockPenColorAry[0] = PALETTERGB( 0, 0, 0 ); + pSalData->maStockPenColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF ); + pSalData->maStockPenColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 ); + pSalData->maStockPenColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 ); + pSalData->mhStockPenAry[0] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[0] ); + pSalData->mhStockPenAry[1] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[1] ); + pSalData->mhStockPenAry[2] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[2] ); + pSalData->mhStockPenAry[3] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[3] ); + pSalData->mnStockPenCount = 4; + + pSalData->maStockBrushColorAry[0] = PALETTERGB( 0, 0, 0 ); + pSalData->maStockBrushColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF ); + pSalData->maStockBrushColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 ); + pSalData->maStockBrushColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 ); + pSalData->mhStockBrushAry[0] = CreateSolidBrush( pSalData->maStockBrushColorAry[0] ); + pSalData->mhStockBrushAry[1] = CreateSolidBrush( pSalData->maStockBrushColorAry[1] ); + pSalData->mhStockBrushAry[2] = CreateSolidBrush( pSalData->maStockBrushColorAry[2] ); + pSalData->mhStockBrushAry[3] = CreateSolidBrush( pSalData->maStockBrushColorAry[3] ); + pSalData->mnStockBrushCount = 4; + + // DC-Cache aufbauen + pSalData->mpHDCCache = new HDCCache[ CACHESIZE_HDC ]; + memset( pSalData->mpHDCCache, 0, CACHESIZE_HDC * sizeof( HDCCache ) ); + + // Nur bei 256 Farben Displays, die Paletten unterstuetzen + HDC hDC = GetDC( 0 ); + int nBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); + int nPlanes = GetDeviceCaps( hDC, PLANES ); + int nRasterCaps = GetDeviceCaps( hDC, RASTERCAPS ); + int nBitCount = nBitsPixel * nPlanes; + + if ( (nBitCount > 8) && (nBitCount < 24) ) + { + // test, if we have to dither + HDC hMemDC = ::CreateCompatibleDC( hDC ); + HBITMAP hMemBmp = ::CreateCompatibleBitmap( hDC, 8, 8 ); + HBITMAP hBmpOld = (HBITMAP) ::SelectObject( hMemDC, hMemBmp ); + HBRUSH hMemBrush = ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) ); + HBRUSH hBrushOld = (HBRUSH) ::SelectObject( hMemDC, hMemBrush ); + BOOL bDither16 = TRUE; + + ::PatBlt( hMemDC, 0, 0, 8, 8, PATCOPY ); + const COLORREF aCol( ::GetPixel( hMemDC, 0, 0 ) ); + + for( int nY = 0; ( nY < 8 ) && bDither16; nY++ ) + for( int nX = 0; ( nX < 8 ) && bDither16; nX++ ) + if( ::GetPixel( hMemDC, nX, nY ) != aCol ) + bDither16 = FALSE; + + ::SelectObject( hMemDC, hBrushOld ), ::DeleteObject( hMemBrush ); + ::SelectObject( hMemDC, hBmpOld ), ::DeleteObject( hMemBmp ); + ::DeleteDC( hMemDC ); + + if( bDither16 ) + { + // create DIBPattern for 16Bit dithering + long n; + + pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, sizeof( BITMAPINFOHEADER ) + 192 ); + pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB ); + pSalData->mpDitherDiff = new long[ 256 ]; + pSalData->mpDitherLow = new BYTE[ 256 ]; + pSalData->mpDitherHigh = new BYTE[ 256 ]; + pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ); + memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) ); + + BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB; + + pBIH->biSize = sizeof( BITMAPINFOHEADER ); + pBIH->biWidth = 8; + pBIH->biHeight = 8; + pBIH->biPlanes = 1; + pBIH->biBitCount = 24; + + for( n = 0; n < 256L; n++ ) + pSalData->mpDitherDiff[ n ] = n - ( n & 248L ); + + for( n = 0; n < 256L; n++ ) + pSalData->mpDitherLow[ n ] = (BYTE) ( n & 248 ); + + for( n = 0; n < 256L; n++ ) + pSalData->mpDitherHigh[ n ] = (BYTE) Min( pSalData->mpDitherLow[ n ] + 8L, 255L ); + } + } + else if ( (nRasterCaps & RC_PALETTE) && (nBitCount == 8) ) + { + BYTE nRed, nGreen, nBlue; + BYTE nR, nG, nB; + PALETTEENTRY* pPalEntry; + LOGPALETTE* pLogPal; + const USHORT nDitherPalCount = DITHER_PAL_COUNT; + ULONG nTotalCount = DITHER_MAX_SYSCOLOR + nDitherPalCount + DITHER_EXTRA_COLORS; + + // create logical palette + pLogPal = (LOGPALETTE*) new char[ sizeof( LOGPALETTE ) + ( nTotalCount * sizeof( PALETTEENTRY ) ) ]; + pLogPal->palVersion = 0x0300; + pLogPal->palNumEntries = (USHORT) nTotalCount; + pPalEntry = pLogPal->palPalEntry; + + // Standard colors + memcpy( pPalEntry, aImplSalSysPalEntryAry, DITHER_MAX_SYSCOLOR * sizeof( PALETTEENTRY ) ); + pPalEntry += DITHER_MAX_SYSCOLOR; + + // own palette (6/6/6) + for( nB=0, nBlue=0; nB < DITHER_PAL_STEPS; nB++, nBlue += DITHER_PAL_DELTA ) + { + for( nG=0, nGreen=0; nG < DITHER_PAL_STEPS; nG++, nGreen += DITHER_PAL_DELTA ) + { + for( nR=0, nRed=0; nR < DITHER_PAL_STEPS; nR++, nRed += DITHER_PAL_DELTA ) + { + pPalEntry->peRed = nRed; + pPalEntry->peGreen = nGreen; + pPalEntry->peBlue = nBlue; + pPalEntry->peFlags = 0; + pPalEntry++; + } + } + } + + // insert special 'Blue' as standard drawing color + *pPalEntry++ = aImplExtraColor1; + + // create palette + pSalData->mhDitherPal = CreatePalette( pLogPal ); + delete[] (char*) pLogPal; + + if( pSalData->mhDitherPal ) + { + // create DIBPattern for 8Bit dithering + long nSize = sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ) + 64; + long n; + + pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, nSize ); + pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB ); + pSalData->mpDitherDiff = new long[ 256 ]; + pSalData->mpDitherLow = new BYTE[ 256 ]; + pSalData->mpDitherHigh = new BYTE[ 256 ]; + pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ); + memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) ); + + BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB; + short* pColors = (short*) ( pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) ); + + pBIH->biSize = sizeof( BITMAPINFOHEADER ); + pBIH->biWidth = 8; + pBIH->biHeight = 8; + pBIH->biPlanes = 1; + pBIH->biBitCount = 8; + + for( n = 0; n < nDitherPalCount; n++ ) + pColors[ n ] = (short)( n + DITHER_MAX_SYSCOLOR ); + + for( n = 0; n < 256L; n++ ) + pSalData->mpDitherDiff[ n ] = n % 51L; + + for( n = 0; n < 256L; n++ ) + pSalData->mpDitherLow[ n ] = (BYTE) ( n / 51L ); + + for( n = 0; n < 256L; n++ ) + pSalData->mpDitherHigh[ n ] = Min( pSalData->mpDitherLow[ n ] + 1, 5 ); + } + + // get system color entries + ImplUpdateSysColorEntries(); + } + + ReleaseDC( 0, hDC ); +} + +// ----------------------------------------------------------------------- + +void ImplFreeSalGDI() +{ + SalData* pSalData = GetSalData(); + USHORT i; + + // destroy stock objects + for ( i = 0; i < pSalData->mnStockPenCount; i++ ) + DeletePen( pSalData->mhStockPenAry[i] ); + for ( i = 0; i < pSalData->mnStockBrushCount; i++ ) + DeleteBrush( pSalData->mhStockBrushAry[i] ); + + // 50% Brush loeschen + if ( pSalData->mh50Brush ) + { + DeleteBrush( pSalData->mh50Brush ); + pSalData->mh50Brush = 0; + } + + // 50% Bitmap loeschen + if ( pSalData->mh50Bmp ) + { + DeleteBitmap( pSalData->mh50Bmp ); + pSalData->mh50Bmp = 0; + } + + ImplClearHDCCache( pSalData ); + delete[] pSalData->mpHDCCache; + + // Ditherpalette loeschen, wenn vorhanden + if ( pSalData->mhDitherPal ) + { + DeleteObject( pSalData->mhDitherPal ); + pSalData->mhDitherPal = 0; + } + + // delete buffers for dithering DIB patterns, if neccessary + if ( pSalData->mhDitherDIB ) + { + GlobalUnlock( pSalData->mhDitherDIB ); + GlobalFree( pSalData->mhDitherDIB ); + pSalData->mhDitherDIB = 0; + delete[] pSalData->mpDitherDiff; + delete[] pSalData->mpDitherLow; + delete[] pSalData->mpDitherHigh; + } + + // delete SysColorList + SysColorEntry* pEntry = pFirstSysColor; + while( pEntry ) + { + SysColorEntry* pTmp = pEntry->pNext; + delete pEntry; + pEntry = pTmp; + } + pFirstSysColor = NULL; +} + +// ----------------------------------------------------------------------- + +static int ImplIsPaletteEntry( BYTE nRed, BYTE nGreen, BYTE nBlue ) +{ + // dither color? + if ( !(nRed % DITHER_PAL_DELTA) && !(nGreen % DITHER_PAL_DELTA) && !(nBlue % DITHER_PAL_DELTA) ) + return TRUE; + + PALETTEENTRY* pPalEntry = aImplSalSysPalEntryAry; + + // standard palette color? + for ( USHORT i = 0; i < DITHER_MAX_SYSCOLOR; i++, pPalEntry++ ) + { + if( pPalEntry->peRed == nRed && pPalEntry->peGreen == nGreen && pPalEntry->peBlue == nBlue ) + return TRUE; + } + + // extra color? + if ( aImplExtraColor1.peRed == nRed && + aImplExtraColor1.peGreen == nGreen && + aImplExtraColor1.peBlue == nBlue ) + { + return TRUE; + } + + return FALSE; +} + +// ======================================================================= + +int ImplIsSysColorEntry( SalColor nSalColor ) +{ + SysColorEntry* pEntry = pFirstSysColor; + const DWORD nTestRGB = (DWORD)RGB( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + + while ( pEntry ) + { + if ( pEntry->nRGB == nTestRGB ) + return TRUE; + pEntry = pEntry->pNext; + } + + return FALSE; +} + +// ======================================================================= + +static void ImplInsertSysColorEntry( int nSysIndex ) +{ + const DWORD nRGB = GetSysColor( nSysIndex ); + + if ( !ImplIsPaletteEntry( GetRValue( nRGB ), GetGValue( nRGB ), GetBValue( nRGB ) ) ) + { + if ( !pFirstSysColor ) + { + pActSysColor = pFirstSysColor = new SysColorEntry; + pFirstSysColor->nRGB = nRGB; + pFirstSysColor->pNext = NULL; + } + else + { + pActSysColor = pActSysColor->pNext = new SysColorEntry; + pActSysColor->nRGB = nRGB; + pActSysColor->pNext = NULL; + } + } +} + +// ======================================================================= + +void ImplUpdateSysColorEntries() +{ + // delete old SysColorList + SysColorEntry* pEntry = pFirstSysColor; + while( pEntry ) + { + SysColorEntry* pTmp = pEntry->pNext; + delete pEntry; + pEntry = pTmp; + } + pActSysColor = pFirstSysColor = NULL; + + // create new sys color list + ImplInsertSysColorEntry( COLOR_ACTIVEBORDER ); + ImplInsertSysColorEntry( COLOR_INACTIVEBORDER ); + if( aSalShlData.mnVersion >= 410 ) + { + ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION ); + ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION ); + } + ImplInsertSysColorEntry( COLOR_3DFACE ); + ImplInsertSysColorEntry( COLOR_3DHILIGHT ); + ImplInsertSysColorEntry( COLOR_3DLIGHT ); + ImplInsertSysColorEntry( COLOR_3DSHADOW ); + ImplInsertSysColorEntry( COLOR_3DDKSHADOW ); + ImplInsertSysColorEntry( COLOR_INFOBK ); + ImplInsertSysColorEntry( COLOR_INFOTEXT ); + ImplInsertSysColorEntry( COLOR_BTNTEXT ); + ImplInsertSysColorEntry( COLOR_WINDOW ); + ImplInsertSysColorEntry( COLOR_WINDOWTEXT ); + ImplInsertSysColorEntry( COLOR_HIGHLIGHT ); + ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT ); + ImplInsertSysColorEntry( COLOR_MENU ); + ImplInsertSysColorEntry( COLOR_MENUTEXT ); + ImplInsertSysColorEntry( COLOR_ACTIVECAPTION ); + ImplInsertSysColorEntry( COLOR_CAPTIONTEXT ); + ImplInsertSysColorEntry( COLOR_INACTIVECAPTION ); + ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT ); +} + +// ----------------------------------------------------------------------- + +static SalColor ImplGetROPSalColor( SalROPColor nROPColor ) +{ + SalColor nSalColor; + if ( nROPColor == SAL_ROP_0 ) + nSalColor = MAKE_SALCOLOR( 0, 0, 0 ); + else + nSalColor = MAKE_SALCOLOR( 255, 255, 255 ); + return nSalColor; +} + +// ======================================================================= + +void ImplSalInitGraphics( SalGraphicsData* pData ) +{ + // Beim Printer berechnen wir die minimale Linienstaerke + if ( pData->mbPrinter ) + { + int nDPIX = GetDeviceCaps( pData->mhDC, LOGPIXELSX ); + if ( nDPIX <= 300 ) + pData->mnPenWidth = 0; + else + pData->mnPenWidth = nDPIX/300; + } + + ::SetTextAlign( pData->mhDC, TA_BASELINE | TA_LEFT | TA_NOUPDATECP ); + ::SetBkMode( pData->mhDC, TRANSPARENT ); + ::SetROP2( pData->mhDC, R2_COPYPEN ); +} + +// ----------------------------------------------------------------------- + +void ImplSalDeInitGraphics( SalGraphicsData* pData ) +{ + // Default Objekte selektieren + if ( pData->mhDefPen ) + SelectPen( pData->mhDC, pData->mhDefPen ); + if ( pData->mhDefBrush ) + SelectBrush( pData->mhDC, pData->mhDefBrush ); + if ( pData->mhDefFont ) + SelectFont( pData->mhDC, pData->mhDefFont ); +} + +// ======================================================================= + +HDC ImplGetCachedDC( ULONG nID, HBITMAP hBmp ) +{ + SalData* pSalData = GetSalData(); + HDCCache* pC = &pSalData->mpHDCCache[ nID ]; + + if( !pC->mhDC ) + { + HDC hDC = GetDC( 0 ); + + // neuen DC mit DefaultBitmap anlegen + pC->mhDC = CreateCompatibleDC( hDC ); + + if( pSalData->mhDitherPal ) + { + pC->mhDefPal = SelectPalette( pC->mhDC, pSalData->mhDitherPal, TRUE ); + RealizePalette( pC->mhDC ); + } + + pC->mhSelBmp = CreateCompatibleBitmap( hDC, CACHED_HDC_DEFEXT, CACHED_HDC_DEFEXT ); + pC->mhDefBmp = (HBITMAP) SelectObject( pC->mhDC, pC->mhSelBmp ); + + ReleaseDC( 0, hDC ); + } + + if ( hBmp ) + SelectObject( pC->mhDC, pC->mhActBmp = hBmp ); + else + pC->mhActBmp = 0; + + return pC->mhDC; +} + +// ======================================================================= + +void ImplReleaseCachedDC( ULONG nID ) +{ + SalData* pSalData = GetSalData(); + HDCCache* pC = &pSalData->mpHDCCache[ nID ]; + + if ( pC->mhActBmp ) + SelectObject( pC->mhDC, pC->mhSelBmp ); +} + +// ======================================================================= + +void ImplClearHDCCache( SalData* pData ) +{ + for( ULONG i = 0; i < CACHESIZE_HDC; i++ ) + { + HDCCache* pC = &pData->mpHDCCache[ i ]; + + if( pC->mhDC ) + { + SelectObject( pC->mhDC, pC->mhDefBmp ); + + if( pC->mhDefPal ) + SelectPalette( pC->mhDC, pC->mhDefPal, TRUE ); + + DeleteDC( pC->mhDC ); + DeleteObject( pC->mhSelBmp ); + } + } +} + +// ======================================================================= + +SalGraphics::SalGraphics() +{ + maGraphicsData.mhDC = 0; + maGraphicsData.mhPen = 0; + maGraphicsData.mhBrush = 0; + maGraphicsData.mhFont = 0; + maGraphicsData.mhRegion = 0; + maGraphicsData.mhDefPen = 0; + maGraphicsData.mhDefBrush = 0; + maGraphicsData.mhDefFont = 0; + maGraphicsData.mhDefPal = 0; + maGraphicsData.mpStdClipRgnData = NULL; + maGraphicsData.mpLogFont = NULL; + maGraphicsData.mpFontCharSets = NULL; + maGraphicsData.mnFontCharSetCount = 0; + maGraphicsData.mpFontKernPairs = NULL; + maGraphicsData.mnFontKernPairCount = 0; + maGraphicsData.mbFontKernInit = FALSE; + maGraphicsData.mnFontOverhang = 0; + maGraphicsData.mbXORMode = FALSE; + maGraphicsData.mnPenWidth = GSL_PEN_WIDTH; + maGraphicsData.mbCalcOverhang = TRUE; +} + +// ----------------------------------------------------------------------- + +SalGraphics::~SalGraphics() +{ + // Objekte zerstoeren + if ( maGraphicsData.mhPen ) + { + if ( !maGraphicsData.mbStockPen ) + DeletePen( maGraphicsData.mhPen ); + } + if ( maGraphicsData.mhBrush ) + { + if ( !maGraphicsData.mbStockBrush ) + DeleteBrush( maGraphicsData.mhBrush ); + } + if ( maGraphicsData.mhFont ) + DeleteFont( maGraphicsData.mhFont ); + + if ( maGraphicsData.mhRegion ) + { + DeleteRegion( maGraphicsData.mhRegion ); + maGraphicsData.mhRegion = 0; + } + + // Cache-Daten zerstoeren + if ( maGraphicsData.mpStdClipRgnData ) + delete maGraphicsData.mpStdClipRgnData; + + if ( maGraphicsData.mpLogFont ) + delete maGraphicsData.mpLogFont; + + if ( maGraphicsData.mpFontCharSets ) + delete maGraphicsData.mpFontCharSets; + + if ( maGraphicsData.mpFontKernPairs ) + delete maGraphicsData.mpFontKernPairs; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::GetResolution( long& rDPIX, long& rDPIY ) +{ + rDPIX = GetDeviceCaps( maGraphicsData.mhDC, LOGPIXELSX ); + rDPIY = GetDeviceCaps( maGraphicsData.mhDC, LOGPIXELSY ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::GetScreenFontResolution( long& rDPIX, long& rDPIY ) +{ + rDPIX = GetDeviceCaps( maGraphicsData.mhDC, LOGPIXELSX ); + rDPIY = GetDeviceCaps( maGraphicsData.mhDC, LOGPIXELSY ); +} + +// ----------------------------------------------------------------------- + +USHORT SalGraphics::GetBitCount() +{ + return (USHORT)GetDeviceCaps( maGraphicsData.mhDC, BITSPIXEL ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::ResetClipRegion() +{ + if ( maGraphicsData.mhRegion ) + { + DeleteRegion( maGraphicsData.mhRegion ); + maGraphicsData.mhRegion = 0; + } + + SelectClipRgn( maGraphicsData.mhDC, 0 ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::BeginSetClipRegion( ULONG nRectCount ) +{ + if ( maGraphicsData.mhRegion ) + { + DeleteRegion( maGraphicsData.mhRegion ); + maGraphicsData.mhRegion = 0; + } + + ULONG nRectBufSize = sizeof(RECT)*nRectCount; + if ( nRectCount < SAL_CLIPRECT_COUNT ) + { + if ( !maGraphicsData.mpStdClipRgnData ) + maGraphicsData.mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))]; + maGraphicsData.mpClipRgnData = maGraphicsData.mpStdClipRgnData; + } + else + maGraphicsData.mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize]; + maGraphicsData.mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER ); + maGraphicsData.mpClipRgnData->rdh.iType = RDH_RECTANGLES; + maGraphicsData.mpClipRgnData->rdh.nCount = nRectCount; + maGraphicsData.mpClipRgnData->rdh.nRgnSize = nRectBufSize; + SetRectEmpty( &(maGraphicsData.mpClipRgnData->rdh.rcBound) ); + maGraphicsData.mpNextClipRect = (RECT*)(&(maGraphicsData.mpClipRgnData->Buffer)); + maGraphicsData.mbFirstClipRect = TRUE; +} + + +// ----------------------------------------------------------------------- + +BOOL SalGraphics::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + if ( nWidth && nHeight ) + { + RECT* pRect = maGraphicsData.mpNextClipRect; + RECT* pBoundRect = &(maGraphicsData.mpClipRgnData->rdh.rcBound); + long nRight = nX + nWidth; + long nBottom = nY + nHeight; + + if ( maGraphicsData.mbFirstClipRect ) + { + pBoundRect->left = nX; + pBoundRect->top = nY; + pBoundRect->right = nRight; + pBoundRect->bottom = nBottom; + maGraphicsData.mbFirstClipRect = FALSE; + } + else + { + if ( nX < pBoundRect->left ) + pBoundRect->left = (int)nX; + + if ( nY < pBoundRect->top ) + pBoundRect->top = (int)nY; + + if ( nRight > pBoundRect->right ) + pBoundRect->right = (int)nRight; + + if ( nBottom > pBoundRect->bottom ) + pBoundRect->bottom = (int)nBottom; + } + + pRect->left = (int)nX; + pRect->top = (int)nY; + pRect->right = (int)nRight; + pRect->bottom = (int)nBottom; + maGraphicsData.mpNextClipRect++; + } + else + { + maGraphicsData.mpClipRgnData->rdh.nCount--; + maGraphicsData.mpClipRgnData->rdh.nRgnSize -= sizeof( RECT ); + } + + return TRUE; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::EndSetClipRegion() +{ + // Aus den Region-Daten muessen wir jetzt eine ClipRegion erzeugen + if ( maGraphicsData.mpClipRgnData->rdh.nCount == 1 ) + { + RECT* pRect = &(maGraphicsData.mpClipRgnData->rdh.rcBound); + maGraphicsData.mhRegion = CreateRectRgn( pRect->left, pRect->top, + pRect->right, pRect->bottom ); + } + else + { + ULONG nSize = maGraphicsData.mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER); + maGraphicsData.mhRegion = ExtCreateRegion( NULL, nSize, maGraphicsData.mpClipRgnData ); + + // if ExtCreateRegion(...) is not supported + if( !maGraphicsData.mhRegion ) + { + RGNDATAHEADER* pHeader = (RGNDATAHEADER*) maGraphicsData.mpClipRgnData; + + if( pHeader->nCount ) + { + RECT* pRect = (RECT*) maGraphicsData.mpClipRgnData->Buffer; + maGraphicsData.mhRegion = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); + pRect++; + + for( ULONG n = 1; n < pHeader->nCount; n++, pRect++ ) + { + HRGN hRgn = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); + CombineRgn( maGraphicsData.mhRegion, maGraphicsData.mhRegion, hRgn, RGN_OR ); + DeleteRegion( hRgn ); + } + } + } + + if ( maGraphicsData.mpClipRgnData != maGraphicsData.mpStdClipRgnData ) + delete maGraphicsData.mpClipRgnData; + } + + SelectClipRgn( maGraphicsData.mhDC, maGraphicsData.mhRegion ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::SetLineColor() +{ + // create and select new pen + HPEN hNewPen = GetStockPen( NULL_PEN ); + HPEN hOldPen = SelectPen( maGraphicsData.mhDC, hNewPen ); + + // destory or save old pen + if ( maGraphicsData.mhPen ) + { + if ( !maGraphicsData.mbStockPen ) + DeletePen( maGraphicsData.mhPen ); + } + else + maGraphicsData.mhDefPen = hOldPen; + + // set new data + maGraphicsData.mhPen = hNewPen; + maGraphicsData.mbPen = FALSE; + maGraphicsData.mbStockPen = TRUE; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::SetLineColor( SalColor nSalColor ) +{ + COLORREF nPenColor = PALETTERGB( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + HPEN hNewPen = 0; + BOOL bStockPen; + + // search for stock pen (only screen, because printer have problems, + // when we use stock objects) + if ( !maGraphicsData.mbPrinter ) + { + SalData* pSalData = GetSalData(); + for ( USHORT i = 0; i < pSalData->mnStockPenCount; i++ ) + { + if ( nPenColor == pSalData->maStockPenColorAry[i] ) + { + hNewPen = pSalData->mhStockPenAry[i]; + bStockPen = TRUE; + break; + } + } + } + + // create new pen + if ( !hNewPen ) + { + if ( !maGraphicsData.mbPrinter ) + { + if ( GetSalData()->mhDitherPal && ImplIsSysColorEntry( nSalColor ) ) + nPenColor = PALRGB_TO_RGB( nPenColor ); + } + + hNewPen = CreatePen( PS_SOLID, maGraphicsData.mnPenWidth, nPenColor ); + bStockPen = FALSE; + } + + // select new pen + HPEN hOldPen = SelectPen( maGraphicsData.mhDC, hNewPen ); + + // destory or save old pen + if ( maGraphicsData.mhPen ) + { + if ( !maGraphicsData.mbStockPen ) + DeletePen( maGraphicsData.mhPen ); + } + else + maGraphicsData.mhDefPen = hOldPen; + + // set new data + maGraphicsData.mnPenColor = nPenColor; + maGraphicsData.mhPen = hNewPen; + maGraphicsData.mbPen = TRUE; + maGraphicsData.mbStockPen = bStockPen; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::SetFillColor() +{ + // create and select new brush + HBRUSH hNewBrush = GetStockBrush( NULL_BRUSH ); + HBRUSH hOldBrush = SelectBrush( maGraphicsData.mhDC, hNewBrush ); + + // destory or save old brush + if ( maGraphicsData.mhBrush ) + { + if ( !maGraphicsData.mbStockBrush ) + DeleteBrush( maGraphicsData.mhBrush ); + } + else + maGraphicsData.mhDefBrush = hOldBrush; + + // set new data + maGraphicsData.mhBrush = hNewBrush; + maGraphicsData.mbBrush = FALSE; + maGraphicsData.mbStockBrush = TRUE; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::SetFillColor( SalColor nSalColor ) +{ + SalData* pSalData = GetSalData(); + BYTE nRed = SALCOLOR_RED( nSalColor ); + BYTE nGreen = SALCOLOR_GREEN( nSalColor ); + BYTE nBlue = SALCOLOR_BLUE( nSalColor ); + COLORREF nBrushColor = PALETTERGB( nRed, nGreen, nBlue ); + HBRUSH hNewBrush = 0; + BOOL bStockBrush; + + // search for stock brush (only screen, because printer have problems, + // when we use stock objects) + if ( !maGraphicsData.mbPrinter ) + { + for ( USHORT i = 0; i < pSalData->mnStockBrushCount; i++ ) + { + if ( nBrushColor == pSalData->maStockBrushColorAry[ i ] ) + { + hNewBrush = pSalData->mhStockBrushAry[i]; + bStockBrush = TRUE; + break; + } + } + } + + // create new brush + if ( !hNewBrush ) + { + if ( maGraphicsData.mbPrinter || !pSalData->mhDitherDIB ) + hNewBrush = CreateSolidBrush( nBrushColor ); + else + { + if ( 24 == ((BITMAPINFOHEADER*)pSalData->mpDitherDIB)->biBitCount ) + { + BYTE* pTmp = pSalData->mpDitherDIBData; + long* pDitherDiff = pSalData->mpDitherDiff; + BYTE* pDitherLow = pSalData->mpDitherLow; + BYTE* pDitherHigh = pSalData->mpDitherHigh; + + for( long nY = 0L; nY < 8L; nY++ ) + { + for( long nX = 0L; nX < 8L; nX++ ) + { + const long nThres = aOrdDither16Bit[ nY ][ nX ]; + *pTmp++ = DMAP( nBlue, nThres ); + *pTmp++ = DMAP( nGreen, nThres ); + *pTmp++ = DMAP( nRed, nThres ); + } + } + + hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_RGB_COLORS ); + } + else if ( ImplIsSysColorEntry( nSalColor ) ) + { + nBrushColor = PALRGB_TO_RGB( nBrushColor ); + hNewBrush = CreateSolidBrush( nBrushColor ); + } + else if ( ImplIsPaletteEntry( nRed, nGreen, nBlue ) ) + hNewBrush = CreateSolidBrush( nBrushColor ); + else + { + BYTE* pTmp = pSalData->mpDitherDIBData; + long* pDitherDiff = pSalData->mpDitherDiff; + BYTE* pDitherLow = pSalData->mpDitherLow; + BYTE* pDitherHigh = pSalData->mpDitherHigh; + + for ( long nY = 0L; nY < 8L; nY++ ) + { + for ( long nX = 0L; nX < 8L; nX++ ) + { + const long nThres = aOrdDither8Bit[ nY ][ nX ]; + *pTmp = DMAP( nRed, nThres ) + DMAP( nGreen, nThres ) * 6 + DMAP( nBlue, nThres ) * 36; + pTmp++; + } + } + + hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_PAL_COLORS ); + } + } + + bStockBrush = FALSE; + } + + // select new brush + HBRUSH hOldBrush = SelectBrush( maGraphicsData.mhDC, hNewBrush ); + + // destory or save old brush + if ( maGraphicsData.mhBrush ) + { + if ( !maGraphicsData.mbStockBrush ) + DeleteBrush( maGraphicsData.mhBrush ); + } + else + maGraphicsData.mhDefBrush = hOldBrush; + + // set new data + maGraphicsData.mnBrushColor = nBrushColor; + maGraphicsData.mhBrush = hNewBrush; + maGraphicsData.mbBrush = FALSE; + maGraphicsData.mbStockBrush = bStockBrush; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::SetXORMode( BOOL bSet ) +{ + maGraphicsData.mbXORMode = bSet; + ::SetROP2( maGraphicsData.mhDC, bSet ? R2_XORPEN : R2_COPYPEN ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::SetROPLineColor( SalROPColor nROPColor ) +{ + SetLineColor( ImplGetROPSalColor( nROPColor ) ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::SetROPFillColor( SalROPColor nROPColor ) +{ + SetFillColor( ImplGetROPSalColor( nROPColor ) ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawPixel( long nX, long nY ) +{ + if ( maGraphicsData.mbXORMode ) + { + HBRUSH hBrush = CreateSolidBrush( maGraphicsData.mnPenColor ); + HBRUSH hOldBrush = SelectBrush( maGraphicsData.mhDC, hBrush ); + PatBlt( maGraphicsData.mhDC, (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); + SelectBrush( maGraphicsData.mhDC, hOldBrush ); + DeleteBrush( hBrush ); + } + else + SetPixel( maGraphicsData.mhDC, (int)nX, (int)nY, maGraphicsData.mnPenColor ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawPixel( long nX, long nY, SalColor nSalColor ) +{ + COLORREF nCol = PALETTERGB( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + + if ( !maGraphicsData.mbPrinter && + GetSalData()->mhDitherPal && + ImplIsSysColorEntry( nSalColor ) ) + nCol = PALRGB_TO_RGB( nCol ); + + if ( maGraphicsData.mbXORMode ) + { + HBRUSH hBrush = CreateSolidBrush( nCol ); + HBRUSH hOldBrush = SelectBrush( maGraphicsData.mhDC, hBrush ); + PatBlt( maGraphicsData.mhDC, (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); + SelectBrush( maGraphicsData.mhDC, hOldBrush ); + DeleteBrush( hBrush ); + } + else + ::SetPixel( maGraphicsData.mhDC, (int)nX, (int)nY, nCol ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawLine( long nX1, long nY1, long nX2, long nY2 ) +{ + MoveToEx( maGraphicsData.mhDC, (int)nX1, (int)nY1, NULL ); + + // we must paint the endpoint + int bPaintEnd = TRUE; + if ( nX1 == nX2 ) + { + bPaintEnd = FALSE; + if ( nY1 <= nY2 ) + nY2++; + else + nY2--; + } + if ( nY1 == nY2 ) + { + bPaintEnd = FALSE; + if ( nX1 <= nX2 ) + nX2++; + else + nX2--; + } + + LineTo( maGraphicsData.mhDC, (int)nX2, (int)nY2 ); + + if ( bPaintEnd && !maGraphicsData.mbPrinter ) + { + if ( maGraphicsData.mbXORMode ) + { + HBRUSH hBrush = CreateSolidBrush( maGraphicsData.mnPenColor ); + HBRUSH hOldBrush = SelectBrush( maGraphicsData.mhDC, hBrush ); + PatBlt( maGraphicsData.mhDC, (int)nX2, (int)nY2, (int)1, (int)1, PATINVERT ); + SelectBrush( maGraphicsData.mhDC, hOldBrush ); + DeleteBrush( hBrush ); + } + else + SetPixel( maGraphicsData.mhDC, (int)nX2, (int)nY2, maGraphicsData.mnPenColor ); + } +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawRect( long nX, long nY, long nWidth, long nHeight ) +{ + if ( !maGraphicsData.mbPen ) + { + if ( !maGraphicsData.mbPrinter ) + { + PatBlt( maGraphicsData.mhDC, (int)nX, (int)nY, (int)nWidth, (int)nHeight, + maGraphicsData.mbXORMode ? PATINVERT : PATCOPY ); + } + else + { + RECT aWinRect; + aWinRect.left = nX; + aWinRect.top = nY; + aWinRect.right = nX+nWidth; + aWinRect.bottom = nY+nHeight; + ::FillRect( maGraphicsData.mhDC, &aWinRect, maGraphicsData.mhBrush ); + } + } + else + WIN_Rectangle( maGraphicsData.mhDC, (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawPolyLine( ULONG nPoints, const SalPoint* pPtAry ) +{ + // Unter NT koennen wir das Array direkt weiterreichen + DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), + "SalGraphics::DrawPolyLine(): POINT != SalPoint" ); + + POINT* pWinPtAry = (POINT*)pPtAry; + // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl + // von Punkten + if ( !Polyline( maGraphicsData.mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) + Polyline( maGraphicsData.mhDC, pWinPtAry, MAX_64KSALPOINTS ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawPolygon( ULONG nPoints, const SalPoint* pPtAry ) +{ + // Unter NT koennen wir das Array direkt weiterreichen + DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), + "SalGraphics::DrawPolygon(): POINT != SalPoint" ); + + POINT* pWinPtAry = (POINT*)pPtAry; + // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl + // von Punkten + if ( !WIN_Polygon( maGraphicsData.mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) + WIN_Polygon( maGraphicsData.mhDC, pWinPtAry, MAX_64KSALPOINTS ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawPolyPolygon( ULONG nPoly, const ULONG* pPoints, + PCONSTSALPOINT* pPtAry ) +{ + UINT aWinPointAry[SAL_POLYPOLYCOUNT_STACKBUF]; + UINT* pWinPointAry; + UINT nPolyPolyPoints = 0; + UINT nPoints; + UINT i; + + if ( nPoly <= SAL_POLYPOLYCOUNT_STACKBUF ) + pWinPointAry = aWinPointAry; + else + pWinPointAry = new UINT[nPoly]; + + for ( i = 0; i < (UINT)nPoly; i++ ) + { + nPoints = (UINT)pPoints[i]+1; + pWinPointAry[i] = nPoints; + nPolyPolyPoints += nPoints; + } + + POINT aWinPointAryAry[SAL_POLYPOLYPOINTS_STACKBUF]; + POINT* pWinPointAryAry; + if ( nPolyPolyPoints <= SAL_POLYPOLYPOINTS_STACKBUF ) + pWinPointAryAry = aWinPointAryAry; + else + pWinPointAryAry = new POINT[nPolyPolyPoints]; + // Unter NT koennen wir das Array direkt weiterreichen + DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), + "SalGraphics::DrawPolyPolygon(): POINT != SalPoint" ); + const SalPoint* pPolyAry; + UINT n = 0; + for ( i = 0; i < (UINT)nPoly; i++ ) + { + nPoints = pWinPointAry[i]; + pPolyAry = pPtAry[i]; + memcpy( pWinPointAryAry+n, pPolyAry, (nPoints-1)*sizeof(POINT) ); + pWinPointAryAry[n+nPoints-1] = pWinPointAryAry[n]; + n += nPoints; + } + + if ( !WIN_PolyPolygon( maGraphicsData.mhDC, pWinPointAryAry, (int*)pWinPointAry, (UINT)nPoly ) && + (nPolyPolyPoints > MAX_64KSALPOINTS) ) + { + nPolyPolyPoints = 0; + nPoly = 0; + do + { + nPolyPolyPoints += pWinPointAry[(UINT)nPoly]; + nPoly++; + } + while ( nPolyPolyPoints < MAX_64KSALPOINTS ); + nPoly--; + if ( pWinPointAry[(UINT)nPoly] > MAX_64KSALPOINTS ) + pWinPointAry[(UINT)nPoly] = MAX_64KSALPOINTS; + if ( nPoly == 1 ) + WIN_Polygon( maGraphicsData.mhDC, pWinPointAryAry, *pWinPointAry ); + else + WIN_PolyPolygon( maGraphicsData.mhDC, pWinPointAryAry, (int*)pWinPointAry, nPoly ); + } + + if ( pWinPointAry != aWinPointAry ) + delete pWinPointAry; + if ( pWinPointAryAry != aWinPointAryAry ) + delete pWinPointAryAry; +} + + +// ----------------------------------------------------------------------- + +#define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF +#define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox + // in the first 4096 bytes + +static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, ULONG nComp, ULONG nSize ) +{ + while ( nComp-- >= nSize ) + { + for ( ULONG 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; + ULONG nBytesRead; + + if ( nSize < 256 ) // we assume that the file is greater than 256 bytes + return FALSE; + + if ( nSize < POSTSCRIPT_BOUNDINGSEARCH ) + nBytesRead = nSize; + else + nBytesRead = POSTSCRIPT_BOUNDINGSEARCH; + + BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nBytesRead, 14 ); + if ( pDest ) + { + int nSecurityCount = 100; // only 100 bytes following the bounding box will be checked + nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0; + pDest += 14; + for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ ) + { + int nDivision = 1; + BOOL bDivision = FALSE; + BOOL bNegative = FALSE; + BOOL bValid = TRUE; + + while ( ( --nSecurityCount ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++; + BYTE nByte = *pDest; + while ( nSecurityCount && ( 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' ) ) + nSecurityCount = 1; // error parsing the bounding box values + else if ( bValid ) + { + if ( bDivision ) + nDivision*=10; + nNumb[i] *= 10; + nNumb[i] += nByte - '0'; + } + break; + } + nSecurityCount--; + nByte = *(++pDest); + } + if ( bNegative ) + nNumb[i] = -nNumb[i]; + if ( bDivision && ( nDivision != 1 ) ) + nNumb[i] /= nDivision; + } + if ( nSecurityCount) + bRetValue = TRUE; + } + return bRetValue; +} + +inline void ImplWriteDouble( BYTE** pBuf, double nNumb ) +{ + *pBuf += sprintf( (char*)*pBuf, "%f", nNumb ); + *(*pBuf)++ = ' '; +} + +inline void ImplWriteString( BYTE** pBuf, const char* sString ) +{ + strcpy( (char*)*pBuf, sString ); + *pBuf += strlen( sString ); +} + +BOOL SalGraphics::DrawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize ) +{ + BOOL bRetValue = FALSE; + + if ( maGraphicsData.mbPrinter ) + { + int nEscape = POSTSCRIPT_PASSTHROUGH; + + if ( Escape( maGraphicsData.mhDC, QUERYESCSUPPORT, sizeof( int ), ( LPSTR )&nEscape, 0 ) ) + { + BYTE* pBuf = new BYTE[ POSTSCRIPT_BUFSIZE ]; + + double nBoundingBox[4]; + + if ( pBuf && ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) ) + { + double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] ); + double dM22 = nHeight / (nBoundingBox[1] - nBoundingBox[3] ); + BYTE* pTemp = pBuf + 2; // +2 because we want to insert the size later + ImplWriteString( &pTemp, "\n\nsave\n[ " ); + ImplWriteDouble( &pTemp, dM11 ); + ImplWriteDouble( &pTemp, 0 ); + ImplWriteDouble( &pTemp, 0 ); + ImplWriteDouble( &pTemp, dM22 ); + ImplWriteDouble( &pTemp, nX - ( dM11 * nBoundingBox[0] ) ); + ImplWriteDouble( &pTemp, nY - ( dM22 * nBoundingBox[3] ) ); + ImplWriteString( &pTemp, "] concat /showpage {} def\n" ); + ImplWriteString( &pTemp, "%%BeginDocument:\n" ); + *((USHORT*)pBuf) = (USHORT)( pTemp - pBuf - 2 ); + Escape ( maGraphicsData.mhDC, nEscape, pTemp - pBuf, (LPTSTR)((BYTE*)pBuf), 0 ); + + ULONG nToDo = nSize; + ULONG nDoNow; + while ( nToDo ) + { + nDoNow = nToDo; + if ( nToDo > POSTSCRIPT_BUFSIZE - 2 ) + nDoNow = POSTSCRIPT_BUFSIZE - 2; + *((USHORT*)pBuf) = (USHORT)nDoNow; + memcpy( pBuf + 2, (BYTE*)pPtr + nSize - nToDo, nDoNow ); + ULONG nResult = Escape ( maGraphicsData.mhDC, nEscape, nDoNow + 2, (LPTSTR)((BYTE*)pBuf), 0 ); + if (!nResult ) + break; + nToDo -= nResult; + } + pTemp = pBuf + 2; + ImplWriteString( &pTemp, "%%EndDocument\n" ); + ImplWriteString( &pTemp, "restore\n\n" ); + *((USHORT*)pBuf) = (USHORT)( pTemp - pBuf - 2 ); + Escape ( maGraphicsData.mhDC, nEscape, pTemp - pBuf, (LPTSTR)((BYTE*)pBuf), 0 ); + bRetValue = TRUE; + } + delete pBuf; + } + } + + return bRetValue; +} diff --git a/vcl/win/source/gdi/salgdi2.cxx b/vcl/win/source/gdi/salgdi2.cxx new file mode 100644 index 000000000000..20252e35f31b --- /dev/null +++ b/vcl/win/source/gdi/salgdi2.cxx @@ -0,0 +1,782 @@ +/************************************************************************* + * + * $RCSfile: salgdi2.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> +#include <stdlib.h> + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#define _SV_SALGDI2_CXX + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALBMP_HXX +#include <salbmp.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALIDS_HRC +#include <salids.hrc> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif + +// ======================================================================= + +BOOL bFastTransparent = FALSE; + +// ======================================================================= + +void SalGraphics::CopyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics ) +{ + HDC hSrcDC; + DWORD nRop; + + if ( pSrcGraphics ) + hSrcDC = pSrcGraphics->maGraphicsData.mhDC; + else + hSrcDC = maGraphicsData.mhDC; + + if ( maGraphicsData.mbXORMode ) + nRop = SRCINVERT; + else + nRop = SRCCOPY; + + if ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) && + (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) ) + { + BitBlt( maGraphicsData.mhDC, + (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, + (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, + hSrcDC, + (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, + nRop ); + } + else + { + int nOldStretchMode = SetStretchBltMode( maGraphicsData.mhDC, STRETCH_DELETESCANS ); + StretchBlt( maGraphicsData.mhDC, + (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, + (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, + hSrcDC, + (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, + (int)pPosAry->mnSrcWidth, (int)pPosAry->mnSrcHeight, + nRop ); + SetStretchBltMode( maGraphicsData.mhDC, nOldStretchMode ); + } +} + +// ----------------------------------------------------------------------- + +void ImplCalcOutSideRgn( const RECT& rSrcRect, + int nLeft, int nTop, int nRight, int nBottom, + HRGN& rhInvalidateRgn ) +{ + HRGN hTempRgn; + + // Bereiche ausserhalb des sichtbaren Bereiches berechnen + if ( rSrcRect.left < nLeft ) + { + if ( !rhInvalidateRgn ) + rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); + hTempRgn = CreateRectRgn( -31999, 0, nLeft, 31999 ); + CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); + DeleteRegion( hTempRgn ); + } + if ( rSrcRect.top < nTop ) + { + if ( !rhInvalidateRgn ) + rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); + hTempRgn = CreateRectRgn( 0, -31999, 31999, nTop ); + CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); + DeleteRegion( hTempRgn ); + } + if ( rSrcRect.right > nRight ) + { + if ( !rhInvalidateRgn ) + rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); + hTempRgn = CreateRectRgn( nRight, 0, 31999, 31999 ); + CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); + DeleteRegion( hTempRgn ); + } + if ( rSrcRect.bottom > nBottom ) + { + if ( !rhInvalidateRgn ) + rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); + hTempRgn = CreateRectRgn( 0, nBottom, 31999, 31999 ); + CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); + DeleteRegion( hTempRgn ); + } +} + +// ----------------------------------------------------------------------- + +void SalGraphics::CopyArea( long nDestX, long nDestY, + long nSrcX, long nSrcY, + long nSrcWidth, long nSrcHeight, + USHORT nFlags ) +{ + BitBlt( maGraphicsData.mhDC, + (int)nDestX, (int)nDestY, + (int)nSrcWidth, (int)nSrcHeight, + maGraphicsData.mhDC, + (int)nSrcX, (int)nSrcY, + SRCCOPY ); + + // Muessen die ueberlappenden Bereiche auch invalidiert werden? + if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && maGraphicsData.mbWindow ) + { + // Overlap-Bereich berechnen und invalidieren + RECT aSrcRect; + RECT aClipRect; + RECT aTempRect; + RECT aTempRect2; + HRGN hInvalidateRgn; + HRGN hTempRgn; + HWND hWnd; + int nRgnType; + + aSrcRect.left = (int)nSrcX; + aSrcRect.top = (int)nSrcY; + aSrcRect.right = aSrcRect.left+(int)nSrcWidth; + aSrcRect.bottom = aSrcRect.top+(int)nSrcHeight; + GetClientRect( maGraphicsData.mhWnd, &aClipRect ); + if ( IntersectRect( &aSrcRect, &aSrcRect, &aClipRect ) ) + { + // Rechteck in Screen-Koordinaaten umrechnen + POINT aPt; + int nScreenDX = GetSystemMetrics( SM_CXSCREEN ); + int nScreenDY = GetSystemMetrics( SM_CYSCREEN ); + aPt.x = 0; + aPt.y = 0; + ClientToScreen( maGraphicsData.mhWnd, &aPt ); + aSrcRect.left += aPt.x; + aSrcRect.top += aPt.y; + aSrcRect.right += aPt.x; + aSrcRect.bottom += aPt.y; + hInvalidateRgn = 0; + // Bereiche ausserhalb des sichtbaren Bereiches berechnen + ImplCalcOutSideRgn( aSrcRect, 0, 0, nScreenDX, nScreenDY, hInvalidateRgn ); + + // Bereiche die von anderen Fenstern ueberlagert werden berechnen + HRGN hTempRgn2 = 0; + HWND hWndTopWindow = maGraphicsData.mhWnd; + // Find the TopLevel Window, because only Windows which are in + // in the foreground of our TopLevel window must be considered + if ( GetWindowStyle( hWndTopWindow ) & WS_CHILD ) + { + RECT aTempRect3 = aSrcRect; + do + { + hWndTopWindow = ::GetParent( hWndTopWindow ); + + // Test, if the Parent clip our window + GetClientRect( hWndTopWindow, &aTempRect ); + POINT aPt2; + aPt2.x = 0; + aPt2.y = 0; + ClientToScreen( hWndTopWindow, &aPt2 ); + aTempRect.left += aPt2.x; + aTempRect.top += aPt2.y; + aTempRect.right += aPt2.x; + aTempRect.bottom += aPt2.y; + IntersectRect( &aTempRect3, &aTempRect3, &aTempRect ); + } + while ( GetWindowStyle( hWndTopWindow ) & WS_CHILD ); + + // If one or more Parents clip our window, than we must + // calculate the outside area + if ( !EqualRect( &aSrcRect, &aTempRect3 ) ) + { + ImplCalcOutSideRgn( aSrcRect, + aTempRect3.left, aTempRect3.top, + aTempRect3.right, aTempRect3.bottom, + hInvalidateRgn ); + } + } + hWnd = GetWindow( GetDesktopWindow(), GW_CHILD ); + while ( hWnd ) + { + if ( hWnd == hWndTopWindow ) + break; + if ( IsWindowVisible( hWnd ) && !IsIconic( hWnd ) ) + { + GetWindowRect( hWnd, &aTempRect ); + if ( IntersectRect( &aTempRect2, &aSrcRect, &aTempRect ) ) + { + if ( !hInvalidateRgn ) + hInvalidateRgn = CreateRectRgnIndirect( &aSrcRect ); + hTempRgn = CreateRectRgnIndirect( &aTempRect ); + if ( !hTempRgn2 ) + hTempRgn2 = CreateRectRgn( 0, 0, 0, 0 ); + nRgnType = GetWindowRgn( hWnd, hTempRgn2 ); + if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) ) + { + OffsetRgn( hTempRgn2, aTempRect.left, aTempRect.top ); + CombineRgn( hTempRgn, hTempRgn, hTempRgn2, RGN_AND ); + } + CombineRgn( hInvalidateRgn, hInvalidateRgn, hTempRgn, RGN_DIFF ); + DeleteRegion( hTempRgn ); + } + } + hWnd = GetWindow( hWnd, GW_HWNDNEXT ); + } + if ( hTempRgn2 ) + DeleteRegion( hTempRgn2 ); + if ( hInvalidateRgn ) + { + hTempRgn = CreateRectRgnIndirect( &aSrcRect ); + nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_DIFF ); + if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) ) + { + int nOffX = (int)(nDestX-nSrcX); + int nOffY = (int)(nDestY-nSrcY); + OffsetRgn( hInvalidateRgn, nOffX-aPt.x, nOffY-aPt.y ); + // Combine Invalidate Region with existing ClipRegion + if ( GetClipRgn( maGraphicsData.mhDC, hTempRgn ) == 1 ) + nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_AND ); + if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) ) + { + InvalidateRgn( maGraphicsData.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(); + DWORD nCurThreadId = GetCurrentThreadId(); + if ( pSalData->mnAppThreadId == nCurThreadId ) + UpdateWindow( maGraphicsData.mhWnd ); + } + } + DeleteRegion( hTempRgn ); + DeleteRegion( hInvalidateRgn ); + } + } + } +} + +// ----------------------------------------------------------------------- + +void ImplDrawBitmap( HDC hDC, + const SalTwoRect* pPosAry, const SalBitmap& rSalBitmap, + BOOL bPrinter, int nDrawMode ) +{ + if( hDC ) + { + HGLOBAL hDrawDIB; + HBITMAP hDrawDDB = rSalBitmap.ImplGethDDB(); + SalBitmap* pTmpSalBmp; + BOOL bPrintDDB = ( bPrinter && hDrawDDB ); + + if( bPrintDDB ) + { + pTmpSalBmp = new SalBitmap; + pTmpSalBmp->Create( rSalBitmap, rSalBitmap.GetBitCount() ); + hDrawDIB = pTmpSalBmp->ImplGethDIB(); + } + else + hDrawDIB = rSalBitmap.ImplGethDIB(); + + if( hDrawDIB ) + { + PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDrawDIB ); + PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; + PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + + rSalBitmap.ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD ); + const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS ); + + int nCount = StretchDIBits( hDC, + (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, + (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, + (int)pPosAry->mnSrcX, (int)(pBIH->biHeight - pPosAry->mnSrcHeight - pPosAry->mnSrcY), + (int)pPosAry->mnSrcWidth, (int)pPosAry->mnSrcHeight, + pBits, pBI, DIB_RGB_COLORS, nDrawMode ); + + GlobalUnlock( hDrawDIB ); + SetStretchBltMode( hDC, nOldStretchMode ); + } + else if( hDrawDDB && !bPrintDDB ) + { + HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_DRAW, hDrawDDB ); + COLORREF nOldBkColor; + COLORREF nOldTextColor; + BOOL bMono = ( rSalBitmap.GetBitCount() == 1 ); + + if( bMono ) + { + nOldBkColor = SetBkColor( hDC, RGB( 0xFF, 0xFF, 0xFF ) ); + nOldTextColor = ::SetTextColor( hDC, RGB( 0x00, 0x00, 0x00 ) ); + } + + if ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) && + (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) ) + { + BitBlt( hDC, + (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, + (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, + hBmpDC, + (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, + nDrawMode ); + } + else + { + const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS ); + + StretchBlt( hDC, + (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, + (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, + hBmpDC, + (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, + (int)pPosAry->mnSrcWidth, (int)pPosAry->mnSrcHeight, + nDrawMode ); + + SetStretchBltMode( hDC, nOldStretchMode ); + } + + if( bMono ) + { + SetBkColor( hDC, nOldBkColor ); + ::SetTextColor( hDC, nOldTextColor ); + } + + ImplReleaseCachedDC( CACHED_HDC_DRAW ); + } + + if( bPrintDDB ) + delete pTmpSalBmp; + } +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap ) +{ + ImplDrawBitmap( maGraphicsData.mhDC, pPosAry, rSalBitmap, + maGraphicsData.mbPrinter, + maGraphicsData.mbXORMode ? SRCINVERT : SRCCOPY ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + SalColor nTransparentColor ) +{ + DBG_ASSERT( !maGraphicsData.mbPrinter, "No transparency print possible!" ); + + SalBitmap* pMask = new SalBitmap; + HDC hDC = maGraphicsData.mhDC; + const Point aPoint; + const Size aSize( rSalBitmap.GetSize() ); + HBITMAP hMaskBitmap = CreateBitmap( (int) aSize.Width(), (int) aSize.Height(), 1, 1, NULL ); + HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_1, hMaskBitmap ); + const BYTE cRed = SALCOLOR_RED( nTransparentColor ); + const BYTE cGreen = SALCOLOR_GREEN( nTransparentColor ); + const BYTE cBlue = SALCOLOR_BLUE( nTransparentColor ); + + if( rSalBitmap.ImplGethDDB() ) + { + HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, rSalBitmap.ImplGethDDB() ); + COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) ); + + BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY ); + + SetBkColor( hSrcDC, aOldCol ); + ImplReleaseCachedDC( CACHED_HDC_2 ); + } + else + { + SalBitmap* pTmpSalBmp = new SalBitmap; + + if( pTmpSalBmp->Create( rSalBitmap, this ) ) + { + HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, pTmpSalBmp->ImplGethDDB() ); + COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) ); + + BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY ); + + SetBkColor( hSrcDC, aOldCol ); + ImplReleaseCachedDC( CACHED_HDC_2 ); + } + + delete pTmpSalBmp; + } + + ImplReleaseCachedDC( CACHED_HDC_1 ); + + // hMaskBitmap is destroyed by new SalBitmap 'pMask' ( bDIB==FALSE, bCopy == FALSE ) + if( pMask->Create( hMaskBitmap, FALSE, FALSE ) ) + DrawBitmap( pPosAry, rSalBitmap, *pMask ); + + delete pMask; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + const SalBitmap& rTransparentBitmap ) +{ + DBG_ASSERT( !maGraphicsData.mbPrinter, "No transparency print possible!" ); + + if( bFastTransparent ) + { + // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, + // die Farben der Maske richtig auf die Palette abzubilden, + // wenn wir die DIB direkt ausgeben => DDB-Ausgabe + if( ( GetBitCount() <= 8 ) && rTransparentBitmap.ImplGethDIB() && rTransparentBitmap.GetBitCount() == 1 ) + { + SalBitmap aTmp; + if( aTmp.Create( rTransparentBitmap, this ) ) + ImplDrawBitmap( maGraphicsData.mhDC, pPosAry, aTmp, FALSE, SRCAND ); + } + else + ImplDrawBitmap( maGraphicsData.mhDC, pPosAry, rTransparentBitmap, FALSE, SRCAND ); + + // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, + // die Farben der Maske richtig auf die Palette abzubilden, + // wenn wir die DIB direkt ausgeben => DDB-Ausgabe + if( ( GetBitCount() <= 8 ) && rSalBitmap.ImplGethDIB() && rSalBitmap.GetBitCount() == 1 ) + { + SalBitmap aTmp; + if( aTmp.Create( rSalBitmap, this ) ) + ImplDrawBitmap( maGraphicsData.mhDC, pPosAry, aTmp, FALSE, SRCPAINT ); + } + else + ImplDrawBitmap( maGraphicsData.mhDC, pPosAry, rSalBitmap, FALSE, 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; + HDC hDC = maGraphicsData.mhDC; + HBITMAP hMemBitmap = 0; + HBITMAP hMaskBitmap = 0; + + if( ( nDstWidth > CACHED_HDC_DEFEXT ) || ( nDstHeight > CACHED_HDC_DEFEXT ) ) + { + hMemBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight ); + hMaskBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight ); + } + + HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, hMemBitmap ); + HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_2, hMaskBitmap ); + + aPosAry.mnDestX = aPosAry.mnDestY = 0; + BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hDC, nDstX, nDstY, SRCCOPY ); + + // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, + // die Farben der Maske richtig auf die Palette abzubilden, + // wenn wir die DIB direkt ausgeben => DDB-Ausgabe + if( ( GetBitCount() <= 8 ) && rTransparentBitmap.ImplGethDIB() && rTransparentBitmap.GetBitCount() == 1 ) + { + SalBitmap aTmp; + + if( aTmp.Create( rTransparentBitmap, this ) ) + ImplDrawBitmap( hMaskDC, &aPosAry, aTmp, FALSE, SRCCOPY ); + } + else + ImplDrawBitmap( hMaskDC, &aPosAry, rTransparentBitmap, FALSE, SRCCOPY ); + + BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCAND ); + ImplDrawBitmap( hMaskDC, &aPosAry, rSalBitmap, FALSE, SRCERASE ); + BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCPAINT ); + BitBlt( hDC, nDstX, nDstY, nDstWidth, nDstHeight, hMemDC, 0, 0, SRCCOPY ); + + ImplReleaseCachedDC( CACHED_HDC_1 ); + ImplReleaseCachedDC( CACHED_HDC_2 ); + + // hMemBitmap != 0 ==> hMaskBitmap != 0 + if( hMemBitmap ) + { + DeleteObject( hMemBitmap ); + DeleteObject( hMaskBitmap ); + } + } +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawMask( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + SalColor nMaskColor ) +{ + DBG_ASSERT( !maGraphicsData.mbPrinter, "No transparency print possible!" ); + + SalTwoRect aPosAry = *pPosAry; + const BYTE cRed = SALCOLOR_RED( nMaskColor ); + const BYTE cGreen = SALCOLOR_GREEN( nMaskColor ); + const BYTE cBlue = SALCOLOR_BLUE( nMaskColor ); + HDC hDC = maGraphicsData.mhDC; + HBRUSH hMaskBrush = CreateSolidBrush( RGB( cRed, cGreen, cBlue ) ); + HBRUSH hOldBrush = SelectBrush( hDC, hMaskBrush ); + + // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, + // die Farben der Maske richtig auf die Palette abzubilden, + // wenn wir die DIB direkt ausgeben => DDB-Ausgabe + if( ( GetBitCount() <= 8 ) && rSalBitmap.ImplGethDIB() && rSalBitmap.GetBitCount() == 1 ) + { + SalBitmap aTmp; + + if( aTmp.Create( rSalBitmap, this ) ) + ImplDrawBitmap( hDC, &aPosAry, aTmp, FALSE, 0x00B8074AUL ); + } + else + ImplDrawBitmap( hDC, &aPosAry, rSalBitmap, FALSE, 0x00B8074AUL ); + + SelectBrush( hDC, hOldBrush ); + DeleteBrush( hMaskBrush ); +} + +// ----------------------------------------------------------------------- + +SalBitmap* SalGraphics::GetBitmap( long nX, long nY, long nDX, long nDY ) +{ + DBG_ASSERT( !maGraphicsData.mbPrinter, "No ::GetBitmap() from printer possible!" ); + + SalBitmap* pSalBitmap = NULL; + + nDX = labs( nDX ); + nDY = labs( nDY ); + + HDC hDC = maGraphicsData.mhDC; + HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY ); + HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap ); + BOOL bRet; + + bRet = BitBlt( hBmpDC, 0, 0, (int) nDX, (int) nDY, hDC, (int) nX, (int) nY, SRCCOPY ); + ImplReleaseCachedDC( CACHED_HDC_1 ); + + if( bRet ) + { + pSalBitmap = new SalBitmap; + + if( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) ) + { + delete pSalBitmap; + pSalBitmap = NULL; + } + } + + return pSalBitmap; +} + +// ----------------------------------------------------------------------- + +SalColor SalGraphics::GetPixel( long nX, long nY ) +{ + COLORREF aWinCol = ::GetPixel( maGraphicsData.mhDC, (int) nX, (int) nY ); + +#ifdef WIN + if ( -1 == aWinCol ) +#else + if ( CLR_INVALID == aWinCol ) +#endif + return MAKE_SALCOLOR( 0, 0, 0 ); + else + return MAKE_SALCOLOR( GetRValue( aWinCol ), + GetGValue( aWinCol ), + GetBValue( aWinCol ) ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::Invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) +{ + if ( nFlags & SAL_INVERT_TRACKFRAME ) + { + HPEN hDotPen = CreatePen( PS_DOT, 0, 0 ); + HPEN hOldPen = SelectPen( maGraphicsData.mhDC, hDotPen ); + HBRUSH hOldBrush = SelectBrush( maGraphicsData.mhDC, GetStockBrush( NULL_BRUSH ) ); + int nOldROP = SetROP2( maGraphicsData.mhDC, R2_NOT ); + + WIN_Rectangle( maGraphicsData.mhDC, (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) ); + + SetROP2( maGraphicsData.mhDC, nOldROP ); + SelectPen( maGraphicsData.mhDC, hOldPen ); + SelectBrush( maGraphicsData.mhDC, hOldBrush ); + DeletePen( hDotPen ); + } + else if ( nFlags & SAL_INVERT_50 ) + { + SalData* pSalData = GetSalData(); + if ( !pSalData->mh50Brush ) + { + if ( !pSalData->mh50Bmp ) + pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 ); + pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp ); + } + + COLORREF nOldTextColor = ::SetTextColor( maGraphicsData.mhDC, 0 ); + HBRUSH hOldBrush = SelectBrush( maGraphicsData.mhDC, pSalData->mh50Brush ); + PatBlt( maGraphicsData.mhDC, nX, nY, nWidth, nHeight, PATINVERT ); + ::SetTextColor( maGraphicsData.mhDC, nOldTextColor ); + SelectBrush( maGraphicsData.mhDC, hOldBrush ); + } + else + { + RECT aRect; + aRect.left = (int)nX; + aRect.top = (int)nY; + aRect.right = (int)nX+nWidth; + aRect.bottom = (int)nY+nHeight; + ::InvertRect( maGraphicsData.mhDC, &aRect ); + } +} + +// ----------------------------------------------------------------------- + +void SalGraphics::Invert( ULONG nPoints, const SalPoint* pPtAry, SalInvert nSalFlags ) +{ + HPEN hPen; + HPEN hOldPen; + HBRUSH hBrush; + HBRUSH hOldBrush; + COLORREF nOldTextColor; + int nOldROP = SetROP2( maGraphicsData.mhDC, R2_NOT ); + + if ( nSalFlags & SAL_INVERT_TRACKFRAME ) + hPen = CreatePen( PS_DOT, 0, 0 ); + else + { + + if ( nSalFlags & SAL_INVERT_50 ) + { + SalData* pSalData = GetSalData(); + if ( !pSalData->mh50Brush ) + { + if ( !pSalData->mh50Bmp ) + pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 ); + pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp ); + } + + hBrush = pSalData->mh50Brush; + } + else + hBrush = GetStockBrush( BLACK_BRUSH ); + + hPen = GetStockPen( NULL_PEN ); + nOldTextColor = ::SetTextColor( maGraphicsData.mhDC, 0 ); + hOldBrush = SelectBrush( maGraphicsData.mhDC, hBrush ); + } + hOldPen = SelectPen( maGraphicsData.mhDC, hPen ); + + POINT* pWinPtAry; +#ifdef WIN + if ( nPoints > MAX_64KSALPOINTS ) + nPoints = MAX_64KSALPOINTS; + + pWinPtAry = new POINT[(USHORT)nPoints]; + const SalPoint huge* pHugePtAry = (const SalPoint huge*)pPtAry; + for( USHORT i=0; i < (USHORT)nPoints ; i++ ) + { + pWinPtAry[i].x = (int)pHugePtAry[i].mnX; + pWinPtAry[i].y = (int)pHugePtAry[i].mnY; + } + if ( nSalFlags & SAL_INVERT_TRACKFRAME ) + Polyline( maGraphicsData.mhDC, pWinPtAry, (int)nPoints ); + else + WIN_Polygon( maGraphicsData.mhDC, pWinPtAry, (int)nPoints ); + delete pWinPtAry; +#else + // Unter NT koennen wir das Array direkt weiterreichen + DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), + "SalGraphics::DrawPolyLine(): POINT != SalPoint" ); + + pWinPtAry = (POINT*)pPtAry; + // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl + // von Punkten + if ( nSalFlags & SAL_INVERT_TRACKFRAME ) + { + if ( !Polyline( maGraphicsData.mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) + Polyline( maGraphicsData.mhDC, pWinPtAry, MAX_64KSALPOINTS ); + } + else + { + if ( !WIN_Polygon( maGraphicsData.mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) + WIN_Polygon( maGraphicsData.mhDC, pWinPtAry, MAX_64KSALPOINTS ); + } +#endif + + SetROP2( maGraphicsData.mhDC, nOldROP ); + SelectPen( maGraphicsData.mhDC, hOldPen ); + + if ( nSalFlags & SAL_INVERT_TRACKFRAME ) + DeletePen( hPen ); + else + { + ::SetTextColor( maGraphicsData.mhDC, nOldTextColor ); + SelectBrush( maGraphicsData.mhDC, hOldBrush ); + } +} diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx new file mode 100644 index 000000000000..aa6b4c347090 --- /dev/null +++ b/vcl/win/source/gdi/salgdi3.cxx @@ -0,0 +1,1531 @@ +/************************************************************************* + * + * $RCSfile: salgdi3.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALGDI3_CXX + +#ifndef _RTL_TENCINFO_H +#include <rtl/tencinfo.h> +#endif + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif +#ifndef _SV_OUTFONT_HXX +#include <outfont.hxx> +#endif +#ifndef _SV_FONT_HXX +#include <font.hxx> +#endif + +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif + +// ----------- +// - Defines - +// ----------- + +#ifdef WIN +#define GDI_ERROR (0xFFFFFFFFUL) +#endif + +#define GLYPH_INC (512UL) +#define MAX_POLYCOUNT (2048UL) +#define CHECKPOINTS( _def_nPnt ) \ + if( (_def_nPnt) >= nPtSize ) \ + nPtSize = ImplIncreaseArrays( nPtSize, &pPoints, &pFlags, GLYPH_INC ) + +// ----------- +// - Inlines - +// ----------- + +inline FIXED FixedFromDouble( double d ) +{ + const long l = (long) ( d * 65536. ); + return *(FIXED*) &l; +} + +// ----------------------------------------------------------------------- + +inline int IntFromFixed(FIXED f) +{ + return( ( f.fract >= 0x8000 ) ? ( f.value + 1 ) : f.value ); +} + +// ----------------------------------------------------------------------- + +inline FIXED fxDiv2( FIXED fxVal1, FIXED fxVal2 ) +{ + const long l = (*((long far *)&(fxVal1)) + *((long far *)&(fxVal2))) >> 1; + return *(FIXED*) &l; +} + +// ======================================================================= + +#define SAL_DRAWTEXT_STACKBUF 128 + +// ======================================================================= + +// Diese Variablen koennen static sein, da systemweite Einstellungen +// gemerkt werden +static BOOL bImplSalCourierScalable = FALSE; +static BOOL bImplSalCourierNew = FALSE; + +// ======================================================================= + +struct ImplEnumInfo +{ + HDC mhDC; + ImplDevFontList* mpList; + XubString* mpName; + LOGFONTA* mpLogFontA; + LOGFONTW* mpLogFontW; + BOOL mbCourier; + BOOL mbImplSalCourierScalable; + BOOL mbImplSalCourierNew; + BOOL mbPrinter; +}; + +// ======================================================================= + +static CharSet ImplCharSetToSal( BYTE nCharSet ) +{ + if ( nCharSet == OEM_CHARSET ) + { + UINT nCP = (USHORT)GetOEMCP(); + return rtl_getTextEncodingFromPCCodePage( nCP ); + } + else + return rtl_getTextEncodingFromWindowsCharset( nCharSet ); +} + +// ----------------------------------------------------------------------- + +static BYTE ImplCharSetToWin( CharSet eCharSet ) +{ + return rtl_getBestWindowsCharsetFromTextEncoding( eCharSet ); +} + +// ----------------------------------------------------------------------- + +static FontFamily ImplFamilyToSal( BYTE nFamily ) +{ + switch ( nFamily & 0xF0 ) + { + case FF_DECORATIVE: + return FAMILY_DECORATIVE; + + case FF_MODERN: + return FAMILY_MODERN; + + case FF_ROMAN: + return FAMILY_ROMAN; + + case FF_SCRIPT: + return FAMILY_SCRIPT; + + case FF_SWISS: + return FAMILY_SWISS; + } + + return FAMILY_DONTKNOW; +} + +// ----------------------------------------------------------------------- + +static BYTE ImplFamilyToWin( FontFamily eFamily ) +{ + switch ( eFamily ) + { + case FAMILY_DECORATIVE: + return FF_DECORATIVE; + + case FAMILY_MODERN: + return FF_MODERN; + + case FAMILY_ROMAN: + return FF_ROMAN; + + case FAMILY_SCRIPT: + return FF_SCRIPT; + + case FAMILY_SWISS: + return FF_SWISS; + + case FAMILY_SYSTEM: + return FF_SWISS; + } + + return FF_DONTCARE; +} + +// ----------------------------------------------------------------------- + +static FontWeight ImplWeightToSal( WinWeight nWeight ) +{ + if ( nWeight <= FW_THIN ) + return WEIGHT_THIN; + else if ( nWeight <= FW_ULTRALIGHT ) + return WEIGHT_ULTRALIGHT; + else if ( nWeight <= FW_LIGHT ) + return WEIGHT_LIGHT; + else if ( nWeight < FW_MEDIUM ) + return WEIGHT_NORMAL; + else if ( nWeight == FW_MEDIUM ) + return WEIGHT_MEDIUM; + else if ( nWeight <= FW_SEMIBOLD ) + return WEIGHT_SEMIBOLD; + else if ( nWeight <= FW_BOLD ) + return WEIGHT_BOLD; + else if ( nWeight <= FW_ULTRABOLD ) + return WEIGHT_ULTRABOLD; + else + return WEIGHT_BLACK; +} + +// ----------------------------------------------------------------------- + +static WinWeight ImplWeightToWin( FontWeight eWeight ) +{ + switch ( eWeight ) + { + case WEIGHT_THIN: + return FW_THIN; + + case WEIGHT_ULTRALIGHT: + return FW_ULTRALIGHT; + + case WEIGHT_LIGHT: + return FW_LIGHT; + + case WEIGHT_SEMILIGHT: + case WEIGHT_NORMAL: + return FW_NORMAL; + + case WEIGHT_MEDIUM: + return FW_MEDIUM; + + case WEIGHT_SEMIBOLD: + return FW_SEMIBOLD; + + case WEIGHT_BOLD: + return FW_BOLD; + + case WEIGHT_ULTRABOLD: + return FW_ULTRABOLD; + + case WEIGHT_BLACK: + return FW_BLACK; + } + + return 0; +} + +// ----------------------------------------------------------------------- + +inline FontPitch ImplLogPitchToSal( BYTE nPitch ) +{ + if ( nPitch & FIXED_PITCH ) + return PITCH_FIXED; + else + return PITCH_VARIABLE; +} + +// ----------------------------------------------------------------------- + +inline FontPitch ImplMetricPitchToSal( BYTE nPitch ) +{ + // Sausaecke bei MS !! siehe NT Hilfe + if ( !(nPitch & TMPF_FIXED_PITCH) ) + return PITCH_FIXED; + else + return PITCH_VARIABLE; +} + +// ----------------------------------------------------------------------- + +inline BYTE ImplPitchToWin( FontPitch ePitch ) +{ + if ( ePitch == PITCH_FIXED ) + return FIXED_PITCH; + else if ( ePitch == PITCH_VARIABLE ) + return VARIABLE_PITCH; + else + return DEFAULT_PITCH; +} + +// ----------------------------------------------------------------------- + +static void ImplLogMetricToDevFontDataA( const LOGFONTA* pLogFont, + const NEWTEXTMETRICA* pMetric, + DWORD nFontType, + ImplFontData* pData ) +{ + if ( !(nFontType & RASTER_FONTTYPE) ) + { + pData->mnWidth = 0; + pData->mnHeight = 0; + } + else + { + pData->mnWidth = 0; + pData->mnHeight = pMetric->tmHeight-pMetric->tmInternalLeading; + } + pData->meFamily = ImplFamilyToSal( pLogFont->lfPitchAndFamily ); + pData->meCharSet = ImplCharSetToSal( pLogFont->lfCharSet ); + pData->meWidthType = WIDTH_DONTKNOW; + pData->meWeight = ImplWeightToSal( pLogFont->lfWeight ); + pData->meItalic = (pLogFont->lfItalic) ? ITALIC_NORMAL : ITALIC_NONE; + pData->mePitch = ImplLogPitchToSal( pLogFont->lfPitchAndFamily ); + if ( pMetric->tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) ) + pData->meType = TYPE_SCALABLE; + else + pData->meType = TYPE_RASTER; + pData->mbOrientation = (nFontType & RASTER_FONTTYPE) == 0; + pData->mbDevice = (pMetric->tmPitchAndFamily & TMPF_DEVICE) != 0; + pData->mnQuality = 0; +} + +// ----------------------------------------------------------------------- + +static void ImplLogMetricToDevFontDataW( const LOGFONTW* pLogFont, + const NEWTEXTMETRICW* pMetric, + DWORD nFontType, + ImplFontData* pData ) +{ + if ( !(nFontType & RASTER_FONTTYPE) ) + { + pData->mnWidth = 0; + pData->mnHeight = 0; + } + else + { + pData->mnWidth = 0; + pData->mnHeight = pMetric->tmHeight-pMetric->tmInternalLeading; + } + pData->meFamily = ImplFamilyToSal( pLogFont->lfPitchAndFamily ); + pData->meCharSet = ImplCharSetToSal( pLogFont->lfCharSet ); + pData->meWidthType = WIDTH_DONTKNOW; + pData->meWeight = ImplWeightToSal( pLogFont->lfWeight ); + pData->meItalic = (pLogFont->lfItalic) ? ITALIC_NORMAL : ITALIC_NONE; + pData->mePitch = ImplLogPitchToSal( pLogFont->lfPitchAndFamily ); + if ( pMetric->tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) ) + pData->meType = TYPE_SCALABLE; + else + pData->meType = TYPE_RASTER; + pData->mbOrientation = (nFontType & RASTER_FONTTYPE) == 0; + pData->mbDevice = (pMetric->tmPitchAndFamily & TMPF_DEVICE) != 0; + pData->mnQuality = 0; +} + +// ----------------------------------------------------------------------- + +void ImplSalLogFontToFontA( const LOGFONTA& rLogFont, Font& rFont ) +{ + XubString aFontName( ImplSalGetUniString( rLogFont.lfFaceName ) ); + if ( aFontName.Len() ) + { + rFont.SetName( aFontName ); + long nFontHeight = rLogFont.lfHeight; + if ( nFontHeight < 0 ) + nFontHeight = -nFontHeight; + HDC hDC = GetDC( 0 ); + long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY ); + ReleaseDC( 0, hDC ); + nFontHeight *= 72; + nFontHeight += nDPIY/2; + nFontHeight /= nDPIY; + rFont.SetSize( Size( 0, nFontHeight ) ); + rFont.SetOrientation( (short)rLogFont.lfEscapement ); + rFont.SetCharSet( ImplCharSetToSal( rLogFont.lfCharSet ) ); + rFont.SetFamily( ImplFamilyToSal( rLogFont.lfPitchAndFamily ) ); + rFont.SetPitch( ImplLogPitchToSal( rLogFont.lfPitchAndFamily ) ); + rFont.SetWeight( ImplWeightToSal( rLogFont.lfWeight ) ); + if ( rLogFont.lfItalic ) + rFont.SetItalic( ITALIC_NORMAL ); + else + rFont.SetItalic( ITALIC_NONE ); + if ( rLogFont.lfUnderline ) + rFont.SetUnderline( UNDERLINE_SINGLE ); + else + rFont.SetUnderline( UNDERLINE_NONE ); + if ( rLogFont.lfStrikeOut ) + rFont.SetStrikeout( STRIKEOUT_SINGLE ); + else + rFont.SetStrikeout( STRIKEOUT_NONE ); + } +} + +// ----------------------------------------------------------------------- + +void ImplSalLogFontToFontW( const LOGFONTW& rLogFont, Font& rFont ) +{ + XubString aFontName( rLogFont.lfFaceName ); + if ( aFontName.Len() ) + { + rFont.SetName( aFontName ); + long nFontHeight = rLogFont.lfHeight; + if ( nFontHeight < 0 ) + nFontHeight = -nFontHeight; + HDC hDC = GetDC( 0 ); + long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY ); + ReleaseDC( 0, hDC ); + nFontHeight *= 72; + nFontHeight += nDPIY/2; + nFontHeight /= nDPIY; + rFont.SetSize( Size( 0, nFontHeight ) ); + rFont.SetOrientation( (short)rLogFont.lfEscapement ); + rFont.SetCharSet( ImplCharSetToSal( rLogFont.lfCharSet ) ); + rFont.SetFamily( ImplFamilyToSal( rLogFont.lfPitchAndFamily ) ); + rFont.SetPitch( ImplLogPitchToSal( rLogFont.lfPitchAndFamily ) ); + rFont.SetWeight( ImplWeightToSal( rLogFont.lfWeight ) ); + if ( rLogFont.lfItalic ) + rFont.SetItalic( ITALIC_NORMAL ); + else + rFont.SetItalic( ITALIC_NONE ); + if ( rLogFont.lfUnderline ) + rFont.SetUnderline( UNDERLINE_SINGLE ); + else + rFont.SetUnderline( UNDERLINE_NONE ); + if ( rLogFont.lfStrikeOut ) + rFont.SetStrikeout( STRIKEOUT_SINGLE ); + else + rFont.SetStrikeout( STRIKEOUT_NONE ); + } +} + +// ======================================================================= + +void SalGraphics::SetTextColor( SalColor nSalColor ) +{ + COLORREF aCol = PALETTERGB( SALCOLOR_RED( nSalColor ), + SALCOLOR_GREEN( nSalColor ), + SALCOLOR_BLUE( nSalColor ) ); + + if( !maGraphicsData.mbPrinter && + GetSalData()->mhDitherPal && + ImplIsSysColorEntry( nSalColor ) ) + { + aCol = PALRGB_TO_RGB( aCol ); + } + + ::SetTextColor( maGraphicsData.mhDC, aCol ); +} + +// ----------------------------------------------------------------------- + +USHORT SalGraphics::SetFont( ImplFontSelectData* pFont ) +{ + HFONT hNewFont; + if ( aSalShlData.mbWNT ) + { + LOGFONTW aLogFont; + UniString aName; + if ( pFont->mpFontData ) + aName = pFont->mpFontData->maName; + else + aName = pFont->maName.GetToken( 0 ); + + UINT nNameLen = aName.Len(); + if ( nNameLen > (sizeof( aLogFont.lfFaceName )/sizeof( wchar_t ))-1 ) + nNameLen = (sizeof( aLogFont.lfFaceName )/sizeof( wchar_t ))-1; + memcpy( aLogFont.lfFaceName, aName.GetBuffer(), nNameLen*sizeof( wchar_t ) ); + aLogFont.lfFaceName[nNameLen] = 0; + if ( pFont->mpFontData && + ((pFont->meCharSet == RTL_TEXTENCODING_DONTKNOW) || + ((WIN_BYTE)(pFont->mpFontData->mpSysData) == OEM_CHARSET)) ) + aLogFont.lfCharSet = (WIN_BYTE)(pFont->mpFontData->mpSysData); + else + aLogFont.lfCharSet = ImplCharSetToWin( pFont->meCharSet ); + aLogFont.lfPitchAndFamily = ImplPitchToWin( pFont->mePitch ); + aLogFont.lfPitchAndFamily |= ImplFamilyToWin( pFont->meFamily ); + aLogFont.lfWeight = ImplWeightToWin( pFont->meWeight ); + aLogFont.lfHeight = (int)-pFont->mnHeight; + aLogFont.lfWidth = (int)pFont->mnWidth; + aLogFont.lfUnderline = 0; + aLogFont.lfStrikeOut = 0; + aLogFont.lfItalic = (pFont->meItalic) != ITALIC_NONE; + aLogFont.lfEscapement = pFont->mnOrientation; + aLogFont.lfOrientation = 0; + aLogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; + aLogFont.lfQuality = DEFAULT_QUALITY; + if ( pFont->mnOrientation ) + { + aLogFont.lfOutPrecision = OUT_TT_PRECIS; + aLogFont.lfClipPrecision |= CLIP_LH_ANGLES; + } + else + aLogFont.lfOutPrecision = OUT_DEFAULT_PRECIS; + + // Auf dem Bildschirm nehmen wir Courier New, wenn Courier nicht + // skalierbar ist und wenn der Font skaliert oder rotiert werden + // muss + if ( maGraphicsData.mbScreen && + (pFont->mnWidth || pFont->mnOrientation || + !pFont->mpFontData || (pFont->mpFontData->mnHeight != pFont->mnHeight)) && + !bImplSalCourierScalable && bImplSalCourierNew && + (ImplSalWICompareAscii( aLogFont.lfFaceName, "Courier" ) == 0) ) + lstrcpyW( aLogFont.lfFaceName, L"Courier New" ); + + hNewFont = CreateFontIndirectW( &aLogFont ); + } + else + { + if ( !maGraphicsData.mpLogFont ) + maGraphicsData.mpLogFont = new LOGFONTA; + + ByteString aName; + if ( pFont->mpFontData ) + aName = ImplSalGetWinAnsiString( pFont->mpFontData->maName ); + else + aName = ImplSalGetWinAnsiString( pFont->maName.GetToken( 0 ) ); + UINT nNameLen = aName.Len(); + if ( nNameLen > sizeof( maGraphicsData.mpLogFont->lfFaceName )-1 ) + nNameLen = sizeof( maGraphicsData.mpLogFont->lfFaceName )-1; + memcpy( maGraphicsData.mpLogFont->lfFaceName, aName.GetBuffer(), nNameLen ); + maGraphicsData.mpLogFont->lfFaceName[nNameLen] = 0; + if ( pFont->mpFontData && + ((pFont->meCharSet == RTL_TEXTENCODING_DONTKNOW) || + ((WIN_BYTE)(pFont->mpFontData->mpSysData) == OEM_CHARSET)) ) + maGraphicsData.mpLogFont->lfCharSet = (WIN_BYTE)(pFont->mpFontData->mpSysData); + else + maGraphicsData.mpLogFont->lfCharSet = ImplCharSetToWin( pFont->meCharSet ); + maGraphicsData.mpLogFont->lfPitchAndFamily = ImplPitchToWin( pFont->mePitch ); + maGraphicsData.mpLogFont->lfPitchAndFamily |= ImplFamilyToWin( pFont->meFamily ); + maGraphicsData.mpLogFont->lfWeight = ImplWeightToWin( pFont->meWeight ); + maGraphicsData.mpLogFont->lfHeight = (int)-pFont->mnHeight; + maGraphicsData.mpLogFont->lfWidth = (int)pFont->mnWidth; + maGraphicsData.mpLogFont->lfUnderline = 0; + maGraphicsData.mpLogFont->lfStrikeOut = 0; + maGraphicsData.mpLogFont->lfItalic = (pFont->meItalic) != ITALIC_NONE; + maGraphicsData.mpLogFont->lfEscapement = pFont->mnOrientation; + maGraphicsData.mpLogFont->lfOrientation = 0; + maGraphicsData.mpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS; + maGraphicsData.mpLogFont->lfQuality = DEFAULT_QUALITY; + if ( pFont->mnOrientation ) + { + maGraphicsData.mpLogFont->lfOutPrecision = OUT_TT_PRECIS; + maGraphicsData.mpLogFont->lfClipPrecision |= CLIP_LH_ANGLES; + } + else + maGraphicsData.mpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS; + + // Auf dem Bildschirm nehmen wir Courier New, wenn Courier nicht + // skalierbar ist und wenn der Font skaliert oder rotiert werden + // muss + if ( maGraphicsData.mbScreen && + (pFont->mnWidth || pFont->mnOrientation || + !pFont->mpFontData || (pFont->mpFontData->mnHeight != pFont->mnHeight)) && + !bImplSalCourierScalable && bImplSalCourierNew && + (stricmp( maGraphicsData.mpLogFont->lfFaceName, "Courier" ) == 0) ) + strcpy( maGraphicsData.mpLogFont->lfFaceName, "Courier New" ); + + hNewFont = CreateFontIndirectA( maGraphicsData.mpLogFont ); + } + + HFONT hOldFont = SelectFont( maGraphicsData.mhDC, hNewFont ); + + // destory or save old font + if ( maGraphicsData.mhFont ) + DeleteFont( maGraphicsData.mhFont ); + else + maGraphicsData.mhDefFont = hOldFont; + + // set new data + maGraphicsData.mhFont = hNewFont; + maGraphicsData.mbCalcOverhang = TRUE; + + maGraphicsData.mnFontCharSetCount = 0; + maGraphicsData.mbFontKernInit = TRUE; + if ( maGraphicsData.mpFontKernPairs ) + { + delete maGraphicsData.mpFontKernPairs; + maGraphicsData.mpFontKernPairs = 0; + } + maGraphicsData.mnFontKernPairCount = 0; + + // Auf dem Printer immer mit DrawTextArray arbeiten, da dort die + // Zeichenbreiten genauer als Pixel sein koennen + if ( maGraphicsData.mbPrinter ) + return SAL_SETFONT_USEDRAWTEXTARRAY; + else + return 0; +} + +// ----------------------------------------------------------------------- + +long SalGraphics::GetCharWidth( sal_Unicode nChar1, sal_Unicode nChar2, long* pWidthAry ) +{ + SIZE aExtent; + SIZE aExtent2; + sal_Unicode nCharCount = nChar2-nChar1+1; + sal_Unicode i; + int* pWinWidthAry = (int*)pWidthAry; + DBG_ASSERT( sizeof( int ) == sizeof( long ), "SalGraphics::GetCharWidth(): int != long" ); + + // Da nicht bei allen Treibern diese Funktion funktioniert + if ( !GetCharWidthW( maGraphicsData.mhDC, nChar1, nChar2, pWinWidthAry ) ) + { + for ( i = 0; i < nCharCount; i++ ) + { + WCHAR c =i+nChar1; + if ( !GetTextExtentPointW( maGraphicsData.mhDC, &c, 1, &aExtent ) ) + pWinWidthAry[i] = 0; + else + pWinWidthAry[i] = aExtent.cx; + } + } + + // Ueberhang abziehen + if ( maGraphicsData.mbCalcOverhang ) + { + WCHAR aAA[2] = { 'A', 'A' }; + if ( GetTextExtentPointW( maGraphicsData.mhDC, aAA, 2, &aExtent ) && + GetTextExtentPointW( maGraphicsData.mhDC, aAA, 1, &aExtent2 ) ) + { + maGraphicsData.mbCalcOverhang = FALSE; + maGraphicsData.mnFontOverhang = (aExtent2.cx*2)-aExtent.cx; + } + + int nOverhang = maGraphicsData.mnFontOverhang; + if ( nOverhang ) + { + for ( i = 0; i < nCharCount; i++ ) + pWinWidthAry[i] -= nOverhang; + } + } + + return 1; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::GetFontMetric( ImplFontMetricData* pMetric ) +{ + if ( aSalShlData.mbWNT ) + { + wchar_t aFaceName[LF_FACESIZE+60]; + GetTextFaceW( maGraphicsData.mhDC, sizeof( aFaceName ), aFaceName ); + pMetric->maName = aFaceName; + + TEXTMETRICW aWinMetric; + GetTextMetricsW( maGraphicsData.mhDC, &aWinMetric ); + + pMetric->mnWidth = aWinMetric.tmAveCharWidth; + pMetric->meFamily = ImplFamilyToSal( aWinMetric.tmPitchAndFamily );; + pMetric->meCharSet = ImplCharSetToSal( aWinMetric.tmCharSet ); + pMetric->meWeight = ImplWeightToSal( aWinMetric.tmWeight ); + pMetric->mePitch = ImplMetricPitchToSal( aWinMetric.tmPitchAndFamily ); + if ( aWinMetric.tmItalic ) + pMetric->meItalic = ITALIC_NORMAL; + else + pMetric->meItalic = ITALIC_NONE; + if ( aWinMetric.tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) ) + pMetric->meType = TYPE_SCALABLE; + else + { + pMetric->meType = TYPE_RASTER; + pMetric->mnOrientation = 0; + } + pMetric->mbDevice = (aWinMetric.tmPitchAndFamily & TMPF_DEVICE) != 0; + pMetric->mnAscent = aWinMetric.tmAscent; + pMetric->mnDescent = aWinMetric.tmDescent; + pMetric->mnLeading = aWinMetric.tmInternalLeading; + pMetric->mnSlant = 0; + pMetric->mnFirstChar = 0; + pMetric->mnLastChar = 0xFF; + } + else + { + char aFaceName[LF_FACESIZE+60]; + GetTextFaceA( maGraphicsData.mhDC, sizeof( aFaceName ), aFaceName ); + pMetric->maName = ImplSalGetUniString( aFaceName ); + + TEXTMETRICA aWinMetric; + GetTextMetricsA( maGraphicsData.mhDC, &aWinMetric ); + + pMetric->mnWidth = aWinMetric.tmAveCharWidth; + pMetric->meFamily = ImplFamilyToSal( aWinMetric.tmPitchAndFamily );; + pMetric->meCharSet = ImplCharSetToSal( aWinMetric.tmCharSet ); + pMetric->meWeight = ImplWeightToSal( aWinMetric.tmWeight ); + pMetric->mePitch = ImplMetricPitchToSal( aWinMetric.tmPitchAndFamily ); + if ( aWinMetric.tmItalic ) + pMetric->meItalic = ITALIC_NORMAL; + else + pMetric->meItalic = ITALIC_NONE; + if ( aWinMetric.tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) ) + pMetric->meType = TYPE_SCALABLE; + else + { + pMetric->meType = TYPE_RASTER; + pMetric->mnOrientation = 0; + } + pMetric->mbDevice = (aWinMetric.tmPitchAndFamily & TMPF_DEVICE) != 0; + pMetric->mnAscent = aWinMetric.tmAscent; + pMetric->mnDescent = aWinMetric.tmDescent; + pMetric->mnLeading = aWinMetric.tmInternalLeading; + pMetric->mnSlant = 0; + pMetric->mnFirstChar = 0; + pMetric->mnLastChar = 0xFF; + } +} + +// ----------------------------------------------------------------------- + +int CALLBACK SalEnumCharSetsProcExA( const ENUMLOGFONTEXA* pLogFont, + const NEWTEXTMETRICEXA* pMetric, + DWORD nFontType, LPARAM lParam ) +{ + SalGraphicsData* pData = (SalGraphicsData*)lParam; + // Charset already in the list? + for ( BYTE i = 0; i < pData->mnFontCharSetCount; i++ ) + { + if ( pData->mpFontCharSets[i] == pLogFont->elfLogFont.lfCharSet ) + return 1; + } + pData->mpFontCharSets[pData->mnFontCharSetCount] = pLogFont->elfLogFont.lfCharSet; + pData->mnFontCharSetCount++; + return 1; +} + +// ----------------------------------------------------------------------- + +static void ImplGetAllFontCharSets( SalGraphicsData* pData ) +{ + if ( !pData->mpFontCharSets ) + pData->mpFontCharSets = new BYTE[256]; + + LOGFONTA aLogFont; + memset( &aLogFont, 0, sizeof( aLogFont ) ); + aLogFont.lfCharSet = DEFAULT_CHARSET; + GetTextFace( pData->mhDC, sizeof( aLogFont.lfFaceName ), aLogFont.lfFaceName ); + EnumFontFamiliesExA( pData->mhDC, &aLogFont, (FONTENUMPROCA)SalEnumCharSetsProcExA, + (LPARAM)(void*)pData, 0 ); +} + +// ----------------------------------------------------------------------- + +static void ImplAddKerningPairs( SalGraphicsData* pData ) +{ + ULONG nPairs = ::GetKerningPairsA( pData->mhDC, 0, NULL ); + if ( !nPairs ) + return; + + CHARSETINFO aInfo; + if ( !TranslateCharsetInfo( (DWORD*)(ULONG)GetTextCharset( pData->mhDC ), &aInfo, TCI_SRCCHARSET ) ) + return; + + if ( !pData->mpFontKernPairs ) + pData->mpFontKernPairs = new KERNINGPAIR[nPairs]; + else + { + KERNINGPAIR* pOldPairs = pData->mpFontKernPairs; + pData->mpFontKernPairs = new KERNINGPAIR[nPairs+pData->mnFontKernPairCount]; + memcpy( pData->mpFontKernPairs, pOldPairs, + pData->mnFontKernPairCount*sizeof( KERNINGPAIR ) ); + delete pOldPairs; + } + + UINT nCP = aInfo.ciACP; + ULONG nOldPairs = pData->mnFontKernPairCount; + KERNINGPAIR* pTempPair = pData->mpFontKernPairs+pData->mnFontKernPairCount; + nPairs = ::GetKerningPairsA( pData->mhDC, nPairs, pTempPair ); + for ( ULONG i = 0; i < nPairs; i++ ) + { + unsigned char aBuf[2]; + wchar_t nChar; + int nLen; + BOOL bAdd = TRUE; + + // None-ASCII?, then we must convert the char + if ( (pTempPair->wFirst > 125) || (pTempPair->wFirst == 92) ) + { + if ( pTempPair->wFirst < 256 ) + { + aBuf[0] = (unsigned char)pTempPair->wFirst; + nLen = 1; + } + else + { + aBuf[0] = (unsigned char)(pTempPair->wFirst >> 8); + aBuf[1] = (unsigned char)(pTempPair->wFirst & 0xFF); + nLen = 2; + } + if ( MultiByteToWideChar( nCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS, + (const char*)aBuf, nLen, &nChar, 1 ) ) + pTempPair->wFirst = nChar; + else + bAdd = FALSE; + } + if ( (pTempPair->wSecond > 125) || (pTempPair->wSecond == 92) ) + { + if ( pTempPair->wSecond < 256 ) + { + aBuf[0] = (unsigned char)pTempPair->wSecond; + nLen = 1; + } + else + { + aBuf[0] = (unsigned char)(pTempPair->wSecond >> 8); + aBuf[1] = (unsigned char)(pTempPair->wSecond & 0xFF); + nLen = 2; + } + if ( MultiByteToWideChar( nCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS, + (const char*)aBuf, nLen, &nChar, 1 ) ) + pTempPair->wSecond = nChar; + else + bAdd = FALSE; + } + + KERNINGPAIR* pTempPair2 = pData->mpFontKernPairs; + for ( ULONG j = 0; j < nOldPairs; j++ ) + { + if ( (pTempPair2->wFirst == pTempPair->wFirst) && + (pTempPair2->wSecond == pTempPair->wSecond) ) + { + bAdd = FALSE; + break; + } + pTempPair2++; + } + + if ( bAdd ) + { + KERNINGPAIR* pDestPair = pData->mpFontKernPairs+pData->mnFontKernPairCount; + if ( pDestPair != pTempPair ) + memcpy( pDestPair, pTempPair, sizeof( KERNINGPAIR ) ); + pData->mnFontKernPairCount++; + } + + pTempPair++; + } +} + +// ----------------------------------------------------------------------- + +ULONG SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs ) +{ + DBG_ASSERT( sizeof( KERNINGPAIR ) == sizeof( ImplKernPairData ), + "SalGraphics::GetKernPairs(): KERNINGPAIR != ImplKernPairData" ); + + if ( aSalShlData.mbWNT ) + { + if ( !pKernPairs ) + return ::GetKerningPairsW( maGraphicsData.mhDC, 0, NULL ); + else + return ::GetKerningPairsW( maGraphicsData.mhDC, nPairs, (KERNINGPAIR*)pKernPairs ); + } + else + { + if ( maGraphicsData.mbFontKernInit ) + { + if ( maGraphicsData.mpFontKernPairs ) + { + delete maGraphicsData.mpFontKernPairs; + maGraphicsData.mpFontKernPairs = 0; + } + maGraphicsData.mnFontKernPairCount = 0; + + if ( !maGraphicsData.mnFontCharSetCount ) + ImplGetAllFontCharSets( &maGraphicsData ); + + if ( maGraphicsData.mnFontCharSetCount <= 1 ) + ImplAddKerningPairs( &maGraphicsData ); + else + { + // Query All Kerning Pairs from all possible CharSets + for ( BYTE i = 0; i < maGraphicsData.mnFontCharSetCount; i++ ) + { + maGraphicsData.mpLogFont->lfCharSet = maGraphicsData.mpFontCharSets[i]; + HFONT hNewFont = CreateFontIndirectA( maGraphicsData.mpLogFont ); + HFONT hOldFont = SelectFont( maGraphicsData.mhDC, hNewFont ); + ImplAddKerningPairs( &maGraphicsData ); + SelectFont( maGraphicsData.mhDC, hOldFont ); + DeleteFont( hNewFont ); + } + } + + maGraphicsData.mbFontKernInit = FALSE; + } + + if ( !pKernPairs ) + return maGraphicsData.mnFontKernPairCount; + else + { + if ( nPairs > maGraphicsData.mnFontKernPairCount ) + nPairs = maGraphicsData.mnFontKernPairCount; + memcpy( pKernPairs, maGraphicsData.mpFontKernPairs, + nPairs*sizeof( ImplKernPairData ) ); + return nPairs; + } + } +} + +// ----------------------------------------------------------------------- + +int CALLBACK SalEnumFontsProcExA( const ENUMLOGFONTEXA* pLogFont, + const NEWTEXTMETRICEXA* pMetric, + DWORD nFontType, LPARAM lParam ) +{ + ImplEnumInfo* pInfo = (ImplEnumInfo*)(void*)lParam; + if ( !pInfo->mpName ) + { + // Ignore vertical fonts + if ( pLogFont->elfLogFont.lfFaceName[0] != '@' ) + { + if ( !pInfo->mbImplSalCourierNew ) + pInfo->mbImplSalCourierNew = stricmp( pLogFont->elfLogFont.lfFaceName, "Courier New" ) == 0; + if ( !pInfo->mbImplSalCourierScalable ) + pInfo->mbCourier = stricmp( pLogFont->elfLogFont.lfFaceName, "Courier" ) == 0; + else + pInfo->mbCourier = FALSE; + XubString aName( ImplSalGetUniString( pLogFont->elfLogFont.lfFaceName ) ); + pInfo->mpName = &aName; + strcpy( pInfo->mpLogFontA->lfFaceName, pLogFont->elfLogFont.lfFaceName ); + pInfo->mpLogFontA->lfCharSet = pLogFont->elfLogFont.lfCharSet; + EnumFontFamiliesExA( pInfo->mhDC, pInfo->mpLogFontA, (FONTENUMPROCA)SalEnumFontsProcExA, + (LPARAM)(void*)pInfo, 0 ); + pInfo->mpLogFontA->lfFaceName[0] = '\0'; + pInfo->mpLogFontA->lfCharSet = DEFAULT_CHARSET; + pInfo->mpName = NULL; + pInfo->mbCourier = FALSE; + } + } + else + { + ImplFontData* pData = new ImplFontData; + pData->maName = *(pInfo->mpName); + + ImplLogMetricToDevFontDataA( &(pLogFont->elfLogFont), &(pMetric->ntmTm), nFontType, pData ); + // StyleName nur bei TrueType uebernehmen, da sonst bei 3.1 Mist drinsteht + if ( pMetric->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE ) + pData->maStyleName = ImplSalGetUniString( (const char*)pLogFont->elfStyle ); + pData->mpSysData = (void*)(pLogFont->elfLogFont.lfCharSet); + BOOL bAdd = TRUE; + + // Wenn es sich um einen nicht skalierbaren Bildschirm-Font + // handelt, dann auf dem Drucker ignorieren + if ( pData->meType != TYPE_SCALABLE ) + { + if ( pInfo->mbPrinter ) + bAdd = pData->mbDevice; + } + else + { + // Feststellen, ob Courier skalierbar ist + if ( pInfo->mbCourier ) + pInfo->mbImplSalCourierScalable = TRUE; + } + + if ( bAdd ) + pInfo->mpList->Add( pData ); + else + delete pData; + } + + return 1; +} + +// ----------------------------------------------------------------------- + +int CALLBACK SalEnumFontsProcExW( const ENUMLOGFONTEXW* pLogFont, + const NEWTEXTMETRICEXW* pMetric, + DWORD nFontType, LPARAM lParam ) +{ + ImplEnumInfo* pInfo = (ImplEnumInfo*)(void*)lParam; + if ( !pInfo->mpName ) + { + // Ignore vertical fonts + if ( pLogFont->elfLogFont.lfFaceName[0] != '@' ) + { + if ( !pInfo->mbImplSalCourierNew ) + pInfo->mbImplSalCourierNew = ImplSalWICompareAscii( pLogFont->elfLogFont.lfFaceName, "Courier New" ) == 0; + if ( !pInfo->mbImplSalCourierScalable ) + pInfo->mbCourier = ImplSalWICompareAscii( pLogFont->elfLogFont.lfFaceName, "Courier" ) == 0; + else + pInfo->mbCourier = FALSE; + XubString aName( pLogFont->elfLogFont.lfFaceName ); + pInfo->mpName = &aName; + memcpy( pInfo->mpLogFontW->lfFaceName, pLogFont->elfLogFont.lfFaceName, (aName.Len()+1)*sizeof( wchar_t ) ); + pInfo->mpLogFontW->lfCharSet = pLogFont->elfLogFont.lfCharSet; + EnumFontFamiliesExW( pInfo->mhDC, pInfo->mpLogFontW, (FONTENUMPROCW)SalEnumFontsProcExW, + (LPARAM)(void*)pInfo, 0 ); + pInfo->mpLogFontW->lfFaceName[0] = '\0'; + pInfo->mpLogFontW->lfCharSet = DEFAULT_CHARSET; + pInfo->mpName = NULL; + pInfo->mbCourier = FALSE; + } + } + else + { + ImplFontData* pData = new ImplFontData; + pData->maName = *(pInfo->mpName); + + ImplLogMetricToDevFontDataW( &(pLogFont->elfLogFont), &(pMetric->ntmTm), nFontType, pData ); + // StyleName nur bei TrueType uebernehmen, da sonst bei 3.1 Mist drinsteht + if ( pMetric->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE ) + pData->maStyleName = pLogFont->elfStyle; + pData->mpSysData = (void*)(pLogFont->elfLogFont.lfCharSet); + BOOL bAdd = TRUE; + + // Wenn es sich um einen nicht skalierbaren Bildschirm-Font + // handelt, dann auf dem Drucker ignorieren + if ( pData->meType != TYPE_SCALABLE ) + { + if ( pInfo->mbPrinter ) + bAdd = pData->mbDevice; + } + else + { + // Feststellen, ob Courier skalierbar ist + if ( pInfo->mbCourier ) + pInfo->mbImplSalCourierScalable = TRUE; + } + + if ( bAdd ) + pInfo->mpList->Add( pData ); + else + delete pData; + } + + return 1; +} + +// ----------------------------------------------------------------------- + +void SalGraphics::GetDevFontList( ImplDevFontList* pList ) +{ + ImplEnumInfo aInfo; + aInfo.mhDC = maGraphicsData.mhDC; + aInfo.mpList = pList; + aInfo.mpName = NULL; + aInfo.mpLogFontA = NULL; + aInfo.mpLogFontW = NULL; + aInfo.mbCourier = FALSE; + if ( !maGraphicsData.mbPrinter ) + { + aInfo.mbImplSalCourierScalable = FALSE; + aInfo.mbImplSalCourierNew = FALSE; + aInfo.mbPrinter = FALSE; + } + else + { + aInfo.mbImplSalCourierScalable = TRUE; + aInfo.mbImplSalCourierNew = TRUE; + aInfo.mbPrinter = TRUE; + } + + if ( aSalShlData.mbWNT ) + { + LOGFONTW aLogFont; + memset( &aLogFont, 0, sizeof( aLogFont ) ); + aLogFont.lfCharSet = DEFAULT_CHARSET; + aInfo.mpLogFontW = &aLogFont; + EnumFontFamiliesExW( maGraphicsData.mhDC, &aLogFont, (FONTENUMPROCW)SalEnumFontsProcExW, + (LPARAM)(void*)&aInfo, 0 ); + } + else + { + LOGFONTA aLogFont; + memset( &aLogFont, 0, sizeof( aLogFont ) ); + aLogFont.lfCharSet = DEFAULT_CHARSET; + aInfo.mpLogFontA = &aLogFont; + EnumFontFamiliesExA( maGraphicsData.mhDC, &aLogFont, (FONTENUMPROCA)SalEnumFontsProcExA, + (LPARAM)(void*)&aInfo, 0 ); + } + + // Feststellen, was es fuer Courier-Schriften auf dem Bildschirm gibt, + // um in SetFont() evt. Courier auf Courier New zu mappen + if ( !maGraphicsData.mbPrinter ) + { + bImplSalCourierScalable = aInfo.mbImplSalCourierScalable; + bImplSalCourierNew = aInfo.mbImplSalCourierNew; + } +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawText( long nX, long nY, + const xub_Unicode* pStr, xub_StrLen nLen ) +{ + DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalGraphics::DrawText(): WCHAR != sal_Unicode" ); + + ::ExtTextOutW( maGraphicsData.mhDC, (int)nX, (int)nY, + 0, NULL, pStr, nLen, NULL ); +} + +// ----------------------------------------------------------------------- + +void SalGraphics::DrawTextArray( long nX, long nY, + const xub_Unicode* pStr, xub_StrLen nLen, + const long* pDXAry ) +{ + DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalGraphics::DrawText(): WCHAR != sal_Unicode" ); + + if ( nLen < 2 ) + ::ExtTextOutW( maGraphicsData.mhDC, (int)nX, (int)nY, 0, NULL, pStr, nLen, NULL ); + else + { + int aStackAry[SAL_DRAWTEXT_STACKBUF]; + int* pWinDXAry; + + if ( nLen <= SAL_DRAWTEXT_STACKBUF ) + pWinDXAry = aStackAry; + else + pWinDXAry = new int[nLen]; + + pWinDXAry[0] = (int)pDXAry[0]; + for ( xub_StrLen i = 1; i < nLen-1; i++ ) + pWinDXAry[i] = (int)pDXAry[i]-pDXAry[i-1]; + + // Breite vom letzten Zeichen ermitteln, da wir dieses auch + // beim Windows-XArray in der richtigen Breite reingeben + // muessen, um nicht auf Probleme bei einigen + // Grafikkarten oder Druckertreibern zu stossen + SIZE aExtent; + if ( GetTextExtentPointW( maGraphicsData.mhDC, pStr+nLen-1, 1, &aExtent ) ) + pWinDXAry[nLen-1] = aExtent.cx; + else + pWinDXAry[nLen-1] = 4095; + + // Text ausgeben + ::ExtTextOutW( maGraphicsData.mhDC, (int)nX, (int)nY, 0, NULL, pStr, nLen, pWinDXAry ); + + if ( pWinDXAry != aStackAry ) + delete pWinDXAry; + } +} + +// ----------------------------------------------------------------------- + +static ULONG ImplIncreaseArrays( ULONG nSize, SalPoint** ppPoints, BYTE** ppFlags, ULONG nIncSize ) +{ + const ULONG nOldSize = nSize; + SalPoint* pNewPoints = new SalPoint[ nSize += nIncSize ]; + BYTE* pNewFlags = new BYTE[ nSize ]; + + if( *ppPoints ) + { + memcpy( pNewPoints, *ppPoints, nOldSize * sizeof( SalPoint ) ); + memset( pNewPoints + nOldSize, 0, nIncSize * sizeof( SalPoint ) ); + delete[] *ppPoints; + } + else + memset( pNewPoints, 0, nSize * sizeof( SalPoint ) ); + + if( *ppFlags ) + { + memcpy( pNewFlags, *ppFlags, nOldSize ); + memset( pNewFlags + nOldSize, 0, nIncSize ); + delete[] *ppFlags; + } + else + memset( pNewFlags, 0, nSize ); + + *ppPoints = pNewPoints; + *ppFlags = pNewFlags; + + return nSize; +} + +// ----------------------------------------------------------------------- + +static void ImplGetFamilyAndAscents( HDC hDC, BYTE& rPitch, long& rAscent ) +{ + rPitch = 0; + rAscent = 0; + + if ( aSalShlData.mbWNT ) + { + TEXTMETRICW aTextMetricW; + if ( GetTextMetricsW( hDC, &aTextMetricW ) ) + { + rPitch = aTextMetricW.tmPitchAndFamily; + rAscent = aTextMetricW.tmAscent; + } + } + else + { + TEXTMETRICA aTextMetricA; + if ( GetTextMetricsA( hDC, &aTextMetricA ) ) + { + rPitch = aTextMetricA.tmPitchAndFamily; + rAscent = aTextMetricA.tmAscent; + } + } +} + +// ----------------------------------------------------------------------- + +static BOOL ImplGetGlyphChar( SalGraphicsData* pData, sal_Unicode c, + WORD& rByteChar, HFONT& rOldFont ) +{ + rOldFont = 0; + + if ( !pData->mnFontCharSetCount ) + ImplGetAllFontCharSets( pData ); + + // Try at first the current charset + CHARSETINFO aInfo; + char aDestBuf[2]; + int nLen = 0; + WIN_BOOL bDefault; + if ( TranslateCharsetInfo( (DWORD*)(ULONG)GetTextCharset( pData->mhDC ), &aInfo, TCI_SRCCHARSET ) ) + { + bDefault = FALSE; + nLen = WideCharToMultiByte( aInfo.ciACP, + WC_COMPOSITECHECK | WC_DISCARDNS | WC_DEFAULTCHAR, + &c, 1, + aDestBuf, sizeof( aDestBuf ), + NULL, &bDefault ); + } + + // Try all possible charsets + if ( (nLen != 1) || bDefault ) + { + // Query All Kerning Pairs from all possible CharSets + for ( BYTE i = 0; i < pData->mnFontCharSetCount; i++ ) + { + if ( TranslateCharsetInfo( (DWORD*)(ULONG)pData->mpFontCharSets[i], &aInfo, TCI_SRCCHARSET ) ) + { + bDefault = FALSE; + nLen = WideCharToMultiByte( aInfo.ciACP, + WC_COMPOSITECHECK | WC_DISCARDNS | WC_DEFAULTCHAR, + &c, 1, + aDestBuf, sizeof( aDestBuf ), + NULL, &bDefault ); + if ( (nLen == 1) && !bDefault ) + { + pData->mpLogFont->lfCharSet = pData->mpFontCharSets[i]; + HFONT hNewFont = CreateFontIndirectA( pData->mpLogFont ); + rOldFont = SelectFont( pData->mhDC, hNewFont ); + break; + } + } + } + } + + // GetGlyphOutline() only works for characters < 256. For all characters + // greater than 256 we use the default mechanismn in VCL to scan + // the printed Glyph + if ( (nLen == 1) && !bDefault ) + { + rByteChar = (unsigned char)aDestBuf[0]; + return TRUE; + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL SalGraphics::GetGlyphBoundRect( xub_Unicode cChar, long* pX, long* pY, + long* pWidth, long* pHeight ) +{ + HDC hDC = maGraphicsData.mhDC; + BYTE nPitchAndFamily; + long nAscent; + + ImplGetFamilyAndAscents( hDC, nPitchAndFamily, nAscent ); + if ( !(nPitchAndFamily & TMPF_TRUETYPE) ) + return FALSE; + + GLYPHMETRICS aGlyphMetrics; + MAT2 aMat; + DWORD nSize; + BOOL bOK; + HFONT hOldFont = 0; + + // Einheitsmatrix erzeugen + aMat.eM11 = FixedFromDouble(1.); + aMat.eM12 = FixedFromDouble(0.); + aMat.eM21 = FixedFromDouble(0.); + aMat.eM22 = FixedFromDouble(1.); + if ( aSalShlData.mbWNT ) + nSize = ::GetGlyphOutlineW( hDC, cChar, GGO_METRICS, &aGlyphMetrics, 0, NULL, &aMat ); + else + { + WORD nChar; + if ( ImplGetGlyphChar( &maGraphicsData, cChar, nChar, hOldFont ) ) + nSize = ::GetGlyphOutlineA( hDC, nChar, GGO_METRICS, &aGlyphMetrics, 0, NULL, &aMat ); + else + nSize = 0; + } + bOK = (nSize != GDI_ERROR) && nSize; + if ( bOK ) + { + *pX = aGlyphMetrics.gmptGlyphOrigin.x; + *pY = nAscent - aGlyphMetrics.gmptGlyphOrigin.y; + *pWidth = aGlyphMetrics.gmBlackBoxX; + *pHeight = aGlyphMetrics.gmBlackBoxY; + } + + if ( hOldFont ) + { + HFONT hNewFont = SelectFont( maGraphicsData.mhDC, hOldFont ); + DeleteFont( hNewFont ); + } + + return bOK; +} + +// ----------------------------------------------------------------------- + +ULONG SalGraphics::GetGlyphOutline( xub_Unicode cChar, USHORT** ppPolySizes, + SalPoint** ppPoints, BYTE** ppFlags ) +{ + HDC hDC = maGraphicsData.mhDC; + BYTE nPitchAndFamily; + long nAscent; + + ImplGetFamilyAndAscents( hDC, nPitchAndFamily, nAscent ); + if ( !(nPitchAndFamily & TMPF_TRUETYPE) ) + return 0; + + GLYPHMETRICS aGlyphMetrics; + MAT2 aMat; + DWORD nSize; + USHORT nChar = cChar; + HFONT hOldFont = 0; + ULONG nPolyCount = 0; + + // Einheitsmatrix erzeugen + aMat.eM11 = FixedFromDouble(1.); + aMat.eM12 = FixedFromDouble(0.); + aMat.eM21 = FixedFromDouble(0.); + aMat.eM22 = FixedFromDouble(1.); + + if ( aSalShlData.mbWNT ) + nSize = ::GetGlyphOutlineW( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, 0, NULL, &aMat ); + else + { + if ( ImplGetGlyphChar( &maGraphicsData, cChar, nChar, hOldFont ) ) + nSize = ::GetGlyphOutlineA( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, 0, NULL, &aMat ); + else + nSize = 0; + } + + if ( (nSize != GDI_ERROR) && nSize ) + { + BYTE* pData = new BYTE[ nSize ]; + ULONG nTotalCount = 0; + DWORD nSize2; + if ( aSalShlData.mbWNT ) + nSize2 = ::GetGlyphOutlineW( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, nSize, pData, &aMat ); + else + nSize2 = ::GetGlyphOutlineA( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, nSize, pData, &aMat ); + if ( nSize == nSize2 ) + { + ULONG nPtSize = GLYPH_INC; + SalPoint* pPoints = new SalPoint[ GLYPH_INC ]; + SalPoint* pTotalPoints = NULL; + BYTE* pFlags = new BYTE[ GLYPH_INC ]; + BYTE* pTotalFlags = NULL; + TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pData; + TTPOLYCURVE* pCurve; + *ppPolySizes = new USHORT[ MAX_POLYCOUNT ]; + memset( *ppPolySizes, 0, MAX_POLYCOUNT * sizeof( USHORT ) ); + + while ( ((BYTE*)pHeader < pData+nSize) && (nPolyCount < (MAX_POLYCOUNT - 1)) ) + { + if ( pHeader->dwType == TT_POLYGON_TYPE ) + { + USHORT nPnt = 0; + USHORT i; + + memset( pPoints, 0, nPtSize * sizeof( SalPoint ) ); + memset( pFlags, 0, nPtSize ); + + // ersten Startpunkt holen; die folgenden Startpunkte sind + // die Endpunkte der vorhergehenden Kurven + pPoints[ nPnt ].mnX = IntFromFixed( pHeader->pfxStart.x ); + pPoints[ nPnt++ ].mnY = IntFromFixed( pHeader->pfxStart.y ); + + pCurve = (TTPOLYCURVE*) ( pHeader + 1 ); + + while ( (BYTE*)pCurve < (BYTE*)pHeader+pHeader->cb ) + { + if ( TT_PRIM_LINE == pCurve->wType ) + { + for( i = 0; i < pCurve->cpfx; i++ ) + { + CHECKPOINTS( nPnt ); + pPoints[ nPnt ].mnX = IntFromFixed( pCurve->apfx[ i ].x ); + pPoints[ nPnt++ ].mnY = IntFromFixed( pCurve->apfx[ i ].y ); + } + } + else if ( pCurve->wType == TT_PRIM_QSPLINE ) + { + for ( i = 0; i < pCurve->cpfx; ) + { + // Punkt B, der Kontrollpunkt der Kurve + CHECKPOINTS( nPnt ); + pPoints[ nPnt ].mnX = IntFromFixed( pCurve->apfx[ i ].x ); + pPoints[ nPnt ].mnY = IntFromFixed( pCurve->apfx[ i++ ].y ); + + // Punkt verdoppeln fuer Bezier-Wandlung + CHECKPOINTS( nPnt + 1UL ); + pPoints[ nPnt + 1 ] = pPoints[ nPnt ]; + nPnt += 2; + + // Endpunkt der Kurve bestimmen + if ( i == (pCurve->cpfx - 1) ) + { + // entweder letzter Punkt + CHECKPOINTS( nPnt ); + pPoints[ nPnt ].mnX = IntFromFixed( pCurve->apfx[ i ].x ); + pPoints[ nPnt++].mnY = IntFromFixed( pCurve->apfx[ i++ ].y ); + } + else + { + // oder die Mitte zwischen den Kontrollpunkten + // dieser und der naechsten Kurce + CHECKPOINTS( nPnt ); + pPoints[ nPnt ].mnX = IntFromFixed( fxDiv2( pCurve->apfx[ i - 1 ].x, + pCurve->apfx[ i ].x ) ); + pPoints[ nPnt++ ].mnY = IntFromFixed( fxDiv2( pCurve->apfx[ i - 1 ].y, + pCurve->apfx[ i ].y ) ); + } + + // Umrechnung in Bezier ( PQ = TrueType-Controlpunkt): + // P1 = 1/3 * (P0 + 2 * PQ) / P2 = 1/3 * (P3 + 2 * PQ) + pPoints[ nPnt - 3 ].mnX = ( pPoints[ nPnt - 4 ].mnX + + ( pPoints[ nPnt - 3 ].mnX << 1 ) ) / 3; + pPoints[ nPnt - 3 ].mnY = ( pPoints[ nPnt - 4 ].mnY + + ( pPoints[ nPnt - 3 ].mnY << 1 ) ) / 3; + + pPoints[ nPnt - 2 ].mnX = ( pPoints[ nPnt - 1 ].mnX + + ( pPoints[ nPnt - 2 ].mnX << 1 ) ) / 3; + pPoints[ nPnt - 2 ].mnY = ( pPoints[ nPnt - 1 ].mnY + + ( pPoints[ nPnt - 2 ].mnY << 1 ) ) / 3; + + pFlags[ nPnt - 3 ] = pFlags[ nPnt - 2 ] = 2; + } + } + + // weiter mit naechstem Kurvensegment + pCurve = (TTPOLYCURVE*) &pCurve->apfx[ i ]; + } + + CHECKPOINTS( nPnt ); + pPoints[nPnt++] = pPoints[0]; + + if ( nPnt ) + { + (*ppPolySizes)[ nPolyCount++ ] = nPnt; + ImplIncreaseArrays( nTotalCount, &pTotalPoints, &pTotalFlags, nPnt ); + + // Polygon senkrecht kippen: TrueType-Y-Koordinaten verlaufen von unten nach oben + for ( i = 0; i < nPnt; i++ ) + { + pTotalPoints[ nTotalCount ].mnX = pPoints[i].mnX; + pTotalPoints[ nTotalCount ].mnY = nAscent - pPoints[i].mnY; + pTotalFlags[ nTotalCount++ ] = pFlags[i]; + } + } + + // naechstes Polygon + pHeader = (TTPOLYGONHEADER*) ( (BYTE*) pHeader + pHeader->cb ); + } + } + + delete[] pPoints; + delete[] pFlags; + + if ( !nPolyCount ) + { + delete[] pTotalPoints; + *ppPoints = NULL; + delete[] pTotalFlags; + *ppFlags = NULL; + delete[] *ppPolySizes; + *ppPolySizes = NULL; + } + else + { + *ppPoints = pTotalPoints; + *ppFlags = pTotalFlags; + } + } + + delete [] pData; + } + + if ( hOldFont ) + { + HFONT hNewFont = SelectFont( maGraphicsData.mhDC, hOldFont ); + DeleteFont( hNewFont ); + } + + return nPolyCount; +} diff --git a/vcl/win/source/gdi/salogl.cxx b/vcl/win/source/gdi/salogl.cxx new file mode 100644 index 000000000000..bdd5ccee00e8 --- /dev/null +++ b/vcl/win/source/gdi/salogl.cxx @@ -0,0 +1,329 @@ +/************************************************************************* + * + * $RCSfile: salogl.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALOGL_CXX + +#ifndef _SV_SALOGL_HXX +#include <salogl.hxx> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif + +// ------------------------------- +// - Additional typedefs for init. +// ------------------------------- + +typedef HGLRC ( *OGLFncCreateContext )( HDC hDC ); +typedef BOOL ( *OGLFncDeleteContext )( HGLRC hContext ); +typedef HGLRC ( *OGLFncGetCurrentContext )( VOID ); +typedef void ( *OGLFncMakeCurrent )( HDC hDC, HGLRC hContext ); + +// ------------ +// - Lib-Name - +// ------------ + +#define OGL_LIBNAME "OPENGL32.DLL" + +// ---------- +// - Macros - +// ---------- + +#define INIT_OGLFNC_WGL( FncName ) static OGLFnc##FncName pImplOpenWGLFnc##FncName = NULL; +#define GET_OGLFNC_WGL( FncName ) \ +pImplOpenWGLFnc##FncName = (OGLFnc##FncName##) GetProcAddress( hImplOGLLib, "wgl" #FncName ); \ +if( !pImplOpenWGLFnc##FncName ) bRet = FALSE; + +// ----------------- +// - Statics init. - +// ----------------- + +// Members +static HINSTANCE hImplOGLLib; +HGLRC SalOpenGL::mhOGLContext = 0; +HDC SalOpenGL::mhOGLLastDC = 0; +ULONG SalOpenGL::mnOGLState = OGL_STATE_UNLOADED; + +INIT_OGLFNC_WGL( CreateContext ); +INIT_OGLFNC_WGL( DeleteContext ); +INIT_OGLFNC_WGL( GetCurrentContext ); +INIT_OGLFNC_WGL( MakeCurrent ); + +// ----------- +// - WndProc - +// ----------- + +LRESULT CALLBACK OpenGLWndProc( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 ) +{ + return DefWindowProc( hWnd, nMsg, nPar1, nPar2 ); +} + +// ------------- +// - SalOpenGL - +// ------------- + +SalOpenGL::SalOpenGL( SalGraphics* pGraphics ) +{ + // Set mhOGLLastDC only the first time a + // SalOpenGL object is created; we need + // this DC in SalOpenGL::Create(); + if ( OGL_STATE_UNLOADED == mnOGLState ) + mhOGLLastDC = pGraphics->maGraphicsData.mhDC; +} + +// ------------------------------------------------------------------------ + +SalOpenGL::~SalOpenGL() +{ +} + +// ------------------------------------------------------------------------ + +BOOL SalOpenGL::Create() +{ + BOOL bRet = FALSE; + + if ( OGL_STATE_UNLOADED == mnOGLState ) + { + if( ImplInitLib() ) + { + USHORT nBitCount = GetDeviceCaps( mhOGLLastDC, BITSPIXEL ); + PIXELFORMATDESCRIPTOR pfd = + { + sizeof( PIXELFORMATDESCRIPTOR ), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL, + PFD_TYPE_RGBA, + (BYTE) nBitCount, + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 16, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + const int nIndex = ChoosePixelFormat( mhOGLLastDC, &pfd ); + + if( nIndex && SetPixelFormat( mhOGLLastDC, nIndex, &pfd ) ) + { + if ( (nBitCount > 8) && ImplInit() && + (mhOGLContext = pImplOpenWGLFncCreateContext( mhOGLLastDC )) != 0 ) + { + WNDCLASS aWc; + HWND hDummyWnd; + + SaveDC( mhOGLLastDC ); + SelectClipRgn( mhOGLLastDC, NULL ); + pImplOpenWGLFncMakeCurrent( mhOGLLastDC, mhOGLContext ); + RestoreDC( mhOGLLastDC, -1 ); + mnOGLState = OGL_STATE_VALID; + bRet = TRUE; + + memset( &aWc, 0, sizeof( aWc ) ); + aWc.hInstance = GetModuleHandle( NULL ); + aWc.lpfnWndProc = OpenGLWndProc; + aWc.lpszClassName = "OpenGLWnd"; + RegisterClass( &aWc ); + hDummyWnd = CreateWindow( aWc.lpszClassName, NULL, WS_OVERLAPPED, 0, -50, 1, 1, HWND_DESKTOP, NULL, aWc.hInstance, 0 ); + ShowWindow( hDummyWnd, SW_SHOW ); + DestroyWindow( hDummyWnd ); + UnregisterClass( aWc.lpszClassName, aWc.hInstance ); + } + else + { + ImplFreeLib(); + mnOGLState = OGL_STATE_INVALID; + } + } + else + mnOGLState = OGL_STATE_INVALID; + } + else + mnOGLState = OGL_STATE_INVALID; + } + else if( OGL_STATE_VALID == mnOGLState ) + bRet = TRUE; + + return bRet; +} + +// ------------------------------------------------------------------------ + +void SalOpenGL::Release() +{ + ImplFreeLib(); +} + +// ------------------------------------------------------------------------ + +void* SalOpenGL::GetOGLFnc( const char* pFncName ) +{ + if ( hImplOGLLib ) + return (void*)GetProcAddress( hImplOGLLib, pFncName ); + else + return NULL; +} + +// ------------------------------------------------------------------------ + +typedef BOOL (WINAPI *MyFuncType)(HDC, HGLRC); + +void SalOpenGL::OGLEntry( SalGraphics* pGraphics ) +{ + if ( pGraphics->maGraphicsData.mhDC != mhOGLLastDC ) + { + PIXELFORMATDESCRIPTOR pfd = + { + sizeof( PIXELFORMATDESCRIPTOR ), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL, + PFD_TYPE_RGBA, + GetDeviceCaps( pGraphics->maGraphicsData.mhDC, BITSPIXEL ), + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 16, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + const int nIndex = ChoosePixelFormat( pGraphics->maGraphicsData.mhDC, &pfd ); + if ( nIndex && SetPixelFormat( pGraphics->maGraphicsData.mhDC, nIndex, &pfd ) ) + { + WNDCLASS aWc; + HWND hDummyWnd; + + pImplOpenWGLFncDeleteContext( mhOGLContext ); + mhOGLLastDC = pGraphics->maGraphicsData.mhDC; + mhOGLContext = pImplOpenWGLFncCreateContext( mhOGLLastDC ); + + SaveDC( mhOGLLastDC ); + SelectClipRgn( mhOGLLastDC, NULL ); + pImplOpenWGLFncMakeCurrent( mhOGLLastDC, mhOGLContext ); + RestoreDC( mhOGLLastDC, -1 ); + + memset( &aWc, 0, sizeof( aWc ) ); + aWc.hInstance = GetModuleHandle( NULL ); + aWc.lpfnWndProc = OpenGLWndProc; + aWc.lpszClassName = "OpenGLWnd"; + RegisterClass( &aWc ); + hDummyWnd = CreateWindow( aWc.lpszClassName, NULL, WS_OVERLAPPED, 0, -50, 1, 1, HWND_DESKTOP, NULL, aWc.hInstance, 0 ); + ShowWindow( hDummyWnd, SW_SHOW ); + DestroyWindow( hDummyWnd ); + UnregisterClass( aWc.lpszClassName, aWc.hInstance ); + } + } +} + +// ------------------------------------------------------------------------ + +void SalOpenGL::OGLExit( SalGraphics* pGraphics ) +{ +} + +// ------------------------------------------------------------------------ + +BOOL SalOpenGL::ImplInitLib() +{ + return ((hImplOGLLib = LoadLibrary( OGL_LIBNAME )) != NULL); +} + +// ------------------------------------------------------------------------ + +void SalOpenGL::ImplFreeLib() +{ + if ( hImplOGLLib ) + { + FreeLibrary( hImplOGLLib ); + hImplOGLLib = NULL; + mnOGLState = OGL_STATE_UNLOADED; + } +} + +// ------------------------------------------------------------------------ + +BOOL SalOpenGL::ImplInit() +{ + BOOL bRet = TRUE; + + // Internal use + GET_OGLFNC_WGL( CreateContext ); + GET_OGLFNC_WGL( DeleteContext ); + GET_OGLFNC_WGL( GetCurrentContext ); + GET_OGLFNC_WGL( MakeCurrent ); + + return bRet; +} diff --git a/vcl/win/source/gdi/salprn.cxx b/vcl/win/source/gdi/salprn.cxx new file mode 100644 index 000000000000..e4ac38538b51 --- /dev/null +++ b/vcl/win/source/gdi/salprn.cxx @@ -0,0 +1,1424 @@ +/************************************************************************* + * + * $RCSfile: salprn.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALPRN_CXX + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALINST_HXX +#include <salinst.hxx> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif +#ifndef _SV_SALPTYPE_HXX +#include <salptype.hxx> +#endif +#ifndef _SV_SALPRN_HXX +#include <salprn.hxx> +#endif + +#ifndef _NEW_HXX +#include <tools/new.hxx> +#endif + +#ifndef _SV_PRINT_H +#include <print.h> +#endif +#ifndef _SV_JOBSET_H +#include <jobset.h> +#endif + +// ======================================================================= + +static char aImplWindows[] = "windows"; +static char aImplDevices[] = "devices"; +static char aImplDevice[] = "device"; + +// ======================================================================= + +static ULONG ImplWinQueueStatusToSal( DWORD nWinStatus ) +{ + ULONG nStatus = 0; + if ( nWinStatus & PRINTER_STATUS_PAUSED ) + nStatus |= QUEUE_STATUS_PAUSED; + if ( nWinStatus & PRINTER_STATUS_ERROR ) + nStatus |= QUEUE_STATUS_ERROR; + if ( nWinStatus & PRINTER_STATUS_PENDING_DELETION ) + nStatus |= QUEUE_STATUS_PENDING_DELETION; + if ( nWinStatus & PRINTER_STATUS_PAPER_JAM ) + nStatus |= QUEUE_STATUS_PAPER_JAM; + if ( nWinStatus & PRINTER_STATUS_PAPER_OUT ) + nStatus |= QUEUE_STATUS_PAPER_OUT; + if ( nWinStatus & PRINTER_STATUS_MANUAL_FEED ) + nStatus |= QUEUE_STATUS_MANUAL_FEED; + if ( nWinStatus & PRINTER_STATUS_PAPER_PROBLEM ) + nStatus |= QUEUE_STATUS_PAPER_PROBLEM; + if ( nWinStatus & PRINTER_STATUS_OFFLINE ) + nStatus |= QUEUE_STATUS_OFFLINE; + if ( nWinStatus & PRINTER_STATUS_IO_ACTIVE ) + nStatus |= QUEUE_STATUS_IO_ACTIVE; + if ( nWinStatus & PRINTER_STATUS_BUSY ) + nStatus |= QUEUE_STATUS_BUSY; + if ( nWinStatus & PRINTER_STATUS_PRINTING ) + nStatus |= QUEUE_STATUS_PRINTING; + if ( nWinStatus & PRINTER_STATUS_OUTPUT_BIN_FULL ) + nStatus |= QUEUE_STATUS_OUTPUT_BIN_FULL; + if ( nWinStatus & PRINTER_STATUS_WAITING ) + nStatus |= QUEUE_STATUS_WAITING; + if ( nWinStatus & PRINTER_STATUS_PROCESSING ) + nStatus |= QUEUE_STATUS_PROCESSING; + if ( nWinStatus & PRINTER_STATUS_INITIALIZING ) + nStatus |= QUEUE_STATUS_INITIALIZING; + if ( nWinStatus & PRINTER_STATUS_WARMING_UP ) + nStatus |= QUEUE_STATUS_WARMING_UP; + if ( nWinStatus & PRINTER_STATUS_TONER_LOW ) + nStatus |= QUEUE_STATUS_TONER_LOW; + if ( nWinStatus & PRINTER_STATUS_NO_TONER ) + nStatus |= QUEUE_STATUS_NO_TONER; + if ( nWinStatus & PRINTER_STATUS_PAGE_PUNT ) + nStatus |= QUEUE_STATUS_PAGE_PUNT; + if ( nWinStatus & PRINTER_STATUS_USER_INTERVENTION ) + nStatus |= QUEUE_STATUS_USER_INTERVENTION; + if ( nWinStatus & PRINTER_STATUS_OUT_OF_MEMORY ) + nStatus |= QUEUE_STATUS_OUT_OF_MEMORY; + if ( nWinStatus & PRINTER_STATUS_DOOR_OPEN ) + nStatus |= QUEUE_STATUS_DOOR_OPEN; + if ( nWinStatus & PRINTER_STATUS_SERVER_UNKNOWN ) + nStatus |= QUEUE_STATUS_SERVER_UNKNOWN; + if ( nWinStatus & PRINTER_STATUS_POWER_SAVE ) + nStatus |= QUEUE_STATUS_POWER_SAVE; + if ( !nStatus && !(nWinStatus & PRINTER_STATUS_NOT_AVAILABLE) ) + nStatus |= QUEUE_STATUS_READY; + return nStatus; +} + +// ----------------------------------------------------------------------- + +void SalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList ) +{ +// !!! UNICODE - NT Optimierung !!! + DWORD i; + DWORD n; + DWORD nBytes = 0; +// DWORD nInfoRet; + DWORD nInfoPrn2; + BOOL bFound = FALSE; + PRINTER_INFO_2* pWinInfo2 = NULL; + PRINTER_INFO_2* pGetInfo2; + EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoPrn2 ); + if ( nBytes ) + { + pWinInfo2 = (PRINTER_INFO_2*)new BYTE[nBytes]; + if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoPrn2 ) ) + { + pGetInfo2 = pWinInfo2; + for ( i = 0; i < nInfoPrn2; i++ ) + { + SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo; + pInfo->maPrinterName = ImplSalGetUniString( pGetInfo2->pPrinterName ); + pInfo->maDriver = ImplSalGetUniString( pGetInfo2->pDriverName ); + XubString aPortName; + if ( pGetInfo2->pPortName ) + aPortName = ImplSalGetUniString( pGetInfo2->pPortName ); + // pLocation can be 0 (the Windows docu doesn't describe this) + if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) ) + pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation ); + else + pInfo->maLocation = aPortName; + // pComment can be 0 (the Windows docu doesn't describe this) + if ( pGetInfo2->pComment ) + pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment ); + pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status ); + pInfo->mnJobs = pGetInfo2->cJobs; + pInfo->mpSysData = new XubString( aPortName ); + pList->Add( pInfo ); + pGetInfo2++; + } + + bFound = TRUE; + } + } + +/* Siehe Kommentar unten !!! + EnumPrinters( PRINTER_ENUM_NETWORK | PRINTER_ENUM_REMOTE, NULL, 1, NULL, 0, &nBytes, &nInfoRet ); + if ( nBytes ) + { + PRINTER_INFO_1* pWinInfo1 = (PRINTER_INFO_1*)new BYTE[nBytes]; + if ( EnumPrinters( PRINTER_ENUM_NETWORK | PRINTER_ENUM_REMOTE, NULL, 1, (LPBYTE)pWinInfo1, nBytes, &nBytes, &nInfoRet ) ) + { + PRINTER_INFO_1* pGetInfo1 = pWinInfo1; + for ( i = 0; i < nInfoRet; i++ ) + { + // Feststellen, ob Printer durch erste Abfrage schon gefunden + // wurde + BOOL bAdd = TRUE; + if ( pWinInfo2 ) + { + pGetInfo2 = pWinInfo2; + for ( n = 0; n < nInfoPrn2; n++ ) + { + if ( strcmp( pGetInfo1->pName, pGetInfo2->pPrinterName ) == 0 ) + { + bAdd = FALSE; + break; + } + pGetInfo2++; + } + } + // Wenn neuer Printer, dann aufnehmen + if ( bAdd ) + { + SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo; + XubString aPrnName( pGetInfo1->pName ); + pInfo->maPrinterName = aPrnName; + pInfo->maDriver = "winspool"; + pInfo->maComment = pGetInfo1->pComment; + pInfo->mnStatus = 0; + pInfo->mnJobs = QUEUE_JOBS_DONTKNOW; + pInfo->mpSysData = new String(); + pList->Add( pInfo ); + } + pGetInfo1++; + } + + bFound = TRUE; + } + + delete pWinInfo1; + } +*/ + +// if ( bFound ) +// return; + +// !!! UNICODE - NT Optimierung !!! + // Drucker aus WIN.INI lesen + UINT nSize = 4096; + char* pBuf = new char[nSize]; + UINT nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize ); + while ( nRead >= nSize-2 ) + { + nSize += 2048; + delete pBuf; + pBuf = new char[nSize]; + nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize ); + } + + // Druckernamen aus Buffer extrahieren und Liste aufbauen + char* pName = pBuf; + while ( *pName ) + { + char* pPortName; + char* pTmp; + char aPortBuf[256]; + GetProfileStringA( aImplDevices, pName, "", aPortBuf, sizeof( aPortBuf ) ); + + pPortName = aPortBuf; + + // Namen anlegen + xub_StrLen nNameLen = strlen( pName ); + XubString aName( ImplSalGetUniString( pName, nNameLen ) ); + + // Treibernamen rausfischen + pTmp = pPortName; + while ( *pTmp != ',' ) + pTmp++; + XubString aDriver( ImplSalGetUniString( pPortName, (USHORT)(pTmp-pPortName) ) ); + pPortName = pTmp; + + // Alle Portnamen raussuchen + do + { + pPortName++; + pTmp = pPortName; + while ( *pTmp && (*pTmp != ',') ) + pTmp++; + + String aPortName( ImplSalGetUniString( pPortName, (USHORT)(pTmp-pPortName) ) ); + + // Neuen Eintrag anlegen + // !!! Da ich zu bloeb bin, die Netzwerk-Printer zur 5.0 + // !!! richtig zu integrieren, gehen wir zusaetzlich + // !!! noch ueber das W16-Interface, da uns dort die + // !!! Drucker noch einfach und schnell geliefert werden + // !!! ohne das wir jetzt zu grossen Aufwand treiben muessen. + // !!! Somit sollten wir dann jedenfalls nicht schlechter sein + // !!! als in einer 4.0 SP2. + // Feststellen, ob Printer durch erste Abfrage schon gefunden + // wurde + BOOL bAdd = TRUE; + if ( pWinInfo2 ) + { + pGetInfo2 = pWinInfo2; + for ( n = 0; n < nInfoPrn2; n++ ) + { + if ( aName.EqualsIgnoreCaseAscii( pGetInfo2->pPrinterName ) ) + { + bAdd = FALSE; + break; + } + pGetInfo2++; + } + } + // Wenn neuer Printer, dann aufnehmen + if ( bAdd ) + { + SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo; + pInfo->maPrinterName = aName; + pInfo->maDriver = aDriver; + pInfo->maLocation = aPortName; + pInfo->mnStatus = 0; + pInfo->mnJobs = QUEUE_JOBS_DONTKNOW; + pInfo->mpSysData = new XubString( aPortName ); + pList->Add( pInfo ); + } + } + while ( *pTmp == ',' ); + + pName += nNameLen + 1; + } + + delete pBuf; + delete pWinInfo2; +} + +// ----------------------------------------------------------------------- + +void SalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo ) +{ +// !!! UNICODE - NT Optimierung !!! + DWORD nBytes = 0; + DWORD nInfoRet; + PRINTER_INFO_2* pWinInfo2; + EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoRet ); + if ( nBytes ) + { + pWinInfo2 = (PRINTER_INFO_2*)new BYTE[nBytes]; + if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoRet ) ) + { + PRINTER_INFO_2* pGetInfo2 = pWinInfo2; + for ( DWORD i = 0; i < nInfoRet; i++ ) + { + if ( pInfo->maPrinterName.EqualsAscii( pGetInfo2->pPrinterName ) && + pInfo->maDriver.EqualsAscii( pGetInfo2->pDriverName ) ) + { + if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) ) + pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation ); + else + pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pPortName ); + pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status ); + pInfo->mnJobs = pGetInfo2->cJobs; + break; + } + + pGetInfo2++; + } + } + + delete pWinInfo2; + } +} + +// ----------------------------------------------------------------------- + +void SalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) +{ + delete (String*)(pInfo->mpSysData); + delete pInfo; +} + +// ----------------------------------------------------------------------- + +// !!! UNICODE - NT Optimierung !!! +XubString SalInstance::GetDefaultPrinter() +{ + // Default-Printer-String aus win.ini holen + char szBuffer[256]; + GetProfileStringA( aImplWindows, aImplDevice, "", szBuffer, sizeof( szBuffer ) ); + if ( szBuffer[0] ) + { + // Printername suchen + char* pBuf = szBuffer; + char* pTmp = pBuf; + while ( *pTmp && (*pTmp != ',') ) + pTmp++; + return ImplSalGetUniString( pBuf, (xub_StrLen)(pTmp-pBuf) ); + } + else + return XubString(); +} + +// ======================================================================= + +static DWORD ImplDeviceCaps( SalInfoPrinter* pPrinter, WORD nCaps, + LPTSTR pOutput, const ImplJobSetup* pSetupData ) +{ + DEVMODE* pDevMode; + if ( !pSetupData || !pSetupData->mpDriverData ) + pDevMode = NULL; + else + pDevMode = SAL_DEVMODE( pSetupData ); + +// !!! UNICODE - NT Optimierung !!! + return DeviceCapabilitiesA( ImplSalGetWinAnsiString( pPrinter->maPrinterData.maDeviceName, TRUE ).GetBuffer(), + ImplSalGetWinAnsiString( pPrinter->maPrinterData.maPortName, TRUE ).GetBuffer(), + nCaps, (LPSTR)pOutput, pDevMode ); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplTestSalJobSetup( SalInfoPrinter* pPrinter, + ImplJobSetup* pSetupData, BOOL bDelete ) +{ + if ( pSetupData && pSetupData->mpDriverData ) + { + // Signature und Groesse muss uebereinstimmen, damit wir keine + // JobSetup's von anderen Systemen setzen + if ( (pSetupData->mnSystem == JOBSETUP_SYSTEM_WINDOWS) && + (pSetupData->mnDriverDataLen > sizeof( SalDriverData )) && + (((SalDriverData*)(pSetupData->mpDriverData))->mnSysSignature == SAL_DRIVERDATA_SYSSIGN) ) + return TRUE; + else if ( bDelete ) + { + delete pSetupData->mpDriverData; + pSetupData->mpDriverData = NULL; + pSetupData->mnDriverDataLen = 0; + } + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplUpdateSalJobSetup( SalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, + BOOL bIn, SalFrame* pVisibleDlgParent ) +{ + HANDLE hPrn; +// !!! UNICODE - NT Optimierung !!! + if ( !OpenPrinterA( (LPSTR)ImplSalGetWinAnsiString( pPrinter->maPrinterData.maDeviceName, TRUE ).GetBuffer(), &hPrn, NULL ) ) + return FALSE; + + LONG nRet; + LONG nSysJobSize; + HWND hWnd = 0; + DWORD nMode = DM_OUT_BUFFER; + ULONG nDriverDataLen = 0; + SalDriverData* pOutBuffer = NULL; + DEVMODE* pInDevBuffer = NULL; + DEVMODE* pOutDevBuffer = NULL; + +// !!! UNICODE - NT Optimierung !!! + nSysJobSize = DocumentPropertiesA( hWnd, hPrn, + (LPSTR)ImplSalGetWinAnsiString( pPrinter->maPrinterData.maDeviceName, TRUE ).GetBuffer(), + NULL, NULL, 0 ); + if ( nSysJobSize < 0 ) + { + ClosePrinter( hPrn ); + return FALSE; + } + + // Outputbuffer anlegen + nDriverDataLen = sizeof(SalDriverData)+nSysJobSize-1; + pOutBuffer = (SalDriverData*)SvMemAlloc( nDriverDataLen ); + memset( pOutBuffer, 0, nDriverDataLen ); + pOutDevBuffer = (LPDEVMODE)(pOutBuffer->maDriverData); + pOutBuffer->mnSysSignature = SAL_DRIVERDATA_SYSSIGN; + pOutBuffer->mnVersion = SAL_DRIVERDATA_VERSION; + pOutBuffer->mnDriverOffset = (USHORT)(((SalDriverData*)NULL)->maDriverData); + + // Testen, ob wir einen geeigneten Inputbuffer haben + if ( bIn && ImplTestSalJobSetup( pPrinter, pSetupData, FALSE ) ) + { + pInDevBuffer = SAL_DEVMODE( pSetupData ); + nMode |= DM_IN_BUFFER; + } + + // Testen, ob Dialog angezeigt werden soll + if ( pVisibleDlgParent ) + { + hWnd = pVisibleDlgParent->maFrameData.mhWnd; + nMode |= DM_IN_PROMPT; + } + +// !!! UNICODE - NT Optimierung !!! + // Release mutex, in the other case we don't get paints and so on + ULONG nMutexCount = ImplSalReleaseYieldMutex(); + nRet = DocumentPropertiesA( hWnd, hPrn, + (LPSTR)ImplSalGetWinAnsiString( pPrinter->maPrinterData.maDeviceName, TRUE ).GetBuffer(), + pOutDevBuffer, pInDevBuffer, nMode ); + ImplSalAcquireYieldMutex( nMutexCount ); + ClosePrinter( hPrn ); + + if ( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) ) + { + SvMemFree( pOutBuffer ); + return FALSE; + } + + // String-Buffer am Ende immer mit 0 initialisieren, damit + // die JobSetups nach Moeglichkeit bei memcmp immer + // identisch sind + if ( pOutDevBuffer->dmSize >= 32 ) + { + USHORT nLen = strlen( (const char*)pOutDevBuffer->dmDeviceName ); + if ( nLen < sizeof( pOutDevBuffer->dmDeviceName ) ) + memset( pOutDevBuffer->dmDeviceName+nLen, 0, sizeof( pOutDevBuffer->dmDeviceName )-nLen ); + } + if ( pOutDevBuffer->dmSize >= 102 ) + { + USHORT nLen = strlen( (const char*)pOutDevBuffer->dmFormName ); + if ( nLen < sizeof( pOutDevBuffer->dmFormName ) ) + memset( pOutDevBuffer->dmFormName+nLen, 0, sizeof( pOutDevBuffer->dmFormName )-nLen ); + } + + // Daten updaten + if ( pSetupData->mpDriverData ) + delete pSetupData->mpDriverData; + pSetupData->mnDriverDataLen = nDriverDataLen; + pSetupData->mpDriverData = (BYTE*)pOutBuffer; + pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +static void ImplDevModeToJobSetup( SalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, ULONG nFlags ) +{ + if ( !pSetupData || !pSetupData->mpDriverData ) + return; + + DEVMODE* pDevMode = SAL_DEVMODE( pSetupData ); + + // Orientation + if ( nFlags & SAL_JOBSET_ORIENTATION ) + { + if ( pDevMode->dmOrientation == DMORIENT_PORTRAIT ) + pSetupData->meOrientation = ORIENTATION_PORTRAIT; + else if ( pDevMode->dmOrientation == DMORIENT_LANDSCAPE ) + pSetupData->meOrientation = ORIENTATION_LANDSCAPE; + } + + // PaperBin + if ( nFlags & SAL_JOBSET_PAPERBIN ) + { + ULONG nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData ); + + if ( nCount && (nCount != ((ULONG)-1)) ) + { + WORD* pBins = new WORD[nCount]; + memset( (BYTE*)pBins, 0, nCount*sizeof(WORD) ); + ImplDeviceCaps( pPrinter, DC_BINS, (LPTSTR)pBins, pSetupData ); + pSetupData->mnPaperBin = 0; + + // search the right bin and assign index to mnPaperBin + for( ULONG i = 0; i < nCount; i++ ) + { + if( pDevMode->dmDefaultSource == pBins[ i ] ) + { + pSetupData->mnPaperBin = (USHORT)i; + break; + } + } + + delete[] pBins; + } + } + + // PaperSize + if ( nFlags & SAL_JOBSET_PAPERSIZE ) + { + pSetupData->mnPaperWidth = pDevMode->dmPaperWidth*10; + pSetupData->mnPaperHeight = pDevMode->dmPaperLength*10; + switch( pDevMode->dmPaperSize ) + { + case( DMPAPER_A3 ): + pSetupData->mePaperFormat = PAPER_A3; + break; + case( DMPAPER_A4 ): + pSetupData->mePaperFormat = PAPER_A4; + break; + case( DMPAPER_A5 ): + pSetupData->mePaperFormat = PAPER_A5; + break; + case( DMPAPER_B4 ): + pSetupData->mePaperFormat = PAPER_B4; + break; + case( DMPAPER_B5 ): + pSetupData->mePaperFormat = PAPER_B5; + break; + case( DMPAPER_LETTER ): + pSetupData->mePaperFormat = PAPER_LETTER; + break; + case( DMPAPER_LEGAL ): + pSetupData->mePaperFormat = PAPER_LEGAL; + break; + case( DMPAPER_TABLOID ): + pSetupData->mePaperFormat = PAPER_TABLOID; + break; + default: + pSetupData->mePaperFormat = PAPER_USER; + break; + } + } +} + +// ----------------------------------------------------------------------- + +static BOOL ImplPaperSizeEqual( short nPaperWidth1, short nPaperHeight1, + short nPaperWidth2, short nPaperHeight2 ) +{ + return (((nPaperWidth1 >= nPaperWidth2-1) && (nPaperWidth1 <= nPaperWidth2+1)) && + ((nPaperHeight1 >= nPaperHeight2-1) && (nPaperHeight1 <= nPaperHeight2+1))); +} + +// ----------------------------------------------------------------------- + +static void ImplJobSetupToDevMode( SalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, ULONG nFlags ) +{ + if ( !pSetupData || !pSetupData->mpDriverData ) + return; + + DEVMODE* pDevMode = SAL_DEVMODE( pSetupData ); + + // Orientation + if ( nFlags & SAL_JOBSET_ORIENTATION ) + { + pDevMode->dmFields |= DM_ORIENTATION; + if ( pSetupData->meOrientation == ORIENTATION_PORTRAIT ) + pDevMode->dmOrientation = DMORIENT_PORTRAIT; + else + pDevMode->dmOrientation = DMORIENT_LANDSCAPE; + } + + // PaperBin + if ( nFlags & SAL_JOBSET_PAPERBIN ) + { + ULONG nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData ); + + if ( nCount && (nCount != ((ULONG)-1)) ) + { + WORD* pBins = new WORD[nCount]; + memset( pBins, 0, nCount*sizeof(WORD) ); + ImplDeviceCaps( pPrinter, DC_BINS, (LPTSTR)pBins, pSetupData ); + pDevMode->dmFields |= DM_DEFAULTSOURCE; + pDevMode->dmDefaultSource = pBins[ pSetupData->mnPaperBin ]; + delete[] pBins; + } + } + + // PaperSize + if ( nFlags & SAL_JOBSET_PAPERSIZE ) + { + pDevMode->dmFields |= DM_PAPERSIZE; + pDevMode->dmPaperWidth = 0; + pDevMode->dmPaperLength = 0; + + switch( pDevMode->dmPaperSize ) + { + case( PAPER_A3 ): + pDevMode->dmPaperSize = DMPAPER_A3; + break; + case( PAPER_A4 ): + pDevMode->dmPaperSize = DMPAPER_A4; + break; + case( PAPER_A5 ): + pDevMode->dmPaperSize = DMPAPER_A5; + break; + case( PAPER_B4 ): + pDevMode->dmPaperSize = DMPAPER_B4; + break; + case( PAPER_B5 ): + pDevMode->dmPaperSize = DMPAPER_B5; + break; + case( PAPER_LETTER ): + pDevMode->dmPaperSize = DMPAPER_LETTER; + break; + case( PAPER_LEGAL ): + pDevMode->dmPaperSize = DMPAPER_LEGAL; + break; + case( PAPER_TABLOID ): + pDevMode->dmPaperSize = DMPAPER_TABLOID; + break; + default: + { + short nPaper = 0; + ULONG nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData ); + WORD* pPapers = NULL; + ULONG nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData ); + POINT* pPaperSizes = NULL; + if ( nPaperCount && (nPaperCount != ((ULONG)-1)) ) + { + pPapers = new WORD[nPaperCount]; + memset( pPapers, 0, nPaperCount*sizeof(WORD) ); + ImplDeviceCaps( pPrinter, DC_PAPERS, (LPTSTR)pPapers, pSetupData ); + } + if ( nPaperSizeCount && (nPaperSizeCount != ((ULONG)-1)) ) + { + pPaperSizes = new POINT[nPaperSizeCount]; + memset( pPaperSizes, 0, nPaperSizeCount*sizeof(POINT) ); + ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (LPTSTR)pPaperSizes, pSetupData ); + } + if ( (nPaperSizeCount == nPaperCount) && pPapers && pPaperSizes ) + { + // Alle Papierformate vergleichen und ein passendes + // raussuchen + for ( ULONG i = 0; i < nPaperCount; i++ ) + { + if ( ImplPaperSizeEqual( (short)(pSetupData->mnPaperWidth/10), + (short)(pSetupData->mnPaperHeight/10), + (short)pPaperSizes[i].x, + (short)pPaperSizes[i].y ) ) + { + nPaper = pPapers[i]; + break; + } + } + } + if ( pPapers ) + delete pPapers; + if ( pPaperSizes ) + delete pPaperSizes; + + if ( nPaper ) + pDevMode->dmPaperSize = nPaper; + else + { + pDevMode->dmFields |= DM_PAPERLENGTH | DM_PAPERWIDTH; + pDevMode->dmPaperSize = DMPAPER_USER; + pDevMode->dmPaperWidth = pSetupData->mnPaperWidth/10; + pDevMode->dmPaperLength = pSetupData->mnPaperHeight/10; + } + } + break; + } + } +} + +// ----------------------------------------------------------------------- + +static HDC ImplCreateSalPrnIC( SalInfoPrinter* pPrinter, ImplJobSetup* pSetupData ) +{ + LPDEVMODE pDevMode; + if ( pSetupData && pSetupData->mpDriverData ) + pDevMode = SAL_DEVMODE( pSetupData ); + else + pDevMode = NULL; +// !!! UNICODE - NT Optimierung !!! + HDC hDC = CreateICA( ImplSalGetWinAnsiString( pPrinter->maPrinterData.maDriverName, TRUE ).GetBuffer(), + ImplSalGetWinAnsiString( pPrinter->maPrinterData.maDeviceName, TRUE ).GetBuffer(), + 0, + (LPDEVMODE)pDevMode ); + return hDC; +} + +// ----------------------------------------------------------------------- + +static SalGraphics* ImplCreateSalPrnGraphics( HDC hDC ) +{ + SalGraphics* pGraphics = new SalGraphics; + pGraphics->maGraphicsData.mhDC = hDC; + pGraphics->maGraphicsData.mhWnd = 0; + pGraphics->maGraphicsData.mbPrinter = TRUE; + pGraphics->maGraphicsData.mbVirDev = FALSE; + pGraphics->maGraphicsData.mbWindow = FALSE; + pGraphics->maGraphicsData.mbScreen = FALSE; + ImplSalInitGraphics( &(pGraphics->maGraphicsData) ); + return pGraphics; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplUpdateSalPrnIC( SalInfoPrinter* pPrinter, ImplJobSetup* pSetupData ) +{ + HDC hNewDC = ImplCreateSalPrnIC( pPrinter, pSetupData ); + if ( !hNewDC ) + return FALSE; + + if ( pPrinter->maPrinterData.mpGraphics ) + { + ImplSalDeInitGraphics( &(pPrinter->maPrinterData.mpGraphics->maGraphicsData) ); + DeleteDC( pPrinter->maPrinterData.mpGraphics->maGraphicsData.mhDC ); + delete pPrinter->maPrinterData.mpGraphics; + } + + SalGraphics* pGraphics = ImplCreateSalPrnGraphics( hNewDC ); + pPrinter->maPrinterData.mhDC = hNewDC; + pPrinter->maPrinterData.mpGraphics = pGraphics; + + return TRUE; +} + +// ======================================================================= + +SalInfoPrinter* SalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, + ImplJobSetup* pSetupData ) +{ + SalInfoPrinter* pPrinter = new SalInfoPrinter; + pPrinter->maPrinterData.maDriverName = pQueueInfo->maDriver; + pPrinter->maPrinterData.maDeviceName = pQueueInfo->maPrinterName; + pPrinter->maPrinterData.maPortName = *(String*)(pQueueInfo->mpSysData); + + // Testen, ob Setupdaten zum Drucker gehoeren (erst aufrufen, nachdem + // die Member gesetzt sind, da diese in dieser Routine abgefragt werden) + ImplTestSalJobSetup( pPrinter, pSetupData, TRUE ); + + HDC hDC = ImplCreateSalPrnIC( pPrinter, pSetupData ); + if ( !hDC ) + { + delete pPrinter; + return NULL; + } + + SalGraphics* pGraphics = ImplCreateSalPrnGraphics( hDC ); + pPrinter->maPrinterData.mhDC = hDC; + pPrinter->maPrinterData.mpGraphics = pGraphics; + if ( !pSetupData->mpDriverData ) + ImplUpdateSalJobSetup( pPrinter, pSetupData, FALSE, NULL ); + ImplDevModeToJobSetup( pPrinter, pSetupData, SAL_JOBSET_ALL ); + pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS; + + return pPrinter; +} + +// ----------------------------------------------------------------------- + +void SalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) +{ + delete pPrinter; +} + +// ======================================================================= + +SalInfoPrinter::SalInfoPrinter() +{ + maPrinterData.mhDC = 0; + maPrinterData.mpGraphics = NULL; + maPrinterData.mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +SalInfoPrinter::~SalInfoPrinter() +{ + if ( maPrinterData.mpGraphics ) + { + ImplSalDeInitGraphics( &(maPrinterData.mpGraphics->maGraphicsData) ); + DeleteDC( maPrinterData.mpGraphics->maGraphicsData.mhDC ); + delete maPrinterData.mpGraphics; + } +} + +// ----------------------------------------------------------------------- + +SalGraphics* SalInfoPrinter::GetGraphics() +{ + if ( maPrinterData.mbGraphics ) + return NULL; + + if ( maPrinterData.mpGraphics ) + maPrinterData.mbGraphics = TRUE; + + return maPrinterData.mpGraphics; +} + +// ----------------------------------------------------------------------- + +void SalInfoPrinter::ReleaseGraphics( SalGraphics* ) +{ + maPrinterData.mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL SalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData ) +{ + if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, pFrame ) ) + { + ImplDevModeToJobSetup( this, pSetupData, SAL_JOBSET_ALL ); + return ImplUpdateSalPrnIC( this, pSetupData ); + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL SalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData ) +{ + if ( !ImplTestSalJobSetup( this, pSetupData, FALSE ) ) + return FALSE; + return ImplUpdateSalPrnIC( this, pSetupData ); +} + +// ----------------------------------------------------------------------- + +BOOL SalInfoPrinter::SetData( ULONG nFlags, ImplJobSetup* pSetupData ) +{ + ImplJobSetupToDevMode( this, pSetupData, nFlags ); + if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, NULL ) ) + { + ImplDevModeToJobSetup( this, pSetupData, nFlags ); + return ImplUpdateSalPrnIC( this, pSetupData ); + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +ULONG SalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pSetupData ) +{ + DWORD nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + return nRet; + else + return 0; +} + +// ----------------------------------------------------------------------- + +XubString SalInfoPrinter::GetPaperBinName( const ImplJobSetup* pSetupData, ULONG nPaperBin ) +{ +// !!! UNICODE - NT Optimierung !!! + XubString aPaperBinName; + + DWORD nBins = ImplDeviceCaps( this, DC_BINNAMES, NULL, pSetupData ); + if ( (nPaperBin < nBins) && (nBins != ((ULONG)-1)) ) + { + char* pBuffer = new char[nBins*24]; + DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, pBuffer, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + aPaperBinName = ImplSalGetUniString( (const char*)(pBuffer + (nPaperBin*24)) ); + delete pBuffer; + } + + return aPaperBinName; +} + +// ----------------------------------------------------------------------- + +ULONG SalInfoPrinter::GetCapabilities( const ImplJobSetup* pSetupData, USHORT nType ) +{ + DWORD nRet; + + switch ( nType ) + { + case PRINTER_CAPABILITIES_SUPPORTDIALOG: + return TRUE; + case PRINTER_CAPABILITIES_COPIES: + nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + return nRet; + return 0; + case PRINTER_CAPABILITIES_COLLATECOPIES: + if ( aSalShlData.mbW40 ) + { + nRet = ImplDeviceCaps( this, DC_COLLATE, NULL, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + { + nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + return nRet; + } + } + return 0; + + case PRINTER_CAPABILITIES_SETORIENTATION: + nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + return TRUE; + return FALSE; + + case PRINTER_CAPABILITIES_SETPAPERBIN: + nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + return TRUE; + return FALSE; + + case PRINTER_CAPABILITIES_SETPAPERSIZE: + case PRINTER_CAPABILITIES_SETPAPER: + nRet = ImplDeviceCaps( this, DC_PAPERS, NULL, pSetupData ); + if ( nRet && (nRet != ((ULONG)-1)) ) + return TRUE; + return FALSE; + } + + return 0; +} + +// ----------------------------------------------------------------------- + +void SalInfoPrinter::GetPageInfo( const ImplJobSetup*, + long& rOutWidth, long& rOutHeight, + long& rPageOffX, long& rPageOffY, + long& rPageWidth, long& rPageHeight ) +{ + HDC hDC = maPrinterData.mhDC; + + rOutWidth = GetDeviceCaps( hDC, HORZRES ); + rOutHeight = GetDeviceCaps( hDC, VERTRES ); + + rPageOffX = GetDeviceCaps( hDC, PHYSICALOFFSETX ); + rPageOffY = GetDeviceCaps( hDC, PHYSICALOFFSETY ); + rPageWidth = GetDeviceCaps( hDC, PHYSICALWIDTH ); + rPageHeight = GetDeviceCaps( hDC, PHYSICALHEIGHT ); +} + +// ======================================================================= + +SalPrinter* SalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter ) +{ + SalPrinter* pPrinter = new SalPrinter; + pPrinter->maPrinterData.mpInfoPrinter = pInfoPrinter; + return pPrinter; +} + +// ----------------------------------------------------------------------- + +void SalInstance::DestroyPrinter( SalPrinter* pPrinter ) +{ + delete pPrinter; +} + +// ======================================================================= + +WIN_BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ ) +{ + SalData* pSalData = GetSalData(); + SalPrinter* pPrinter; + BOOL bWhile = TRUE; + int i = 0; + + do + { + // Messages verarbeiten + MSG aMsg; + if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &aMsg ); + ImplDispatchMessage( &aMsg ); + i++; + if ( i > 15 ) + bWhile = FALSE; + } + else + bWhile = FALSE; + + pPrinter = pSalData->mpFirstPrinter; + while ( pPrinter ) + { + if( pPrinter->maPrinterData.mhDC == hPrnDC ) + break; + + pPrinter = pPrinter->maPrinterData.mpNextPrinter; + } + + if ( !pPrinter || pPrinter->maPrinterData.mbAbort ) + return FALSE; + } + while ( bWhile ); + + return TRUE; +} + +// ----------------------------------------------------------------------- + +static LPDEVMODE ImplSalSetCopies( LPDEVMODE pDevMode, ULONG nCopies, BOOL bCollate ) +{ + LPDEVMODE pNewDevMode = pDevMode; + if ( pDevMode && (nCopies > 1) ) + { + if ( nCopies > 32765 ) + nCopies = 32765; + ULONG nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra; + pNewDevMode = (LPDEVMODE)new BYTE[nDevSize]; + memcpy( pNewDevMode, pDevMode, nDevSize ); + pDevMode = pNewDevMode; + pDevMode->dmFields |= DM_COPIES; + pDevMode->dmCopies = (short)(USHORT)nCopies; + if ( aSalShlData.mbW40 ) + { + pDevMode->dmFields |= DM_COLLATE; + if ( bCollate ) + pDevMode->dmCollate = DMCOLLATE_TRUE; + else + pDevMode->dmCollate = DMCOLLATE_FALSE; + } + } + + return pNewDevMode; +} + +// ----------------------------------------------------------------------- + +SalPrinter::SalPrinter() +{ + SalData* pSalData = GetSalData(); + + maPrinterData.mhDC = 0; + maPrinterData.mpGraphics = NULL; + maPrinterData.mbAbort = FALSE; + maPrinterData.mnCopies = 0; + maPrinterData.mbCollate = FALSE; + + // insert frame in framelist + maPrinterData.mpNextPrinter = pSalData->mpFirstPrinter; + pSalData->mpFirstPrinter = this; +} + +// ----------------------------------------------------------------------- + +SalPrinter::~SalPrinter() +{ + SalData* pSalData = GetSalData(); + + // DC freigeben, wenn er noch durch ein AbortJob existiert + HDC hDC = maPrinterData.mhDC; + if ( hDC ) + { + if ( maPrinterData.mpGraphics ) + { + ImplSalDeInitGraphics( &(maPrinterData.mpGraphics->maGraphicsData) ); + delete maPrinterData.mpGraphics; + } + + DeleteDC( hDC ); + } + + // remove printer from printerlist + if ( this == pSalData->mpFirstPrinter ) + pSalData->mpFirstPrinter = maPrinterData.mpNextPrinter; + else + { + SalPrinter* pTempPrinter = pSalData->mpFirstPrinter; + + while( pTempPrinter->maPrinterData.mpNextPrinter != this ) + pTempPrinter = pTempPrinter->maPrinterData.mpNextPrinter; + + pTempPrinter->maPrinterData.mpNextPrinter = maPrinterData.mpNextPrinter; + } +} + +// ----------------------------------------------------------------------- + +BOOL SalPrinter::StartJob( const XubString* pFileName, + const XubString& rJobName, + const XubString&, + ULONG nCopies, BOOL bCollate, + ImplJobSetup* pSetupData ) +{ + maPrinterData.mnError = 0; + maPrinterData.mbAbort = FALSE; + maPrinterData.mnCopies = nCopies; + maPrinterData.mbCollate = bCollate; + + LPDEVMODE pOrgDevMode = NULL; + LPDEVMODE pDevMode; + BOOL bOwnDevMode = FALSE; + if ( pSetupData && pSetupData->mpDriverData ) + { + pOrgDevMode = SAL_DEVMODE( pSetupData ); + pDevMode = ImplSalSetCopies( pOrgDevMode, nCopies, bCollate ); + } + else + pDevMode = NULL; + +// !!! UNICODE - NT Optimierung !!! + HDC hDC = CreateDCA( ImplSalGetWinAnsiString( maPrinterData.mpInfoPrinter->maPrinterData.maDriverName, TRUE ).GetBuffer(), + ImplSalGetWinAnsiString( maPrinterData.mpInfoPrinter->maPrinterData.maDeviceName, TRUE ).GetBuffer(), + 0, + (LPDEVMODEA)pDevMode ); + + if ( pDevMode != pOrgDevMode ) + delete pDevMode; + + if ( !hDC ) + { + maPrinterData.mnError = SAL_PRINTER_ERROR_GENERALERROR; + return FALSE; + } + + if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 ) + { + maPrinterData.mnError = SAL_PRINTER_ERROR_GENERALERROR; + return FALSE; + } + + maPrinterData.mnError = 0; + maPrinterData.mbAbort = FALSE; + +// !!! UNICODE - NT Optimierung !!! + // Both strings must be exist, if StartJob() is called + ByteString aJobName( ImplSalGetWinAnsiString( rJobName, TRUE ) ); + ByteString aFileName; + + DOCINFO aInfo; + memset( &aInfo, 0, sizeof( DOCINFO ) ); + aInfo.cbSize = sizeof( aInfo ); + aInfo.lpszDocName = (LPCSTR)aJobName.GetBuffer(); + if ( pFileName ) + { + if ( pFileName->Len() ) + { + aFileName = ImplSalGetWinAnsiString( *pFileName, TRUE ); + aInfo.lpszOutput = (LPCSTR)aFileName.GetBuffer(); + } + else + aInfo.lpszOutput = "FILE:"; + } + else + aInfo.lpszOutput = NULL; + + // Wegen Telocom Balloon Fax-Treiber, der uns unsere Messages + // ansonsten oefters schickt, versuchen wir vorher alle + // zu verarbeiten und dann eine Dummy-Message reinstellen + BOOL bWhile = TRUE; + int i = 0; + do + { + // Messages verarbeiten + MSG aMsg; + if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &aMsg ); + ImplDispatchMessage( &aMsg ); + i++; + if ( i > 15 ) + bWhile = FALSE; + } + else + bWhile = FALSE; + } + while ( bWhile ); + ImplPostMessage( GetSalData()->mpFirstInstance->maInstData.mhComWnd, SAL_MSG_DUMMY, 0, 0 ); + + // Job starten + int nRet = ::StartDoc( hDC, &aInfo ); + if ( nRet <= 0 ) + { + if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (GetLastError() == ERROR_PRINT_CANCELLED) ) + maPrinterData.mnError = SAL_PRINTER_ERROR_ABORT; + else + maPrinterData.mnError = SAL_PRINTER_ERROR_GENERALERROR; + return FALSE; + } + + maPrinterData.mhDC = hDC; + return TRUE; +} + +// ----------------------------------------------------------------------- + +BOOL SalPrinter::EndJob() +{ + HDC hDC = maPrinterData.mhDC; + if ( hDC ) + { + if ( maPrinterData.mpGraphics ) + { + ImplSalDeInitGraphics( &(maPrinterData.mpGraphics->maGraphicsData) ); + delete maPrinterData.mpGraphics; + maPrinterData.mpGraphics = NULL; + } + + ::EndDoc( hDC ); + DeleteDC( hDC ); + } + + return TRUE; +} + +// ----------------------------------------------------------------------- + +BOOL SalPrinter::AbortJob() +{ + maPrinterData.mbAbort = TRUE; + + // Abort asyncron ausloesen + HDC hDC = maPrinterData.mhDC; + if ( hDC ) + { + SalData* pSalData = GetSalData(); + ImplPostMessage( pSalData->mpFirstInstance->maInstData.mhComWnd, + SAL_MSG_PRINTABORTJOB, (WPARAM)hDC, 0 ); + } + + return TRUE; +} + +// ----------------------------------------------------------------------- + +void ImplSalPrinterAbortJobAsync( HDC hPrnDC ) +{ + SalData* pSalData = GetSalData(); + SalPrinter* pPrinter = pSalData->mpFirstPrinter; + + // Feststellen, ob Printer noch existiert + while ( pPrinter ) + { + if ( pPrinter->maPrinterData.mhDC == hPrnDC ) + break; + + pPrinter = pPrinter->maPrinterData.mpNextPrinter; + } + + // Wenn Printer noch existiert, dann den Job abbrechen + if ( pPrinter ) + { + HDC hDC = pPrinter->maPrinterData.mhDC; + if ( hDC ) + { + if ( pPrinter->maPrinterData.mpGraphics ) + { + ImplSalDeInitGraphics( &(pPrinter->maPrinterData.mpGraphics->maGraphicsData) ); + delete pPrinter->maPrinterData.mpGraphics; + pPrinter->maPrinterData.mpGraphics = NULL; + } + + ::AbortDoc( hDC ); + DeleteDC( hDC ); + } + } +} + +// ----------------------------------------------------------------------- + +SalGraphics* SalPrinter::StartPage( ImplJobSetup* pSetupData, BOOL bNewJobData ) +{ + HDC hDC = maPrinterData.mhDC; + if ( pSetupData && pSetupData->mpDriverData && bNewJobData ) + { + LPDEVMODE pOrgDevMode; + LPDEVMODE pDevMode; + pOrgDevMode = SAL_DEVMODE( pSetupData ); + pDevMode = ImplSalSetCopies( pOrgDevMode, maPrinterData.mnCopies, maPrinterData.mbCollate ); + ResetDC( hDC, pDevMode ); + if ( pDevMode != pOrgDevMode ) + delete pDevMode; + } + int nRet = ::StartPage( hDC ); + if ( nRet <= 0 ) + { + maPrinterData.mnError = SAL_PRINTER_ERROR_GENERALERROR; + return NULL; + } + + // Hack, damit alte PS-Treiber Leerseiten nicht wegoptimieren + HPEN hTempPen = SelectPen( hDC, GetStockPen( NULL_PEN ) ); + HBRUSH hTempBrush = SelectBrush( hDC, GetStockBrush( NULL_BRUSH ) ); + WIN_Rectangle( hDC, -8000, -8000, -7999, -7999 ); + SelectPen( hDC, hTempPen ); + SelectBrush( hDC, hTempBrush ); + + SalGraphics* pGraphics = new SalGraphics; + pGraphics->maGraphicsData.mhDC = hDC; + pGraphics->maGraphicsData.mhWnd = 0; + pGraphics->maGraphicsData.mbPrinter = TRUE; + pGraphics->maGraphicsData.mbVirDev = FALSE; + pGraphics->maGraphicsData.mbWindow = FALSE; + pGraphics->maGraphicsData.mbScreen = FALSE; + ImplSalInitGraphics( &(pGraphics->maGraphicsData) ); + maPrinterData.mpGraphics = pGraphics; + return pGraphics; +} + +// ----------------------------------------------------------------------- + +BOOL SalPrinter::EndPage() +{ + HDC hDC = maPrinterData.mhDC; + if ( hDC && maPrinterData.mpGraphics ) + { + ImplSalDeInitGraphics( &(maPrinterData.mpGraphics->maGraphicsData) ); + delete maPrinterData.mpGraphics; + maPrinterData.mpGraphics = NULL; + } + int nRet = ::EndPage( hDC ); + if ( nRet > 0 ) + return TRUE; + else + { + maPrinterData.mnError = SAL_PRINTER_ERROR_GENERALERROR; + return FALSE; + } +} + +// ----------------------------------------------------------------------- + +ULONG SalPrinter::GetErrorCode() +{ + return maPrinterData.mnError; +} diff --git a/vcl/win/source/gdi/salvd.cxx b/vcl/win/source/gdi/salvd.cxx new file mode 100644 index 000000000000..d9f79ce479a8 --- /dev/null +++ b/vcl/win/source/gdi/salvd.cxx @@ -0,0 +1,226 @@ +/************************************************************************* + * + * $RCSfile: salvd.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _SVWIN_H +#include <tools/svwin.h> +#endif + +#define _SV_SALVD_CXX + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALINST_HXX +#include <salinst.hxx> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif +#ifndef _SV_SALVD_HXX +#include <salvd.hxx> +#endif + +// ======================================================================= + +static HBITMAP ImplCreateVirDevBitmap( HDC hDC, long nDX, long nDY, + USHORT nBitCount ) +{ + HBITMAP hBitmap; + + if ( nBitCount == 1 ) + hBitmap = CreateBitmap( (int)nDX, (int)nDY, 1, 1, NULL ); + else + hBitmap = CreateCompatibleBitmap( hDC, (int)nDX, (int)nDY ); + + return hBitmap; +} + +// ======================================================================= + +SalVirtualDevice* SalInstance::CreateVirtualDevice( SalGraphics* pGraphics, + long nDX, long nDY, + USHORT nBitCount ) +{ + HDC hDC = CreateCompatibleDC( pGraphics->maGraphicsData.mhDC ); + HBITMAP hBmp = ImplCreateVirDevBitmap( pGraphics->maGraphicsData.mhDC, + nDX, nDY, nBitCount ); + + if ( hDC && hBmp ) + { + SalVirtualDevice* pVDev = new SalVirtualDevice; + SalData* pSalData = GetSalData(); + SalGraphics* pVirGraphics = new SalGraphics; + pVirGraphics->maGraphicsData.mhDC = hDC; + pVirGraphics->maGraphicsData.mhWnd = 0; + pVirGraphics->maGraphicsData.mbPrinter = FALSE; + pVirGraphics->maGraphicsData.mbVirDev = TRUE; + pVirGraphics->maGraphicsData.mbWindow = FALSE; + pVirGraphics->maGraphicsData.mbScreen = pGraphics->maGraphicsData.mbScreen; + if ( pSalData->mhDitherPal && pVirGraphics->maGraphicsData.mbScreen ) + { + pVirGraphics->maGraphicsData.mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); + RealizePalette( hDC ); + } + ImplSalInitGraphics( &(pVirGraphics->maGraphicsData) ); + + pVDev->maVirDevData.mhDC = hDC; + pVDev->maVirDevData.mhBmp = hBmp; + pVDev->maVirDevData.mhDefBmp = SelectBitmap( hDC, hBmp ); + pVDev->maVirDevData.mpGraphics = pVirGraphics; + pVDev->maVirDevData.mnBitCount = nBitCount; + pVDev->maVirDevData.mbGraphics = FALSE; + + // insert VirDev in VirDevList + pVDev->maVirDevData.mpNext = pSalData->mpFirstVD; + pSalData->mpFirstVD = pVDev; + + return pVDev; + } + else + { + if ( hDC ) + DeleteDC( hDC ); + if ( hBmp ) + DeleteBitmap( hBmp ); + return NULL; + } +} + +// ----------------------------------------------------------------------- + +void SalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice ) +{ + delete pDevice; +} + +// ======================================================================= + +SalVirtualDevice::SalVirtualDevice() +{ +} + +// ----------------------------------------------------------------------- + +SalVirtualDevice::~SalVirtualDevice() +{ + SalData* pSalData = GetSalData(); + + // destroy saved DC + if ( maVirDevData.mpGraphics->maGraphicsData.mhDefPal ) + SelectPalette( maVirDevData.mpGraphics->maGraphicsData.mhDC, maVirDevData.mpGraphics->maGraphicsData.mhDefPal, TRUE ); + ImplSalDeInitGraphics( &(maVirDevData.mpGraphics->maGraphicsData) ); + SelectBitmap( maVirDevData.mpGraphics->maGraphicsData.mhDC, maVirDevData.mhDefBmp ); + DeleteDC( maVirDevData.mpGraphics->maGraphicsData.mhDC ); + DeleteBitmap( maVirDevData.mhBmp ); + delete maVirDevData.mpGraphics; + + // remove VirDev from VirDevList + if ( this == pSalData->mpFirstVD ) + pSalData->mpFirstVD = maVirDevData.mpNext; + else + { + SalVirtualDevice* pTempVD = pSalData->mpFirstVD; + while ( pTempVD->maVirDevData.mpNext != this ) + pTempVD = pTempVD->maVirDevData.mpNext; + + pTempVD->maVirDevData.mpNext = maVirDevData.mpNext; + } +} + +// ----------------------------------------------------------------------- + +SalGraphics* SalVirtualDevice::GetGraphics() +{ + if ( maVirDevData.mbGraphics ) + return NULL; + + if ( maVirDevData.mpGraphics ) + maVirDevData.mbGraphics = TRUE; + + return maVirDevData.mpGraphics; +} + +// ----------------------------------------------------------------------- + +void SalVirtualDevice::ReleaseGraphics( SalGraphics* ) +{ + maVirDevData.mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL SalVirtualDevice::SetSize( long nDX, long nDY ) +{ + HBITMAP hNewBmp = ImplCreateVirDevBitmap( maVirDevData.mhDC, nDX, nDY, + maVirDevData.mnBitCount ); + if ( hNewBmp ) + { + SelectBitmap( maVirDevData.mhDC, hNewBmp ); + DeleteBitmap( maVirDevData.mhBmp ); + maVirDevData.mhBmp = hNewBmp; + return TRUE; + } + else + return FALSE; +} diff --git a/vcl/win/source/gdi/wntgdi.cxx b/vcl/win/source/gdi/wntgdi.cxx new file mode 100644 index 000000000000..0bd7751c97e9 --- /dev/null +++ b/vcl/win/source/gdi/wntgdi.cxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * $RCSfile: wntgdi.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <windows.h> + +// ----------------------------------------------------------------------- + +extern "C" +{ +BOOL WINAPI WIN_Rectangle( HDC hDC, int X1, int Y1, int X2, int Y2 ) +{ + return Rectangle( hDC, X1, Y1, X2, Y2 ); +} +} + +// ----------------------------------------------------------------------- + +extern "C" +{ +BOOL WINAPI WIN_Polygon( HDC hDC, CONST POINT * ppt, int ncnt ) +{ + return Polygon( hDC, ppt, ncnt ); +} +} + +// ----------------------------------------------------------------------- + +extern "C" +{ +BOOL WINAPI WIN_PolyPolygon( HDC hDC, CONST POINT * ppt, LPINT npcnt, int ncnt ) +{ + return PolyPolygon( hDC, ppt, npcnt, ncnt ); +} +} diff --git a/vcl/win/source/src/50.bmp b/vcl/win/source/src/50.bmp Binary files differnew file mode 100644 index 000000000000..b9d56fcd14c1 --- /dev/null +++ b/vcl/win/source/src/50.bmp diff --git a/vcl/win/source/src/MAKEFILE.MK b/vcl/win/source/src/MAKEFILE.MK new file mode 100644 index 000000000000..463741b23bb7 --- /dev/null +++ b/vcl/win/source/src/MAKEFILE.MK @@ -0,0 +1,106 @@ +#************************************************************************* +#* +#* $Workfile: makefile. $ +#* +#* Ersterstellung TH 01.04.97 +#* Letzte Aenderung $Author: hr $ $Date: 2000-09-18 17:05:49 $ +#* $Revision: 1.1.1.1 $ +#* +#* $Logfile: T:/vcl/win/source/src/makefile.__v $ +#* +#* Copyright (c) 1990 - 2000, STAR DIVISION +#* +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=salsrc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +RCDEPN= nullptr.cur \ + help.cur \ + hsize.cur \ + vsize.cur \ + neswsize.cur \ + nwsesize.cur \ + cross.cur \ + move.cur \ + hsplit.cur \ + vsplit.cur \ + hsizebar.cur \ + vsizebar.cur \ + hand.cur \ + refhand.cur \ + pen.cur \ + magnify.cur \ + fill.cur \ + rotate.cur \ + hshear.cur \ + vshear.cur \ + mirror.cur \ + crook.cur \ + crop.cur \ + movept.cur \ + movebw.cur \ + movedata.cur \ + copydata.cur \ + linkdata.cur \ + movedlnk.cur \ + copydlnk.cur \ + movef.cur \ + copyf.cur \ + linkf.cur \ + moveflnk.cur \ + copyflnk.cur \ + movef2.cur \ + copyf2.cur \ + notallow.cur \ + dline.cur \ + drect.cur \ + dpolygon.cur \ + dbezier.cur \ + darc.cur \ + dpie.cur \ + dcirccut.cur \ + dellipse.cur \ + dfree.cur \ + dconnect.cur \ + dtext.cur \ + dcapt.cur \ + chart.cur \ + detectiv.cur \ + pivotcol.cur \ + pivotrow.cur \ + pivotfld.cur \ + chain.cur \ + chainnot.cur \ + timemove.cur \ + timesize.cur \ + asn.cur \ + ass.cur \ + asw.cur \ + ase.cur \ + asnw.cur \ + asne.cur \ + assw.cur \ + asse.cur \ + asns.cur \ + aswe.cur \ + asnswe.cur \ + airbrush.cur \ + 50.bmp \ + sd.ico + +RCFILES= salsrc.rc + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/win/source/src/airbrush.cur b/vcl/win/source/src/airbrush.cur Binary files differnew file mode 100644 index 000000000000..f6a684e6fcbd --- /dev/null +++ b/vcl/win/source/src/airbrush.cur diff --git a/vcl/win/source/src/ase.cur b/vcl/win/source/src/ase.cur Binary files differnew file mode 100755 index 000000000000..7634a7d34a7b --- /dev/null +++ b/vcl/win/source/src/ase.cur diff --git a/vcl/win/source/src/asn.cur b/vcl/win/source/src/asn.cur Binary files differnew file mode 100755 index 000000000000..e444e42bf37e --- /dev/null +++ b/vcl/win/source/src/asn.cur diff --git a/vcl/win/source/src/asne.cur b/vcl/win/source/src/asne.cur Binary files differnew file mode 100755 index 000000000000..e92cc65e7eb1 --- /dev/null +++ b/vcl/win/source/src/asne.cur diff --git a/vcl/win/source/src/asns.cur b/vcl/win/source/src/asns.cur Binary files differnew file mode 100755 index 000000000000..04d0b09c353e --- /dev/null +++ b/vcl/win/source/src/asns.cur diff --git a/vcl/win/source/src/asnswe.cur b/vcl/win/source/src/asnswe.cur Binary files differnew file mode 100755 index 000000000000..a0e25b16de1f --- /dev/null +++ b/vcl/win/source/src/asnswe.cur diff --git a/vcl/win/source/src/asnw.cur b/vcl/win/source/src/asnw.cur Binary files differnew file mode 100755 index 000000000000..20322bc97b16 --- /dev/null +++ b/vcl/win/source/src/asnw.cur diff --git a/vcl/win/source/src/ass.cur b/vcl/win/source/src/ass.cur Binary files differnew file mode 100755 index 000000000000..7166636a1a77 --- /dev/null +++ b/vcl/win/source/src/ass.cur diff --git a/vcl/win/source/src/asse.cur b/vcl/win/source/src/asse.cur Binary files differnew file mode 100755 index 000000000000..8cb71234b0a9 --- /dev/null +++ b/vcl/win/source/src/asse.cur diff --git a/vcl/win/source/src/assw.cur b/vcl/win/source/src/assw.cur Binary files differnew file mode 100755 index 000000000000..fddaf3f57cbf --- /dev/null +++ b/vcl/win/source/src/assw.cur diff --git a/vcl/win/source/src/asw.cur b/vcl/win/source/src/asw.cur Binary files differnew file mode 100755 index 000000000000..0ccac50f4596 --- /dev/null +++ b/vcl/win/source/src/asw.cur diff --git a/vcl/win/source/src/aswe.cur b/vcl/win/source/src/aswe.cur Binary files differnew file mode 100755 index 000000000000..c238b7e10aef --- /dev/null +++ b/vcl/win/source/src/aswe.cur diff --git a/vcl/win/source/src/chain.cur b/vcl/win/source/src/chain.cur Binary files differnew file mode 100755 index 000000000000..02abb7ab714f --- /dev/null +++ b/vcl/win/source/src/chain.cur diff --git a/vcl/win/source/src/chainnot.cur b/vcl/win/source/src/chainnot.cur Binary files differnew file mode 100755 index 000000000000..938ece03f329 --- /dev/null +++ b/vcl/win/source/src/chainnot.cur diff --git a/vcl/win/source/src/chart.cur b/vcl/win/source/src/chart.cur Binary files differnew file mode 100644 index 000000000000..25fe85b76039 --- /dev/null +++ b/vcl/win/source/src/chart.cur diff --git a/vcl/win/source/src/copydata.cur b/vcl/win/source/src/copydata.cur Binary files differnew file mode 100644 index 000000000000..d3c4bc93afd5 --- /dev/null +++ b/vcl/win/source/src/copydata.cur diff --git a/vcl/win/source/src/copydlnk.cur b/vcl/win/source/src/copydlnk.cur Binary files differnew file mode 100644 index 000000000000..495fd5e17776 --- /dev/null +++ b/vcl/win/source/src/copydlnk.cur diff --git a/vcl/win/source/src/copyf.cur b/vcl/win/source/src/copyf.cur Binary files differnew file mode 100644 index 000000000000..450c09443a84 --- /dev/null +++ b/vcl/win/source/src/copyf.cur diff --git a/vcl/win/source/src/copyf2.cur b/vcl/win/source/src/copyf2.cur Binary files differnew file mode 100644 index 000000000000..ac8de5da6ba5 --- /dev/null +++ b/vcl/win/source/src/copyf2.cur diff --git a/vcl/win/source/src/copyflnk.cur b/vcl/win/source/src/copyflnk.cur Binary files differnew file mode 100644 index 000000000000..e67f0539fa43 --- /dev/null +++ b/vcl/win/source/src/copyflnk.cur diff --git a/vcl/win/source/src/crook.cur b/vcl/win/source/src/crook.cur Binary files differnew file mode 100644 index 000000000000..c40cf591e261 --- /dev/null +++ b/vcl/win/source/src/crook.cur diff --git a/vcl/win/source/src/crop.cur b/vcl/win/source/src/crop.cur Binary files differnew file mode 100644 index 000000000000..327fb06976c2 --- /dev/null +++ b/vcl/win/source/src/crop.cur diff --git a/vcl/win/source/src/cross.cur b/vcl/win/source/src/cross.cur Binary files differnew file mode 100644 index 000000000000..8fd9762386b1 --- /dev/null +++ b/vcl/win/source/src/cross.cur diff --git a/vcl/win/source/src/darc.cur b/vcl/win/source/src/darc.cur Binary files differnew file mode 100644 index 000000000000..38504fa23c4a --- /dev/null +++ b/vcl/win/source/src/darc.cur diff --git a/vcl/win/source/src/dbezier.cur b/vcl/win/source/src/dbezier.cur Binary files differnew file mode 100644 index 000000000000..f630b837ddf8 --- /dev/null +++ b/vcl/win/source/src/dbezier.cur diff --git a/vcl/win/source/src/dcapt.cur b/vcl/win/source/src/dcapt.cur Binary files differnew file mode 100644 index 000000000000..10dd5ba0d676 --- /dev/null +++ b/vcl/win/source/src/dcapt.cur diff --git a/vcl/win/source/src/dcirccut.cur b/vcl/win/source/src/dcirccut.cur Binary files differnew file mode 100644 index 000000000000..b19d3f8257f4 --- /dev/null +++ b/vcl/win/source/src/dcirccut.cur diff --git a/vcl/win/source/src/dconnect.cur b/vcl/win/source/src/dconnect.cur Binary files differnew file mode 100644 index 000000000000..5318d8f22d8b --- /dev/null +++ b/vcl/win/source/src/dconnect.cur diff --git a/vcl/win/source/src/dellipse.cur b/vcl/win/source/src/dellipse.cur Binary files differnew file mode 100644 index 000000000000..c489a640335e --- /dev/null +++ b/vcl/win/source/src/dellipse.cur diff --git a/vcl/win/source/src/detectiv.cur b/vcl/win/source/src/detectiv.cur Binary files differnew file mode 100644 index 000000000000..30e5685b64b2 --- /dev/null +++ b/vcl/win/source/src/detectiv.cur diff --git a/vcl/win/source/src/dfree.cur b/vcl/win/source/src/dfree.cur Binary files differnew file mode 100644 index 000000000000..3ff56d007648 --- /dev/null +++ b/vcl/win/source/src/dfree.cur diff --git a/vcl/win/source/src/dline.cur b/vcl/win/source/src/dline.cur Binary files differnew file mode 100644 index 000000000000..623c33ac2351 --- /dev/null +++ b/vcl/win/source/src/dline.cur diff --git a/vcl/win/source/src/dpie.cur b/vcl/win/source/src/dpie.cur Binary files differnew file mode 100644 index 000000000000..3b911cd01e43 --- /dev/null +++ b/vcl/win/source/src/dpie.cur diff --git a/vcl/win/source/src/dpolygon.cur b/vcl/win/source/src/dpolygon.cur Binary files differnew file mode 100644 index 000000000000..9467f1e286aa --- /dev/null +++ b/vcl/win/source/src/dpolygon.cur diff --git a/vcl/win/source/src/drect.cur b/vcl/win/source/src/drect.cur Binary files differnew file mode 100644 index 000000000000..60a5242c203c --- /dev/null +++ b/vcl/win/source/src/drect.cur diff --git a/vcl/win/source/src/dtext.cur b/vcl/win/source/src/dtext.cur Binary files differnew file mode 100644 index 000000000000..01e7d31eae7e --- /dev/null +++ b/vcl/win/source/src/dtext.cur diff --git a/vcl/win/source/src/fill.cur b/vcl/win/source/src/fill.cur Binary files differnew file mode 100644 index 000000000000..78f5fad87ad0 --- /dev/null +++ b/vcl/win/source/src/fill.cur diff --git a/vcl/win/source/src/hand.cur b/vcl/win/source/src/hand.cur Binary files differnew file mode 100644 index 000000000000..fc0e53b474e2 --- /dev/null +++ b/vcl/win/source/src/hand.cur diff --git a/vcl/win/source/src/help.cur b/vcl/win/source/src/help.cur Binary files differnew file mode 100644 index 000000000000..e59ee97992b3 --- /dev/null +++ b/vcl/win/source/src/help.cur diff --git a/vcl/win/source/src/hshear.cur b/vcl/win/source/src/hshear.cur Binary files differnew file mode 100644 index 000000000000..5cf2211458c3 --- /dev/null +++ b/vcl/win/source/src/hshear.cur diff --git a/vcl/win/source/src/hsize.cur b/vcl/win/source/src/hsize.cur Binary files differnew file mode 100644 index 000000000000..571dd0ef703c --- /dev/null +++ b/vcl/win/source/src/hsize.cur diff --git a/vcl/win/source/src/hsizebar.cur b/vcl/win/source/src/hsizebar.cur Binary files differnew file mode 100644 index 000000000000..dda3483bb5d4 --- /dev/null +++ b/vcl/win/source/src/hsizebar.cur diff --git a/vcl/win/source/src/hsplit.cur b/vcl/win/source/src/hsplit.cur Binary files differnew file mode 100644 index 000000000000..f2f0be363d3a --- /dev/null +++ b/vcl/win/source/src/hsplit.cur diff --git a/vcl/win/source/src/linkdata.cur b/vcl/win/source/src/linkdata.cur Binary files differnew file mode 100644 index 000000000000..e47c1dea2cec --- /dev/null +++ b/vcl/win/source/src/linkdata.cur diff --git a/vcl/win/source/src/linkf.cur b/vcl/win/source/src/linkf.cur Binary files differnew file mode 100644 index 000000000000..6cc498a02610 --- /dev/null +++ b/vcl/win/source/src/linkf.cur diff --git a/vcl/win/source/src/mirror.cur b/vcl/win/source/src/mirror.cur Binary files differnew file mode 100644 index 000000000000..e05eb836eb5d --- /dev/null +++ b/vcl/win/source/src/mirror.cur diff --git a/vcl/win/source/src/move.cur b/vcl/win/source/src/move.cur Binary files differnew file mode 100644 index 000000000000..a407a1298ad5 --- /dev/null +++ b/vcl/win/source/src/move.cur diff --git a/vcl/win/source/src/movebw.cur b/vcl/win/source/src/movebw.cur Binary files differnew file mode 100644 index 000000000000..d079eb9fe20d --- /dev/null +++ b/vcl/win/source/src/movebw.cur diff --git a/vcl/win/source/src/movedata.cur b/vcl/win/source/src/movedata.cur Binary files differnew file mode 100644 index 000000000000..4d67cbe47149 --- /dev/null +++ b/vcl/win/source/src/movedata.cur diff --git a/vcl/win/source/src/movedlnk.cur b/vcl/win/source/src/movedlnk.cur Binary files differnew file mode 100644 index 000000000000..1bb7b0306406 --- /dev/null +++ b/vcl/win/source/src/movedlnk.cur diff --git a/vcl/win/source/src/movef.cur b/vcl/win/source/src/movef.cur Binary files differnew file mode 100644 index 000000000000..6abee2381dcf --- /dev/null +++ b/vcl/win/source/src/movef.cur diff --git a/vcl/win/source/src/movef2.cur b/vcl/win/source/src/movef2.cur Binary files differnew file mode 100644 index 000000000000..d044981a3ffd --- /dev/null +++ b/vcl/win/source/src/movef2.cur diff --git a/vcl/win/source/src/moveflnk.cur b/vcl/win/source/src/moveflnk.cur Binary files differnew file mode 100644 index 000000000000..630fa1bc3e4e --- /dev/null +++ b/vcl/win/source/src/moveflnk.cur diff --git a/vcl/win/source/src/movept.cur b/vcl/win/source/src/movept.cur Binary files differnew file mode 100644 index 000000000000..81d3af5a05c4 --- /dev/null +++ b/vcl/win/source/src/movept.cur diff --git a/vcl/win/source/src/neswsize.cur b/vcl/win/source/src/neswsize.cur Binary files differnew file mode 100644 index 000000000000..c38501ee15a8 --- /dev/null +++ b/vcl/win/source/src/neswsize.cur diff --git a/vcl/win/source/src/notallow.cur b/vcl/win/source/src/notallow.cur Binary files differnew file mode 100644 index 000000000000..90c1dfbb3a97 --- /dev/null +++ b/vcl/win/source/src/notallow.cur diff --git a/vcl/win/source/src/nullptr.cur b/vcl/win/source/src/nullptr.cur Binary files differnew file mode 100644 index 000000000000..28dbb2a903f2 --- /dev/null +++ b/vcl/win/source/src/nullptr.cur diff --git a/vcl/win/source/src/nwsesize.cur b/vcl/win/source/src/nwsesize.cur Binary files differnew file mode 100644 index 000000000000..570cbbb571cc --- /dev/null +++ b/vcl/win/source/src/nwsesize.cur diff --git a/vcl/win/source/src/pen.cur b/vcl/win/source/src/pen.cur Binary files differnew file mode 100644 index 000000000000..040c5dc703e9 --- /dev/null +++ b/vcl/win/source/src/pen.cur diff --git a/vcl/win/source/src/refhand.cur b/vcl/win/source/src/refhand.cur Binary files differnew file mode 100644 index 000000000000..a654974c6f8b --- /dev/null +++ b/vcl/win/source/src/refhand.cur diff --git a/vcl/win/source/src/rotate.cur b/vcl/win/source/src/rotate.cur Binary files differnew file mode 100644 index 000000000000..43c2a54a10ac --- /dev/null +++ b/vcl/win/source/src/rotate.cur diff --git a/vcl/win/source/src/salsrc.rc b/vcl/win/source/src/salsrc.rc new file mode 100644 index 000000000000..d7785d3ee734 --- /dev/null +++ b/vcl/win/source/src/salsrc.rc @@ -0,0 +1,148 @@ +/************************************************************************* +* +* $RCSfile: salsrc.rc,v $ +* +* $Revision: 1.1.1.1 $ +* +* last change: $Author: hr $ $Date: 2000-09-18 17:05:50 $ +* +* The Contents of this file are made available subject to the terms of +* either of the following licenses +* +* - GNU Lesser General Public License Version 2.1 +* - Sun Industry Standards Source License Version 1.1 +* +* Sun Microsystems Inc., October, 2000 +* +* GNU Lesser General Public License Version 2.1 +* ============================================= +* Copyright 2000 by Sun Microsystems, Inc. +* 901 San Antonio Road, Palo Alto, CA 94303, USA +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License version 2.1, as published by the Free Software Foundation. +* +* This library 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 for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307 USA +* +* +* Sun Industry Standards Source License Version 1.1 +* ================================================= +* The contents of this file are subject to the Sun Industry Standards +* Source License Version 1.1 (the "License"); You may not use this file +* except in compliance with the License. You may obtain a copy of the +* License at http://www.openoffice.org/license.html. +* +* Software provided under this License is provided on an "AS IS" basis, +* WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, +* WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +* See the License for the specific provisions governing your rights and +* obligations concerning the Software. +* +* The Initial Developer of the Original Code is: Sun Microsystems, Inc.. +* +* Copyright: 2000 by Sun Microsystems, Inc. +* +* All Rights Reserved. +* +* Contributor(s): _______________________________________ +* +* +* +**************************************************************************/ + +// for WINVER +#include <windows.h> + +#ifndef _SV_SALIDS_HRC +#include <salids.hrc> +#endif + +SAL_RESID_POINTER_NULL CURSOR NULLPTR.CUR +#if ( WINVER < 0x0400 ) +SAL_RESID_POINTER_HELP CURSOR HELP.CUR +#endif +#ifndef WNT +SAL_RESID_POINTER_HSIZE CURSOR HSIZE.CUR +SAL_RESID_POINTER_VSIZE CURSOR VSIZE.CUR +SAL_RESID_POINTER_NESWSIZE CURSOR NESWSIZE.CUR +SAL_RESID_POINTER_NWSESIZE CURSOR NWSESIZE.CUR +#endif +SAL_RESID_POINTER_CROSS CURSOR CROSS.CUR +SAL_RESID_POINTER_MOVE CURSOR MOVE.CUR +SAL_RESID_POINTER_HSPLIT CURSOR HSPLIT.CUR +SAL_RESID_POINTER_VSPLIT CURSOR VSPLIT.CUR +SAL_RESID_POINTER_HSIZEBAR CURSOR HSIZEBAR.CUR +SAL_RESID_POINTER_VSIZEBAR CURSOR VSIZEBAR.CUR +SAL_RESID_POINTER_HAND CURSOR HAND.CUR +SAL_RESID_POINTER_REFHAND CURSOR REFHAND.CUR +SAL_RESID_POINTER_PEN CURSOR PEN.CUR +SAL_RESID_POINTER_MAGNIFY CURSOR MAGNIFY.CUR +SAL_RESID_POINTER_FILL CURSOR FILL.CUR +SAL_RESID_POINTER_ROTATE CURSOR ROTATE.CUR +SAL_RESID_POINTER_HSHEAR CURSOR HSHEAR.CUR +SAL_RESID_POINTER_VSHEAR CURSOR VSHEAR.CUR +SAL_RESID_POINTER_MIRROR CURSOR MIRROR.CUR +SAL_RESID_POINTER_CROOK CURSOR CROOK.CUR +SAL_RESID_POINTER_CROP CURSOR CROP.CUR +SAL_RESID_POINTER_MOVEPOINT CURSOR MOVEPT.CUR +SAL_RESID_POINTER_MOVEBEZIERWEIGHT CURSOR MOVEBW.CUR +SAL_RESID_POINTER_MOVEDATA CURSOR MOVEDATA.CUR +SAL_RESID_POINTER_COPYDATA CURSOR COPYDATA.CUR +SAL_RESID_POINTER_LINKDATA CURSOR LINKDATA.CUR +SAL_RESID_POINTER_MOVEDATALINK CURSOR MOVEDLNK.CUR +SAL_RESID_POINTER_COPYDATALINK CURSOR COPYDLNK.CUR +SAL_RESID_POINTER_MOVEFILE CURSOR MOVEF.CUR +SAL_RESID_POINTER_COPYFILE CURSOR COPYF.CUR +SAL_RESID_POINTER_LINKFILE CURSOR LINKF.CUR +SAL_RESID_POINTER_MOVEFILELINK CURSOR MOVEFLNK.CUR +SAL_RESID_POINTER_COPYFILELINK CURSOR COPYFLNK.CUR +SAL_RESID_POINTER_MOVEFILES CURSOR MOVEF2.CUR +SAL_RESID_POINTER_COPYFILES CURSOR COPYF2.CUR +SAL_RESID_POINTER_NOTALLOWED CURSOR NOTALLOW.CUR +SAL_RESID_POINTER_DRAW_LINE CURSOR DLINE.CUR +SAL_RESID_POINTER_DRAW_RECT CURSOR DRECT.CUR +SAL_RESID_POINTER_DRAW_POLYGON CURSOR DPOLYGON.CUR +SAL_RESID_POINTER_DRAW_BEZIER CURSOR DBEZIER.CUR +SAL_RESID_POINTER_DRAW_ARC CURSOR DARC.CUR +SAL_RESID_POINTER_DRAW_PIE CURSOR DPIE.CUR +SAL_RESID_POINTER_DRAW_CIRCLECUT CURSOR DCIRCCUT.CUR +SAL_RESID_POINTER_DRAW_ELLIPSE CURSOR DELLIPSE.CUR +SAL_RESID_POINTER_DRAW_FREEHAND CURSOR DFREE.CUR +SAL_RESID_POINTER_DRAW_CONNECT CURSOR DCONNECT.CUR +SAL_RESID_POINTER_DRAW_TEXT CURSOR DTEXT.CUR +SAL_RESID_POINTER_DRAW_CAPTION CURSOR DCAPT.CUR +SAL_RESID_POINTER_CHART CURSOR CHART.CUR +SAL_RESID_POINTER_DETECTIVE CURSOR DETECTIV.CUR +SAL_RESID_POINTER_PIVOT_COL CURSOR PIVOTCOL.CUR +SAL_RESID_POINTER_PIVOT_ROW CURSOR PIVOTROW.CUR +SAL_RESID_POINTER_PIVOT_FIELD CURSOR PIVOTFLD.CUR +SAL_RESID_POINTER_CHAIN CURSOR CHAIN.CUR +SAL_RESID_POINTER_CHAIN_NOTALLOWED CURSOR CHAINNOT.CUR +SAL_RESID_POINTER_TIMEEVENT_MOVE CURSOR TIMEMOVE.CUR +SAL_RESID_POINTER_TIMEEVENT_SIZE CURSOR TIMESIZE.CUR +SAL_RESID_POINTER_AUTOSCROLL_N CURSOR ASN.CUR +SAL_RESID_POINTER_AUTOSCROLL_S CURSOR ASS.CUR +SAL_RESID_POINTER_AUTOSCROLL_W CURSOR ASW.CUR +SAL_RESID_POINTER_AUTOSCROLL_E CURSOR ASE.CUR +SAL_RESID_POINTER_AUTOSCROLL_NW CURSOR ASNW.CUR +SAL_RESID_POINTER_AUTOSCROLL_NE CURSOR ASNE.CUR +SAL_RESID_POINTER_AUTOSCROLL_SW CURSOR ASSW.CUR +SAL_RESID_POINTER_AUTOSCROLL_SE CURSOR ASSE.CUR +SAL_RESID_POINTER_AUTOSCROLL_NS CURSOR ASNS.CUR +SAL_RESID_POINTER_AUTOSCROLL_WE CURSOR ASWE.CUR +SAL_RESID_POINTER_AUTOSCROLL_NSWE CURSOR ASNSWE.CUR +SAL_RESID_POINTER_AIRBRUSH CURSOR AIRBRUSH.CUR + +SAL_RESID_BITMAP_50 BITMAP 50.BMP + +SAL_RESID_ICON_DEFAULT ICON SD.ICO diff --git a/vcl/win/source/src/sd.ico b/vcl/win/source/src/sd.ico Binary files differnew file mode 100644 index 000000000000..b2a0a07a67c3 --- /dev/null +++ b/vcl/win/source/src/sd.ico diff --git a/vcl/win/source/src/timemove.cur b/vcl/win/source/src/timemove.cur Binary files differnew file mode 100755 index 000000000000..319b6edc5774 --- /dev/null +++ b/vcl/win/source/src/timemove.cur diff --git a/vcl/win/source/src/timesize.cur b/vcl/win/source/src/timesize.cur Binary files differnew file mode 100755 index 000000000000..1ec23de05b71 --- /dev/null +++ b/vcl/win/source/src/timesize.cur diff --git a/vcl/win/source/src/vshear.cur b/vcl/win/source/src/vshear.cur Binary files differnew file mode 100644 index 000000000000..a4bbf7e8eb00 --- /dev/null +++ b/vcl/win/source/src/vshear.cur diff --git a/vcl/win/source/src/vsize.cur b/vcl/win/source/src/vsize.cur Binary files differnew file mode 100644 index 000000000000..76449be89d0a --- /dev/null +++ b/vcl/win/source/src/vsize.cur diff --git a/vcl/win/source/src/vsizebar.cur b/vcl/win/source/src/vsizebar.cur Binary files differnew file mode 100644 index 000000000000..a87811cb474d --- /dev/null +++ b/vcl/win/source/src/vsizebar.cur diff --git a/vcl/win/source/src/vsplit.cur b/vcl/win/source/src/vsplit.cur Binary files differnew file mode 100644 index 000000000000..a4260808fadc --- /dev/null +++ b/vcl/win/source/src/vsplit.cur diff --git a/vcl/win/source/window/MAKEFILE.MK b/vcl/win/source/window/MAKEFILE.MK new file mode 100644 index 000000000000..c370e52b2bb9 --- /dev/null +++ b/vcl/win/source/window/MAKEFILE.MK @@ -0,0 +1,38 @@ +#************************************************************************* +#* +#* $Workfile: makefile. $ +#* +#* Ersterstellung TH 01.04.97 +#* Letzte Aenderung $Author: hr $ $Date: 2000-09-18 17:05:50 $ +#* $Revision: 1.1.1.1 $ +#* +#* $Logfile: T:/sv2/win/source/window/makefile.__v $ +#* +#* Copyright (c) 1990 - 1998, STAR DIVISION +#* +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=salwin + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +SLOFILES= $(SLO)$/salframe.obj \ + $(SLO)$/salobj.obj + +.IF "$(UPDATER)"=="YES" +OBJFILES= $(OBJ)$/salframe.obj \ + $(OBJ)$/salobj.obj +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/vcl/win/source/window/salframe.cxx b/vcl/win/source/window/salframe.cxx new file mode 100644 index 000000000000..48d964af3ab6 --- /dev/null +++ b/vcl/win/source/window/salframe.cxx @@ -0,0 +1,3901 @@ +/************************************************************************* + * + * $RCSfile: salframe.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:50 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> +#include <limits.h> + +#ifdef DBG_UTIL +#include <stdio.h> +#endif + +#ifndef _SVWIN_HXX +#include <tools/svwin.h> +#endif + +#define _SV_SALFRAME_CXX + +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#define private public +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALIDS_HRC +#include <salids.hrc> +#endif +#ifndef _SV_SYSDATA_HXX +#include <sysdata.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALINST_HXX +#include <salinst.hxx> +#endif +#ifndef _SV_SALGDI_HXX +#include <salgdi.hxx> +#endif +#ifndef _SV_SALSYS_HXX +#include <salsys.hxx> +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif +#ifndef _SV_SALVD_HXX +#include <salvd.hxx> +#endif + +#ifndef _SV_TIMER_HXX +#include <timer.hxx> +#endif +#ifndef _SV_SETTINGS_HXX +#include <settings.hxx> +#endif +#ifndef _SV_KEYCOES_HXX +#include <keycodes.hxx> +#endif + +// ======================================================================= + +// Wegen Fehler in Windows-Headerfiles +#ifndef IMN_OPENCANDIDATE +#define IMN_OPENCANDIDATE 0x0005 +#endif +#ifndef IMN_CLOSECANDIDATE +#define IMN_CLOSECANDIDATE 0x0004 +#endif + +// ======================================================================= + +static void ImplSaveFrameState( SalFrame* pFrame ) +{ + // Position, Groesse und Status fuer GetWindowState() merken + if ( !pFrame->maFrameData.mbFullScreen ) + { + BOOL bVisible = (GetWindowStyle( pFrame->maFrameData.mhWnd ) & WS_VISIBLE) != 0; + if ( IsIconic( pFrame->maFrameData.mhWnd ) ) + { + pFrame->maFrameData.maState.mnState |= SAL_FRAMESTATE_MINIMIZED; + if ( bVisible ) + pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED; + } + else if ( IsZoomed( pFrame->maFrameData.mhWnd ) ) + { + pFrame->maFrameData.maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED; + pFrame->maFrameData.maState.mnState |= SAL_FRAMESTATE_MAXIMIZED; + if ( bVisible ) + pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED; + pFrame->maFrameData.mbRestoreMaximize = TRUE; + } + else + { + RECT aRect; + GetWindowRect( pFrame->maFrameData.mhWnd, &aRect ); + pFrame->maFrameData.maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED); + pFrame->maFrameData.maState.mnX = aRect.left; + pFrame->maFrameData.maState.mnY = aRect.top; + pFrame->maFrameData.maState.mnWidth = aRect.right-aRect.left; + pFrame->maFrameData.maState.mnHeight = aRect.bottom-aRect.top; + if ( bVisible ) + pFrame->maFrameData.mnShowState = SW_SHOWNORMAL; + pFrame->maFrameData.mbRestoreMaximize = FALSE; + } + } +} + +// ======================================================================= + +SalFrame* ImplSalCreateFrame( SalInstance* pInst, + HWND hWndParent, ULONG nSalFrameStyle ) +{ + SalFrame* pFrame = new SalFrame; + HWND hWnd; + DWORD nSysStyle = 0; + DWORD nExSysStyle = 0; + BOOL bSaveBits = FALSE; + + // determine creation data + if ( nSalFrameStyle & SAL_FRAME_STYLE_CHILD ) + nSysStyle |= WS_CHILD; + else if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT ) + { + pFrame->maFrameData.mbCaption = TRUE; + nSysStyle |= WS_OVERLAPPED; +#if ( WINVER >= 0x0400 ) + nExSysStyle |= WS_EX_APPWINDOW; +#endif + } + else + nSysStyle |= WS_POPUP; + if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE ) + { + pFrame->maFrameData.mbSizeBorder = TRUE; + nSysStyle |= WS_THICKFRAME | WS_SYSMENU; + } + else if ( nSalFrameStyle & SAL_FRAME_STYLE_BORDER ) + { + pFrame->maFrameData.mbBorder = TRUE; + nSysStyle |= WS_BORDER; + } + if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE ) + { + pFrame->maFrameData.mbCaption = TRUE; + nSysStyle |= WS_CAPTION | WS_SYSMENU; + } +#if ( WINVER >= 0x0400 ) + else + nExSysStyle |= WS_EX_TOOLWINDOW; +#endif + if ( nSalFrameStyle & SAL_FRAME_STYLE_MINABLE ) + nSysStyle |= WS_MINIMIZEBOX | WS_SYSMENU; + if ( nSalFrameStyle & SAL_FRAME_STYLE_MAXABLE ) + nSysStyle |= WS_MAXIMIZEBOX | WS_SYSMENU; + + // init frame data + pFrame->maFrameData.mnStyle = nSalFrameStyle; + + // determine show style + if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT ) + { + SalData* pSalData = GetSalData(); + pFrame->maFrameData.mnShowState = pSalData->mnCmdShow; + if ( (pFrame->maFrameData.mnShowState != SW_SHOWMINIMIZED) && + (pFrame->maFrameData.mnShowState != SW_MINIMIZE) && + (pFrame->maFrameData.mnShowState != SW_SHOWMINNOACTIVE) ) + { + if ( (pFrame->maFrameData.mnShowState == SW_SHOWMAXIMIZED) || + (pFrame->maFrameData.mnShowState == SW_MAXIMIZE) ) + pFrame->maFrameData.mbOverwriteState = FALSE; + pFrame->maFrameData.mnShowState = SW_SHOWMAXIMIZED; + } + else + pFrame->maFrameData.mbOverwriteState = FALSE; + } + else + pFrame->maFrameData.mnShowState = SW_SHOWNORMAL; + + // create frame + if ( aSalShlData.mbWNT ) + { + LPCWSTR pClassName; + if ( bSaveBits ) + pClassName = SAL_FRAME_CLASSNAME_SBW; + else + pClassName = SAL_FRAME_CLASSNAMEW; + hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, + hWndParent, 0, pInst->maInstData.mhInst, (void*)pFrame ); + } + else + { + LPCSTR pClassName; + if ( bSaveBits ) + pClassName = SAL_FRAME_CLASSNAME_SBA; + else + pClassName = SAL_FRAME_CLASSNAMEA; + hWnd = CreateWindowExA( nExSysStyle, pClassName, "", nSysStyle, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, + hWndParent, 0, pInst->maInstData.mhInst, (void*)pFrame ); + } + if ( !hWnd ) + { + delete pFrame; + return NULL; + } + + // disable close + if ( !(nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE) ) + { + HMENU hSysMenu = GetSystemMenu( hWnd, FALSE ); + if ( hSysMenu ) + EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED ); + } + + // reset input context + pFrame->maFrameData.mhDefIMEContext = ImmAssociateContext( hWnd, 0 ); + + // determine output size and state + RECT aRect; + GetClientRect( hWnd, &aRect ); + pFrame->maFrameData.mnWidth = aRect.right; + pFrame->maFrameData.mnHeight = aRect.bottom; + ImplSaveFrameState( pFrame ); + pFrame->maFrameData.mbDefPos = TRUE; + + // CreateHDC in the main thread + pFrame->ReleaseGraphics( pFrame->GetGraphics() ); + + return pFrame; +} + +// ======================================================================= + +// Uebersetzungstabelle von System-Keycodes in StarView-Keycodes +#define KEY_TAB_SIZE 146 + +static USHORT aImplTranslateKeyTab[KEY_TAB_SIZE] = +{ + // StarView-Code System-Code Index + 0, // 0 + 0, // VK_LBUTTON 1 + 0, // VK_RBUTTON 2 + 0, // VK_CANCEL 3 + 0, // VK_MBUTTON 4 + 0, // 5 + 0, // 6 + 0, // 7 + KEY_BACKSPACE, // VK_BACK 8 + KEY_TAB, // VK_TAB 9 + 0, // 10 + 0, // 11 + 0, // VK_CLEAR 12 + KEY_RETURN, // VK_RETURN 13 + 0, // 14 + 0, // 15 + 0, // VK_SHIFT 16 + 0, // VK_CONTROL 17 + 0, // VK_MENU 18 + 0, // VK_PAUSE 19 + 0, // VK_CAPITAL 20 + 0, // 21 + 0, // 22 + 0, // 23 + 0, // 24 + 0, // 25 + 0, // 26 + KEY_ESCAPE, // VK_ESCAPE 27 + 0, // 28 + 0, // 29 + 0, // 30 + 0, // 31 + KEY_SPACE, // VK_SPACE 32 + KEY_PAGEUP, // VK_PRIOR 33 + KEY_PAGEDOWN, // VK_NEXT 34 + KEY_END, // VK_END 35 + KEY_HOME, // VK_HOME 36 + KEY_LEFT, // VK_LEFT 37 + KEY_UP, // VK_UP 38 + KEY_RIGHT, // VK_RIGHT 39 + KEY_DOWN, // VK_DOWN 40 + 0, // VK_SELECT 41 + 0, // VK_PRINT 42 + 0, // VK_EXECUTE 43 + 0, // VK_SNAPSHOT 44 + KEY_INSERT, // VK_INSERT 45 + KEY_DELETE, // VK_DELETE 46 + KEY_HELP, // VK_HELP 47 + KEY_0, // 48 + KEY_1, // 49 + KEY_2, // 50 + KEY_3, // 51 + KEY_4, // 52 + KEY_5, // 53 + KEY_6, // 54 + KEY_7, // 55 + KEY_8, // 56 + KEY_9, // 57 + 0, // 58 + 0, // 59 + 0, // 60 + 0, // 61 + 0, // 62 + 0, // 63 + 0, // 64 + KEY_A, // 65 + KEY_B, // 66 + KEY_C, // 67 + KEY_D, // 68 + KEY_E, // 69 + KEY_F, // 70 + KEY_G, // 71 + KEY_H, // 72 + KEY_I, // 73 + KEY_J, // 74 + KEY_K, // 75 + KEY_L, // 76 + KEY_M, // 77 + KEY_N, // 78 + KEY_O, // 79 + KEY_P, // 80 + KEY_Q, // 81 + KEY_R, // 82 + KEY_S, // 83 + KEY_T, // 84 + KEY_U, // 85 + KEY_V, // 86 + KEY_W, // 87 + KEY_X, // 88 + KEY_Y, // 89 + KEY_Z, // 90 + 0, // VK_LWIN 91 + 0, // VK_RWIN 92 + KEY_CONTEXTMENU, // VK_APPS 93 + 0, // 94 + 0, // 95 + KEY_0, // VK_NUMPAD0 96 + KEY_1, // VK_NUMPAD1 97 + KEY_2, // VK_NUMPAD2 98 + KEY_3, // VK_NUMPAD3 99 + KEY_4, // VK_NUMPAD4 100 + KEY_5, // VK_NUMPAD5 101 + KEY_6, // VK_NUMPAD6 102 + KEY_7, // VK_NUMPAD7 103 + KEY_8, // VK_NUMPAD8 104 + KEY_9, // VK_NUMPAD9 105 + KEY_MULTIPLY, // VK_MULTIPLY 106 + KEY_ADD, // VK_ADD 107 + KEY_COMMA, // VK_SEPARATOR 108 + KEY_SUBTRACT, // VK_SUBTRACT 109 + KEY_POINT, // VK_DECIMAL 110 + KEY_DIVIDE, // VK_DIVIDE 111 + KEY_F1, // VK_F1 112 + KEY_F2, // VK_F2 113 + KEY_F3, // VK_F3 114 + KEY_F4, // VK_F4 115 + KEY_F5, // VK_F5 116 + KEY_F6, // VK_F6 117 + KEY_F7, // VK_F7 118 + KEY_F8, // VK_F8 119 + KEY_F9, // VK_F9 120 + KEY_F10, // VK_F10 121 + KEY_F11, // VK_F11 122 + KEY_F12, // VK_F12 123 + KEY_F13, // VK_F13 124 + KEY_F14, // VK_F14 125 + KEY_F15, // VK_F15 126 + KEY_F16, // VK_F16 127 + KEY_F17, // VK_F17 128 + KEY_F18, // VK_F18 129 + KEY_F19, // VK_F19 130 + KEY_F20, // VK_F20 131 + KEY_F21, // VK_F21 132 + KEY_F22, // VK_F22 133 + KEY_F23, // VK_F23 134 + KEY_F24, // VK_F24 135 + 0, // 136 + 0, // 137 + 0, // 138 + 0, // 139 + 0, // 140 + 0, // 141 + 0, // 142 + 0, // 143 + 0, // NUMLOCK 144 + 0 // SCROLLLOCK 145 +}; + +// ======================================================================= + +long ImplSalCallbackDummy( void*, SalFrame*, USHORT, const void* ) +{ + return 0; +} + +// ----------------------------------------------------------------------- + +static UINT ImplSalGetWheelScrollLines() +{ + UINT nScrLines = 0; + HWND hWndMsWheel = WIN_FindWindow( MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE ); + if ( hWndMsWheel ) + { + UINT nGetScrollLinesMsgId = RegisterWindowMessage( MSH_SCROLL_LINES ); + nScrLines = (UINT)ImplSendMessage( hWndMsWheel, nGetScrollLinesMsgId, 0, 0 ); + } + + if ( !nScrLines ) + nScrLines = SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0 ); + + if ( !nScrLines ) + nScrLines = 3; + + return nScrLines; +} + +// ----------------------------------------------------------------------- + +static void ImplSalCalcFullScreenSize( const SalFrame* pFrame, + int& rX, int& rY, int& rDX, int& rDY ) +{ + // set window to screen size + int nFrameX; + int nFrameY; + int nCaptionY; + int nScreenDX; + int nScreenDY; + + if ( pFrame->maFrameData.mbSizeBorder ) + { + nFrameX = GetSystemMetrics( SM_CXFRAME ); + nFrameY = GetSystemMetrics( SM_CYFRAME ); + } + else if ( pFrame->maFrameData.mbBorder ) + { + nFrameX = GetSystemMetrics( SM_CXBORDER ); + nFrameY = GetSystemMetrics( SM_CYBORDER ); + } + else + { + nFrameX = 0; + nFrameY = 0; + } + if ( pFrame->maFrameData.mbCaption ) + nCaptionY = GetSystemMetrics( SM_CYCAPTION ); + else + nCaptionY = 0; + + nScreenDX = GetSystemMetrics( SM_CXSCREEN ); + nScreenDY = GetSystemMetrics( SM_CYSCREEN ); + + rX = -nFrameX; + rY = -(nFrameY+nCaptionY); + rDX = nScreenDX+(nFrameX*2); + rDY = nScreenDY+(nFrameY*2)+nCaptionY; +} + +// ----------------------------------------------------------------------- + +static void ImplSalFrameFullScreenPos( SalFrame* pFrame, BOOL bAlways = FALSE ) +{ + if ( bAlways || !IsIconic( pFrame->maFrameData.mhWnd ) ) + { + // set window to screen size + int nX; + int nY; + int nWidth; + int nHeight; + ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight ); + SetWindowPos( pFrame->maFrameData.mhWnd, 0, + nX, nY, nWidth, nHeight, + SWP_NOZORDER | SWP_NOACTIVATE ); + } +} + +// ----------------------------------------------------------------------- + +SalFrame::SalFrame() +{ + SalData* pSalData = GetSalData(); + + maFrameData.mhWnd = 0; + maFrameData.mhCursor = LoadCursor( 0, IDC_ARROW ); + maFrameData.mhDefIMEContext = 0; + maFrameData.mpGraphics = NULL; + maFrameData.mpInst = NULL; + maFrameData.mpProc = ImplSalCallbackDummy; + maFrameData.mnInputLang = 0; + maFrameData.mnInputCodePage = 0; + maFrameData.mbGraphics = FALSE; + maFrameData.mbCaption = FALSE; + maFrameData.mbBorder = FALSE; + maFrameData.mbSizeBorder = FALSE; + maFrameData.mbFullScreen = FALSE; + maFrameData.mbPresentation = FALSE; + maFrameData.mbInShow = FALSE; + maFrameData.mbRestoreMaximize = FALSE; + maFrameData.mbInMoveMsg = FALSE; + maFrameData.mbInSizeMsg = FALSE; + maFrameData.mbFullScreenToolWin = FALSE; + maFrameData.mbDefPos = TRUE; + maFrameData.mbOverwriteState = TRUE; + maFrameData.mbIME = FALSE; + maFrameData.mbHandleIME = FALSE; + maFrameData.mbSpezIME = FALSE; + maFrameData.mbAtCursorIME = FALSE; + maFrameData.mbCompositionMode = FALSE; + maFrameData.mbCandidateMode = FALSE; + memset( &maFrameData.maState, 0, sizeof( SalFrameState ) ); + maFrameData.maSysData.nSize = sizeof( SystemEnvData ); + + // Daten ermitteln, wenn erster Frame angelegt wird + if ( !pSalData->mpFirstFrame ) + { + if ( !aSalShlData.mnWheelMsgId ) + aSalShlData.mnWheelMsgId = RegisterWindowMessage( MSH_MOUSEWHEEL ); + if ( !aSalShlData.mnWheelScrollLines ) + aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines(); + } + + // insert frame in framelist + maFrameData.mpNextFrame = pSalData->mpFirstFrame; + pSalData->mpFirstFrame = this; +} + +// ----------------------------------------------------------------------- + +SalFrame::~SalFrame() +{ + SalData* pSalData = GetSalData(); + + // destroy saved DC + if ( maFrameData.mpGraphics ) + { + if ( maFrameData.mpGraphics->maGraphicsData.mhDefPal ) + SelectPalette( maFrameData.mpGraphics->maGraphicsData.mhDC, maFrameData.mpGraphics->maGraphicsData.mhDefPal, TRUE ); + ImplSalDeInitGraphics( &(maFrameData.mpGraphics->maGraphicsData) ); + ReleaseDC( maFrameData.mhWnd, maFrameData.mpGraphics->maGraphicsData.mhDC ); + delete maFrameData.mpGraphics; + } + + if ( maFrameData.mhWnd ) + { + // reset mouse leave data + if ( pSalData->mhWantLeaveMsg == maFrameData.mhWnd ) + { + pSalData->mhWantLeaveMsg = 0; + if ( pSalData->mpMouseLeaveTimer ) + { + delete pSalData->mpMouseLeaveTimer; + pSalData->mpMouseLeaveTimer = NULL; + } + } + + // destroy system frame + if ( !DestroyWindow( maFrameData.mhWnd ) ) + SetWindowPtr( maFrameData.mhWnd, 0 ); + } + + // remove frame from framelist + if ( this == pSalData->mpFirstFrame ) + pSalData->mpFirstFrame = maFrameData.mpNextFrame; + else + { + SalFrame* pTempFrame = pSalData->mpFirstFrame; + while ( pTempFrame->maFrameData.mpNextFrame != this ) + pTempFrame = pTempFrame->maFrameData.mpNextFrame; + + pTempFrame->maFrameData.mpNextFrame = maFrameData.mpNextFrame; + } +} + +// ----------------------------------------------------------------------- + +SalGraphics* SalFrame::GetGraphics() +{ + if ( maFrameData.mbGraphics ) + return NULL; + + if ( !maFrameData.mpGraphics ) + { + HDC hDC = GetDC( maFrameData.mhWnd ); + if ( hDC ) + { + SalData* pSalData = GetSalData(); + maFrameData.mpGraphics = new SalGraphics; + maFrameData.mpGraphics->maGraphicsData.mhDC = hDC; + maFrameData.mpGraphics->maGraphicsData.mhWnd = maFrameData.mhWnd; + maFrameData.mpGraphics->maGraphicsData.mbPrinter = FALSE; + maFrameData.mpGraphics->maGraphicsData.mbVirDev = FALSE; + maFrameData.mpGraphics->maGraphicsData.mbWindow = TRUE; + maFrameData.mpGraphics->maGraphicsData.mbScreen = TRUE; + if ( pSalData->mhDitherPal ) + { + maFrameData.mpGraphics->maGraphicsData.mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); + RealizePalette( hDC ); + } + ImplSalInitGraphics( &(maFrameData.mpGraphics->maGraphicsData) ); + maFrameData.mbGraphics = TRUE; + } + } + else + maFrameData.mbGraphics = TRUE; + + return maFrameData.mpGraphics; +} + +// ----------------------------------------------------------------------- + +void SalFrame::ReleaseGraphics( SalGraphics* ) +{ + maFrameData.mbGraphics = FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL SalFrame::PostEvent( void* pData ) +{ + return (BOOL)ImplPostMessage( maFrameData.mhWnd, SAL_MSG_USEREVENT, 0, (LPARAM)pData ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetTitle( const XubString& rTitle ) +{ + DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalFrame::SetTitle(): WCHAR != sal_Unicode" ); + + if ( !SetWindowTextW( maFrameData.mhWnd, rTitle.GetBuffer() ) ) + { + ByteString aAnsiTitle = ImplSalGetWinAnsiString( rTitle ); + SetWindowTextA( maFrameData.mhWnd, aAnsiTitle.GetBuffer() ); + } +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetIcon( USHORT nIcon ) +{ +// ImplSendMessage( maFrameData.mhWnd, WM_SETICON, FALSE, hSmIcon ); +// ImplSendMessage( maFrameData.mhWnd, WM_SETICON, TRUE, hIcon ); +} + +// ----------------------------------------------------------------------- + +static void ImplSalShow( HWND hWnd, BOOL bVisible ) +{ + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( !pFrame ) + return; + + if ( bVisible ) + { + pFrame->maFrameData.mbDefPos = FALSE; + pFrame->maFrameData.mbOverwriteState = TRUE; + pFrame->maFrameData.mbInShow = TRUE; + ShowWindow( hWnd, pFrame->maFrameData.mnShowState ); + // Damit Taskleiste unter W98 auch gleich ausgeblendet wird + if ( pFrame->maFrameData.mbPresentation ) + { + HWND hWndParent = ::GetParent( hWnd ); + if ( hWndParent ) + SetForegroundWindow( hWndParent ); + SetForegroundWindow( hWnd ); + } + pFrame->maFrameData.mnShowState = SW_SHOW; + pFrame->maFrameData.mbInShow = FALSE; + UpdateWindow( hWnd ); + } + else + { + if ( pFrame->maFrameData.mbFullScreen && + pFrame->maFrameData.mbPresentation && + !::GetParent( hWnd ) ) + { + // Damit im Impress-Player in der Taskleiste nicht durch + // einen Windows-Fehler hin- und wieder mal ein leerer + // Button stehen bleibt, muessen wir hier die Taskleiste + // etwas austricksen. Denn wenn wir im FullScreenMode sind + // und das Fenster hiden kommt Windows anscheinend etwas aus + // dem tritt und somit minimieren wir das Fenster damit es + // nicht flackert + ANIMATIONINFO aInfo; + aInfo.cbSize = sizeof( aInfo ); + SystemParametersInfo( SPI_GETANIMATION, 0, &aInfo, 0 ); + if ( aInfo.iMinAnimate ) + { + int nOldAni = aInfo.iMinAnimate; + aInfo.iMinAnimate = 0; + SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 ); + ShowWindow( pFrame->maFrameData.mhWnd, SW_SHOWMINNOACTIVE ); + aInfo.iMinAnimate = nOldAni; + SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 ); + } + else + ShowWindow( hWnd, SW_SHOWMINNOACTIVE ); + ShowWindow( hWnd, SW_HIDE ); + } + else + ShowWindow( hWnd, SW_HIDE ); + } +} + +// ----------------------------------------------------------------------- + +void SalFrame::Show( BOOL bVisible ) +{ + // Send this Message to the window, because this only works + // in the thread of the window, which has create this window + ImplSendMessage( maFrameData.mhWnd, SAL_MSG_SHOW, bVisible, 0 ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::Enable( BOOL bEnable ) +{ + EnableWindow( maFrameData.mhWnd, bEnable ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetMinClientSize( long nWidth, long nHeight ) +{ +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetClientSize( long nWidth, long nHeight ) +{ + BOOL bVisible = (GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) != 0; + if ( !bVisible ) + maFrameData.mnShowState = SW_SHOWNORMAL; + else + { + if ( IsIconic( maFrameData.mhWnd ) || IsZoomed( maFrameData.mhWnd ) ) + ShowWindow( maFrameData.mhWnd, SW_RESTORE ); + } + + // Fenstergroesse berechnen + RECT aWinRect; + aWinRect.left = 0; + aWinRect.right = (int)nWidth-1; + aWinRect.top = 0; + aWinRect.bottom = (int)nHeight-1; + AdjustWindowRectEx( &aWinRect, + GetWindowStyle( maFrameData.mhWnd ), + FALSE, + GetWindowExStyle( maFrameData.mhWnd ) ); + nWidth = aWinRect.right - aWinRect.left + 1; + nHeight = aWinRect.bottom - aWinRect.top + 1; + + // Position so berechnen, das Fenster zentiert auf dem Desktop + // angezeigt wird + int nX; + int nY; + int nScreenX; + int nScreenY; + int nScreenWidth; + int nScreenHeight; + +#if ( WINVER >= 0x0400 ) + W40IF + { + RECT aRect; + SystemParametersInfo( SPI_GETWORKAREA, 0, &aRect, 0 ); + nScreenX = aRect.left; + nScreenY = aRect.top; + nScreenWidth = aRect.right-aRect.left; + nScreenHeight = aRect.bottom-aRect.top; + } + W40ELSE +#endif +#ifndef W40ONLY + { + nScreenX = 0; + nScreenY = 0; + nScreenWidth = GetSystemMetrics( SM_CXSCREEN ); + nScreenHeight = GetSystemMetrics( SM_CYSCREEN ); + } +#endif + + if ( maFrameData.mbDefPos ) + { + nX = (nScreenWidth-nWidth)/2 + nScreenX; + nY = (nScreenHeight-nHeight)/2 + nScreenY; + if ( bVisible ) + maFrameData.mbDefPos = FALSE; + } + else + { + RECT aWinRect; + GetWindowRect( maFrameData.mhWnd, &aWinRect ); + nX = aWinRect.left; + nY = aWinRect.top; + if ( nX+nWidth > nScreenX+nScreenWidth ) + nX = (nScreenX+nScreenWidth) - nWidth; + if ( nY+nHeight > nScreenY+nScreenHeight ) + nY = (nScreenY+nScreenHeight) - nHeight; + if ( nX < nScreenX ) + nX = nScreenX; + if ( nY < nScreenY ) + nY = nScreenY; + } + + SetWindowPos( maFrameData.mhWnd, 0, nX, nY, (int)nWidth, (int)nHeight, SWP_NOZORDER | SWP_NOACTIVATE ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::GetClientSize( long& rWidth, long& rHeight ) +{ + rWidth = maFrameData.mnWidth; + rHeight = maFrameData.mnHeight; +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetWindowState( const SalFrameState* pState ) +{ + // Wir testen, ob das Fenster ueberhaupt auf den Bildschirm passt, damit + // nicht wenn die Bildschirm-Aufloesung geaendert wurde, das Fenster aus + // diesem herausragt + int nX; + int nY; + int nWidth; + int nHeight; + int nScreenX; + int nScreenY; + int nScreenWidth; + int nScreenHeight; + +#if ( WINVER >= 0x0400 ) + W40IF + { + RECT aRect; + SystemParametersInfo( SPI_GETWORKAREA, 0, &aRect, 0 ); + nScreenX = aRect.left; + nScreenY = aRect.top; + nScreenWidth = aRect.right-aRect.left; + nScreenHeight = aRect.bottom-aRect.top; + } + W40ELSE +#endif +#ifndef W40ONLY + { + nScreenX = 0; + nScreenY = 0; + nScreenWidth = GetSystemMetrics( SM_CXSCREEN ); + nScreenHeight = GetSystemMetrics( SM_CYSCREEN ); + } +#endif + + // Fenster-Position/Groesse in den Bildschirm einpassen + nX = (int)pState->mnX; + nY = (int)pState->mnY; + nWidth = (int)pState->mnWidth; + nHeight = (int)pState->mnHeight; + if ( nX < nScreenX ) + nX = nScreenX; + if ( nY < nScreenY ) + nY = nScreenY; + if ( nScreenWidth < nWidth ) + nWidth = nScreenWidth; + if ( nScreenHeight < nHeight ) + nHeight = nScreenHeight; + + // Restore-Position setzen + WINDOWPLACEMENT aPlacement; + aPlacement.length = sizeof( aPlacement ); + GetWindowPlacement( maFrameData.mhWnd, &aPlacement ); + + // Status setzen + BOOL bVisible = (GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) != 0; + if ( !bVisible ) + { + aPlacement.showCmd = SW_HIDE; + + if ( maFrameData.mbOverwriteState ) + { + if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED ) + maFrameData.mnShowState = SW_SHOWMINIMIZED; + else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED ) + maFrameData.mnShowState = SW_SHOWMAXIMIZED; + else + maFrameData.mnShowState = SW_SHOWNORMAL; + } + } + else + { + if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED ) + { + if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED ) + aPlacement.flags |= WPF_RESTORETOMAXIMIZED; + aPlacement.showCmd = SW_SHOWMINIMIZED; + } + else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED ) + aPlacement.showCmd = SW_SHOWMAXIMIZED; + else + aPlacement.showCmd = SW_RESTORE; + } + + // Wenn Fenster nicht minimiert/maximiert ist oder nicht optisch + // umgesetzt werden muss, dann SetWindowPos() benutzen, da + // SetWindowPlacement() die TaskBar mit einrechnet + if ( !IsIconic( maFrameData.mhWnd ) && !IsZoomed( maFrameData.mhWnd ) && + (!bVisible || (aPlacement.showCmd == SW_RESTORE)) ) + { + SetWindowPos( maFrameData.mhWnd, 0, + nX, nY, nWidth, nHeight, + SWP_NOZORDER | SWP_NOACTIVATE ); + } + else + { + aPlacement.rcNormalPosition.left = nX-nScreenX; + aPlacement.rcNormalPosition.top = nY-nScreenY; + aPlacement.rcNormalPosition.right = nX+nWidth-nScreenX; + aPlacement.rcNormalPosition.bottom = nY+nHeight-nScreenY; + SetWindowPlacement( maFrameData.mhWnd, &aPlacement ); + } +} + +// ----------------------------------------------------------------------- + +BOOL SalFrame::GetWindowState( SalFrameState* pState ) +{ + if ( maFrameData.maState.mnWidth && maFrameData.maState.mnHeight ) + { + *pState = maFrameData.maState; + return TRUE; + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +void SalFrame::ShowFullScreen( BOOL bFullScreen ) +{ + if ( maFrameData.mbFullScreen == bFullScreen ) + return; + + maFrameData.mbFullScreen = bFullScreen; + if ( bFullScreen ) + { +#if ( WINVER >= 0x0400 ) + // Damit Taskleiste von Windows ausgeblendet wird + DWORD nExStyle = GetWindowExStyle( maFrameData.mhWnd ); + if ( nExStyle & WS_EX_TOOLWINDOW ) + { + maFrameData.mbFullScreenToolWin = TRUE; + nExStyle &= ~WS_EX_TOOLWINDOW; + SetWindowExStyle( maFrameData.mhWnd, nExStyle ); + } +#endif + + // save old position + GetWindowRect( maFrameData.mhWnd, &maFrameData.maFullScreenRect ); + + // save show state + maFrameData.mnFullScreenShowState = maFrameData.mnShowState; + if ( !(GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) ) + maFrameData.mnShowState = SW_SHOW; + + // set window to screen size + ImplSalFrameFullScreenPos( this, TRUE ); + } + else + { + // wenn ShowState wieder hergestellt werden muss, hiden wir zuerst + // das Fenster, damit es nicht so sehr flackert + BOOL bVisible = (GetWindowStyle( maFrameData.mhWnd ) & WS_VISIBLE) != 0; + if ( bVisible && (maFrameData.mnShowState != maFrameData.mnFullScreenShowState) ) + ShowWindow( maFrameData.mhWnd, SW_HIDE ); + +#if ( WINVER >= 0x0400 ) + if ( maFrameData.mbFullScreenToolWin ) + SetWindowExStyle( maFrameData.mhWnd, GetWindowExStyle( maFrameData.mhWnd ) | WS_EX_TOOLWINDOW ); + maFrameData.mbFullScreenToolWin = FALSE; +#endif + + SetWindowPos( maFrameData.mhWnd, 0, + maFrameData.maFullScreenRect.left, + maFrameData.maFullScreenRect.top, + maFrameData.maFullScreenRect.right-maFrameData.maFullScreenRect.left, + maFrameData.maFullScreenRect.bottom-maFrameData.maFullScreenRect.top, + SWP_NOZORDER | SWP_NOACTIVATE ); + + // restore show state + if ( maFrameData.mnShowState != maFrameData.mnFullScreenShowState ) + { + maFrameData.mnShowState = maFrameData.mnFullScreenShowState; + if ( bVisible ) + { + maFrameData.mbInShow = TRUE; + ShowWindow( maFrameData.mhWnd, maFrameData.mnShowState ); + maFrameData.mbInShow = FALSE; + UpdateWindow( maFrameData.mhWnd ); + } + } + } +} + +// ----------------------------------------------------------------------- + +void SalFrame::StartPresentation( BOOL bStart ) +{ + if ( maFrameData.mbPresentation == bStart ) + return; + + maFrameData.mbPresentation = bStart; + + SalData* pSalData = GetSalData(); + if ( bStart ) + { +#if ( WINVER >= 0x0400 ) + if ( !pSalData->mpSageEnableProc ) + { + if ( pSalData->mnSageStatus != DISABLE_AGENT ) + { + OFSTRUCT aOS; + OpenFile( "SAGE.DLL", &aOS, OF_EXIST ); + + if ( !aOS.nErrCode ) + { + pSalData->mhSageInst = LoadLibrary( aOS.szPathName ); + pSalData->mpSageEnableProc = (SysAgt_Enable_PROC)GetProcAddress( pSalData->mhSageInst, "System_Agent_Enable" ); + } + else + pSalData->mnSageStatus = DISABLE_AGENT; + } + } + + if ( pSalData->mpSageEnableProc ) + { + pSalData->mnSageStatus = pSalData->mpSageEnableProc( GET_AGENT_STATUS ); + if ( pSalData->mnSageStatus == ENABLE_AGENT ) + pSalData->mpSageEnableProc( DISABLE_AGENT ); + } +#endif + + // Bildschirmschoner ausschalten, wenn Praesentation laueft + SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0, + &(pSalData->mbScrSvrEnabled), 0 ); + if ( pSalData->mbScrSvrEnabled ) + SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0 ); + } + else + { + // Bildschirmschoner wieder einschalten + if ( pSalData->mbScrSvrEnabled ) + SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, pSalData->mbScrSvrEnabled, 0, 0 ); + +#if ( WINVER >= 0x0400 ) + // Systemagenten wieder aktivieren + if ( pSalData->mnSageStatus == ENABLE_AGENT ) + pSalData->mpSageEnableProc( pSalData->mnSageStatus ); +#endif + } +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetAlwaysOnTop( BOOL bOnTop ) +{ + HWND hWnd; + if ( bOnTop ) + hWnd = HWND_TOPMOST; + else + hWnd = HWND_NOTOPMOST; + SetWindowPos( maFrameData.mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE ); +} + +// ----------------------------------------------------------------------- + +static void ImplSalToTop( HWND hWnd, USHORT nFlags ) +{ + if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK ) + SetForegroundWindow( hWnd ); + if ( !IsIconic( hWnd ) ) + { + SetFocus( hWnd ); + + // Windows behauptet oefters mal, das man den Focus hat, obwohl + // man diesen nicht hat. Wenn dies der Fall ist, dann versuchen + // wir diesen auch ganz richtig zu bekommen. + if ( ::GetFocus() == hWnd ) + SetForegroundWindow( hWnd ); + } + else + { + if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN ) + { + if ( GetWindowPtr( hWnd )->maFrameData.mbRestoreMaximize ) + ShowWindow( hWnd, SW_MAXIMIZE ); + else + ShowWindow( hWnd, SW_RESTORE ); + } + } +} + +// ----------------------------------------------------------------------- + +void SalFrame::ToTop( USHORT nFlags ) +{ + // Send this Message to the window, because SetFocus() only work + // in the thread of the window, which has create this window + ImplSendMessage( maFrameData.mhWnd, SAL_MSG_TOTOP, nFlags, 0 ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetPointer( PointerStyle ePointerStyle ) +{ + struct ImplPtrData + { + HCURSOR mhCursor; + LPCSTR mnSysId; + UINT mnOwnId; + }; + + static ImplPtrData aImplPtrTab[POINTER_COUNT] = + { + { 0, IDC_ARROW, 0 }, // POINTER_ARROW + { 0, 0, SAL_RESID_POINTER_NULL }, // POINTER_NULL + { 0, IDC_WAIT, 0 }, // POINTER_WAIT + { 0, IDC_IBEAM, 0 }, // POINTER_TEXT +#if ( WINVER >= 0x0400 ) + { 0, IDC_HELP, 0 }, // POINTER_HELP +#else + { 0, 0, SAL_RESID_POINTER_HELP }, // POINTER_HELP +#endif + { 0, 0, SAL_RESID_POINTER_CROSS }, // POINTER_CROSS + { 0, 0, SAL_RESID_POINTER_MOVE }, // POINTER_MOVE + { 0, IDC_SIZENS, 0 }, // POINTER_NSIZE + { 0, IDC_SIZENS, 0 }, // POINTER_SSIZE + { 0, IDC_SIZEWE, 0 }, // POINTER_WSIZE + { 0, IDC_SIZEWE, 0 }, // POINTER_ESIZE + { 0, IDC_SIZENWSE, 0 }, // POINTER_NWSIZE + { 0, IDC_SIZENESW, 0 }, // POINTER_NESIZE + { 0, IDC_SIZENESW, 0 }, // POINTER_SWSIZE + { 0, IDC_SIZENWSE, 0 }, // POINTER_SESIZE + { 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_NSIZE + { 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_SSIZE + { 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_WSIZE + { 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_ESIZE + { 0, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_NWSIZE + { 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_NESIZE + { 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_SWSIZE + { 0, IDC_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, 0, SAL_RESID_POINTER_NOTALLOWED }, // 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 + }; + +#if POINTER_COUNT != 86 +#error New Pointer must be defined! +#endif + + // Mousepointer loaded ? + if ( !aImplPtrTab[ePointerStyle].mhCursor ) + { + if ( aImplPtrTab[ePointerStyle].mnOwnId ) + aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId ); + else + aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( 0, aImplPtrTab[ePointerStyle].mnSysId ); + } + + // Unterscheidet sich der Mauspointer, dann den neuen setzen + if ( maFrameData.mhCursor != aImplPtrTab[ePointerStyle].mhCursor ) + { + maFrameData.mhCursor = aImplPtrTab[ePointerStyle].mhCursor; + SetCursor( maFrameData.mhCursor ); + } +} + +// ----------------------------------------------------------------------- + +void SalFrame::CaptureMouse( BOOL bCapture ) +{ + // Send this Message to the window, because CaptureMouse() only work + // in the thread of the window, which has create this window + int nMsg; + if ( bCapture ) + nMsg = SAL_MSG_CAPTUREMOUSE; + else + nMsg = SAL_MSG_RELEASEMOUSE; + ImplSendMessage( maFrameData.mhWnd, nMsg, 0, 0 ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetPointerPos( long nX, long nY ) +{ + POINT aPt; + aPt.x = (int)nX; + aPt.y = (int)nY; + ClientToScreen( maFrameData.mhWnd, &aPt ); + SetCursorPos( aPt.x, aPt.y ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::Flush() +{ + GdiFlush(); +} + +// ----------------------------------------------------------------------- + +void SalFrame::Sync() +{ + GdiFlush(); +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetInputContext( SalInputContext* pContext ) +{ + BOOL bIME = pContext->mnOptions != 0; + if ( bIME == maFrameData.mbIME ) + return; + + maFrameData.mbIME = bIME; + if ( !bIME ) + { + ImmAssociateContext( maFrameData.mhWnd, 0 ); + maFrameData.mbHandleIME = FALSE; + } + else + { + if ( maFrameData.mhDefIMEContext ) + { + ImmAssociateContext( maFrameData.mhWnd, maFrameData.mhDefIMEContext ); + UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY ); + maFrameData.mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; + maFrameData.mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; + maFrameData.mbHandleIME = !maFrameData.mbSpezIME; + } + } +} + +// ----------------------------------------------------------------------- + +void SalFrame::UpdateExtTextInputArea() +{ +} + +// ----------------------------------------------------------------------- + +void SalFrame::EndExtTextInput( USHORT nFlags ) +{ + HWND hWnd = maFrameData.mhWnd; + HIMC hIMC = ImmGetContext( hWnd ); + if ( hIMC ) + { + DWORD nIndex; + if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE ) + nIndex = CPS_COMPLETE; + else + nIndex = CPS_CANCEL; + + ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 ); + ImmReleaseContext( hWnd, hIMC ); + } +} + +// ----------------------------------------------------------------------- + +static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf, + UINT& rCount, UINT nMaxSize, + const sal_Char* pReplace ) +{ + DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalFrame::ImplGetKeyNameTextW(): WCHAR != sal_Unicode" ); + + WCHAR aKeyBuf[350]; + int nKeyLen = 0; + if ( lParam ) + { + nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, sizeof( aKeyBuf ) / sizeof( sal_Unicode ) ); + if ( nKeyLen > 0 ) + { + // Convert name, so that the keyname start with an upper + // char and the rest of the word are in lower chars + CharLowerBuffW( aKeyBuf, nKeyLen ); + CharUpperBuffW( aKeyBuf, 1 ); + WCHAR cTempChar; + WCHAR* pKeyBuf = aKeyBuf; + while ( (cTempChar = *pKeyBuf) != 0 ) + { + if ( (cTempChar == '+') || (cTempChar == '-') || + (cTempChar == ' ') || (cTempChar == '.') ) + CharUpperBuffW( pKeyBuf+1, 1 ); + pKeyBuf++; + } + } + else + { + sal_Char aAnsiKeyBuf[250]; + int nAnsiKeyLen = GetKeyNameTextA( lParam, aAnsiKeyBuf, sizeof( aAnsiKeyBuf ) / sizeof( sal_Char ) ); + if ( nAnsiKeyLen ) + { + // Convert name, so that the keyname start with an upper + // char and the rest of the word are in lower chars + CharLowerBuffA( aAnsiKeyBuf, nAnsiKeyLen ); + CharUpperBuffA( aAnsiKeyBuf, 1 ); + sal_Char cTempChar; + sal_Char* pAnsiKeyBuf = aAnsiKeyBuf; + while ( (cTempChar = *pAnsiKeyBuf) != 0 ) + { + if ( (cTempChar == '+') || (cTempChar == '-') || + (cTempChar == ' ') || (cTempChar == '.') ) + CharUpperBuffA( pAnsiKeyBuf+1, 1 ); + pAnsiKeyBuf++; + } + + // Convert to Unicode and copy the data in the Unicode Buffer + nKeyLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, aAnsiKeyBuf, nAnsiKeyLen, aKeyBuf, sizeof( aKeyBuf ) / sizeof( sal_Unicode ) ); + } + } + } + + if ( (nKeyLen > 0) || pReplace ) + { + if ( rCount ) + { + pBuf[rCount] = '+'; + rCount++; + } + + if ( nKeyLen ) + { + memcpy( pBuf+rCount, aKeyBuf, nKeyLen*sizeof( sal_Unicode ) ); + rCount += nKeyLen; + } + else + { + while ( *pReplace ) + { + pBuf[rCount] = *pReplace; + rCount++; + pReplace++; + } + } + } + else + rCount = 0; +} + +// ----------------------------------------------------------------------- + +XubString SalFrame::GetKeyName( USHORT nKeyCode ) +{ + XubString aKeyCode; + sal_Unicode aKeyBuf[350]; + UINT nKeyBufLen = 0; + UINT nSysCode; + + if ( nKeyCode & KEY_MOD2 ) + { + nSysCode = MapVirtualKey( VK_MENU, 0 ); + nSysCode = (nSysCode << 16) | (((ULONG)1) << 25); + ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, + sizeof( aKeyBuf ) / sizeof( sal_Unicode ), + "Alt" ); + } + + if ( nKeyCode & KEY_MOD1 ) + { + nSysCode = MapVirtualKey( VK_CONTROL, 0 ); + nSysCode = (nSysCode << 16) | (((ULONG)1) << 25); + ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, + sizeof( aKeyBuf ) / sizeof( sal_Unicode ), + "Ctrl" ); + } + + if ( nKeyCode & KEY_SHIFT ) + { + nSysCode = MapVirtualKey( VK_SHIFT, 0 ); + nSysCode = (nSysCode << 16) | (((ULONG)1) << 25); + ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, + sizeof( aKeyBuf ) / sizeof( sal_Unicode ), + "Shift" ); + } + + USHORT nCode = nKeyCode & 0x0FFF; + ULONG nSysCode2 = 0; + sal_Char* pReplace = NULL; + sal_Unicode cSVCode = 0; + sal_Char aFBuf[4]; + nSysCode = 0; + + if ( (nCode >= KEY_0) && (nCode <= KEY_9) ) + cSVCode = '0' + (nCode - KEY_0); + else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) ) + cSVCode = 'A' + (nCode - KEY_A); + else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) ) + { + nSysCode = VK_F1 + (nCode - KEY_F1); + aFBuf[0] = 'F'; + if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) ) + { + aFBuf[1] = '1' + (nCode - KEY_F1); + aFBuf[2] = 0; + } + else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) ) + { + aFBuf[1] = '1'; + aFBuf[2] = '0' + (nCode - KEY_F10); + aFBuf[3] = 0; + } + else + { + aFBuf[1] = '2'; + aFBuf[2] = '0' + (nCode - KEY_F20); + aFBuf[3] = 0; + } + pReplace = aFBuf; + } + else + { + switch ( nCode ) + { + case KEY_DOWN: + nSysCode = VK_DOWN; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Down"; + break; + case KEY_UP: + nSysCode = VK_UP; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Up"; + break; + case KEY_LEFT: + nSysCode = VK_LEFT; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Left"; + break; + case KEY_RIGHT: + nSysCode = VK_RIGHT; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Right"; + break; + case KEY_HOME: + nSysCode = VK_HOME; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Home"; + break; + case KEY_END: + nSysCode = VK_END; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "End"; + break; + case KEY_PAGEUP: + nSysCode = VK_PRIOR; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Page Up"; + break; + case KEY_PAGEDOWN: + nSysCode = VK_NEXT; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Page Down"; + break; + case KEY_RETURN: + nSysCode = VK_RETURN; + pReplace = "Enter"; + break; + case KEY_ESCAPE: + nSysCode = VK_ESCAPE; + pReplace = "Escape"; + break; + case KEY_TAB: + nSysCode = VK_TAB; + pReplace = "Tab"; + break; + case KEY_BACKSPACE: + nSysCode = VK_BACK; + pReplace = "Backspace"; + break; + case KEY_SPACE: + nSysCode = VK_SPACE; + pReplace = "Space"; + break; + case KEY_INSERT: + nSysCode = VK_INSERT; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Insert"; + break; + case KEY_DELETE: + nSysCode = VK_DELETE; + nSysCode2 = (((ULONG)1) << 24); + pReplace = "Delete"; + break; + + case KEY_ADD: + cSVCode = '+'; + break; + case KEY_SUBTRACT: + cSVCode = '-'; + break; + case KEY_MULTIPLY: + cSVCode = '*'; + break; + case KEY_DIVIDE: + cSVCode = '/'; + break; + case KEY_POINT: + cSVCode = '.'; + break; + case KEY_COMMA: + cSVCode = ','; + break; + case KEY_LESS: + cSVCode = '<'; + break; + case KEY_GREATER: + cSVCode = '>'; + break; + case KEY_EQUAL: + cSVCode = '='; + break; + } + } + + if ( nSysCode ) + { + nSysCode = MapVirtualKey( (UINT)nSysCode, 0 ); + if ( nSysCode ) + nSysCode = (nSysCode << 16) | nSysCode2; + ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, + sizeof( aKeyBuf ) / sizeof( sal_Unicode ), + pReplace ); + } + else + { + if ( cSVCode ) + { + if ( !nKeyBufLen ) + { + aKeyBuf[0] = cSVCode; + nKeyBufLen = 1; + } + else + { + aKeyBuf[nKeyBufLen] = '+'; + nKeyBufLen++; + aKeyBuf[nKeyBufLen] = cSVCode; + nKeyBufLen++; + } + } + } + + if ( nKeyBufLen ) + aKeyCode.Assign( (const sal_Unicode*)aKeyBuf, nKeyBufLen ); + + return aKeyCode; +} + +// ----------------------------------------------------------------------- + +XubString SalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode ) +{ + return GetKeyName( nKeyCode ); +} + +// ----------------------------------------------------------------------- + +inline Color ImplWinColorToSal( COLORREF nColor ) +{ + return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) ); +} + +// ----------------------------------------------------------------------- + +static void ImplSalUpdateStyleFontA( const LOGFONTA& rLogFont, Font& rFont, + BOOL bOverwriteSystemCharSet ) +{ + ImplSalLogFontToFontA( rLogFont, rFont ); + if ( bOverwriteSystemCharSet && (rFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL) ) + rFont.SetCharSet( gsl_getSystemTextEncoding() ); + // Da bei einigen Windows-Einstellungen 6 Punkt eingetragen ist, + // obwohl im Dialog 8 Punkt angezeigt werden (da MS Sans Serif + // nicht skalierbar ist) vergroessern wir hier das als Hack, da + // ansonsten in russisch Symbolunterschriften nicht lesbar sind + if ( (rFont.GetName().EqualsIgnoreCaseAscii( "MS Sans Serif" ) ) && + (rFont.GetHeight() < 8) ) + rFont.SetHeight( 8 ); +} + +// ----------------------------------------------------------------------- + +static void ImplSalUpdateStyleFontW( const LOGFONTW& rLogFont, Font& rFont, + BOOL bOverwriteSystemCharSet ) +{ + ImplSalLogFontToFontW( rLogFont, rFont ); + if ( bOverwriteSystemCharSet && (rFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL) ) + rFont.SetCharSet( gsl_getSystemTextEncoding() ); + // Da bei einigen Windows-Einstellungen 6 Punkt eingetragen ist, + // obwohl im Dialog 8 Punkt angezeigt werden (da MS Sans Serif + // nicht skalierbar ist) vergroessern wir hier das als Hack, da + // ansonsten in russisch Symbolunterschriften nicht lesbar sind + if ( (rFont.GetName().EqualsIgnoreCaseAscii( "MS Sans Serif" ) ) && + (rFont.GetHeight() < 8) ) + rFont.SetHeight( 8 ); +} + +// ----------------------------------------------------------------------- + +static long ImplA2I( const BYTE* pStr ) +{ + long n = 0; + int nSign = 1; + + if ( *pStr == '-' ) + { + nSign = -1; + pStr++; + } + + while( (*pStr >= 48) && (*pStr <= 57) ) + { + n *= 10; + n += ((*pStr) - 48); + pStr++; + } + + n *= nSign; + + return n; +} + +// ----------------------------------------------------------------------- + +void SalFrame::UpdateSettings( AllSettings& rSettings ) +{ + MouseSettings aMouseSettings = rSettings.GetMouseSettings(); + aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() ); + aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) ); + aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) ); + long nDragWidth = GetSystemMetrics( SM_CXDRAG ); + long nDragHeight = GetSystemMetrics( SM_CYDRAG ); + if ( nDragWidth ) + aMouseSettings.SetStartDragWidth( nDragWidth ); + if ( nDragHeight ) + aMouseSettings.SetStartDragHeight( nDragHeight ); + HKEY hRegKey; + if ( RegOpenKey( HKEY_CURRENT_USER, + "Control Panel\\Desktop", + &hRegKey ) == ERROR_SUCCESS ) + { + BYTE aValueBuf[10]; + DWORD nValueSize = sizeof( aValueBuf ); + DWORD nType; + if ( RegQueryValueEx( hRegKey, "MenuShowDelay", 0, + &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS ) + { + if ( nType == REG_SZ ) + aMouseSettings.SetMenuDelay( (ULONG)ImplA2I( aValueBuf ) ); + } + + RegCloseKey( hRegKey ); + } + + StyleSettings aStyleSettings = rSettings.GetStyleSettings(); + BOOL bCompBorder = (aStyleSettings.GetOptions() & (STYLE_OPTION_MACSTYLE | STYLE_OPTION_UNIXSTYLE)) == 0; + aStyleSettings.SetScrollBarSize( GetSystemMetrics( SM_CXVSCROLL ) ); + aStyleSettings.SetSpinSize( GetSystemMetrics( SM_CXVSCROLL ) ); + aStyleSettings.SetCursorBlinkTime( GetCaretBlinkTime() ); + if ( bCompBorder ) + { + aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) ); + aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) ); + aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) ); + aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) ); + if ( aSalShlData.mnVersion >= 410 ) + { + aStyleSettings.SetActiveColor2( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTACTIVECAPTION ) ) ); + aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) ); + } + aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) ); + aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) ); + aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) ); + aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) ); + aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) ); + } + aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) ); + aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) ); + aStyleSettings.SetDialogColor( aStyleSettings.GetFaceColor() ); + aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() ); + aStyleSettings.SetButtonTextColor( ImplWinColorToSal( GetSysColor( COLOR_BTNTEXT ) ) ); + aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) ); + aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() ); + aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() ); + aStyleSettings.SetInfoTextColor( aStyleSettings.GetRadioCheckTextColor() ); + aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) ); + aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) ); + aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() ); + aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() ); + aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) ); + aStyleSettings.SetHighlightTextColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHTTEXT ) ) ); + aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() ); + aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() ); + if ( bCompBorder ) + { + aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) ); + aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) ); + aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) ); + aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) ); + aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) ); + aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) ); + } + // Bei hellgrau geben wir die Farbe vor, damit es besser aussieht + if ( aStyleSettings.GetFaceColor() == COL_LIGHTGRAY ) + aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) ); + else + { + // 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 ) ); + } + + // Query Fonts + int bOverwriteSystemCharSet = getenv("LC_CHARSET") != 0; + Font aMenuFont = aStyleSettings.GetMenuFont(); + Font aTitleFont = aStyleSettings.GetTitleFont(); + Font aFloatTitleFont = aStyleSettings.GetFloatTitleFont(); + Font aHelpFont = aStyleSettings.GetHelpFont(); + Font aAppFont = aStyleSettings.GetAppFont(); + Font aIconFont = aStyleSettings.GetIconFont(); + if ( aSalShlData.mbWNT ) + { + NONCLIENTMETRICSW aNonClientMetrics; + aNonClientMetrics.cbSize = sizeof( aNonClientMetrics ); + if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) ) + { + ImplSalUpdateStyleFontW( aNonClientMetrics.lfMenuFont, aMenuFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontW( aNonClientMetrics.lfCaptionFont, aTitleFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontW( aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontW( aNonClientMetrics.lfStatusFont, aHelpFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontW( aNonClientMetrics.lfMessageFont, aAppFont, bOverwriteSystemCharSet ); + + LOGFONTW aLogFont; + if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) ) + ImplSalUpdateStyleFontW( aLogFont, aIconFont, bOverwriteSystemCharSet ); + } + } + else + { + NONCLIENTMETRICSA aNonClientMetrics; + aNonClientMetrics.cbSize = sizeof( aNonClientMetrics ); + if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) ) + { + ImplSalUpdateStyleFontA( aNonClientMetrics.lfMenuFont, aMenuFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontA( aNonClientMetrics.lfCaptionFont, aTitleFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontA( aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontA( aNonClientMetrics.lfStatusFont, aHelpFont, bOverwriteSystemCharSet ); + ImplSalUpdateStyleFontA( aNonClientMetrics.lfMessageFont, aAppFont, bOverwriteSystemCharSet ); + + LOGFONTA aLogFont; + if ( SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) ) + ImplSalUpdateStyleFontA( aLogFont, aIconFont, bOverwriteSystemCharSet ); + } + } + aStyleSettings.SetMenuFont( aMenuFont ); + aStyleSettings.SetTitleFont( aTitleFont ); + aStyleSettings.SetFloatTitleFont( aFloatTitleFont ); + aStyleSettings.SetHelpFont( aHelpFont ); + aStyleSettings.SetIconFont( aIconFont ); + // We prefer Arial in the russian version, because MS Sans Serif + // is to wide for the dialogs + if ( rSettings.GetInternational().GetLanguage() == LANGUAGE_RUSSIAN ) + { + XubString aFontName = aAppFont.GetName(); + XubString aFirstName = aFontName.GetToken( 0, ';' ); + if ( aFirstName.EqualsIgnoreCaseAscii( "MS Sans Serif" ) ) + { + aFontName.InsertAscii( "Arial;", 0 ); + aAppFont.SetName( aFontName ); + } + } + aStyleSettings.SetAppFont( aAppFont ); + aStyleSettings.SetGroupFont( aAppFont ); + aStyleSettings.SetLabelFont( aAppFont ); + aStyleSettings.SetRadioCheckFont( aAppFont ); + aStyleSettings.SetPushButtonFont( aAppFont ); + aStyleSettings.SetFieldFont( aAppFont ); + if ( aAppFont.GetWeight() > WEIGHT_NORMAL ) + aAppFont.SetWeight( WEIGHT_NORMAL ); + aStyleSettings.SetInfoFont( aAppFont ); + aStyleSettings.SetToolFont( aAppFont ); + + WIN_BOOL bDragFull; + if ( SystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) ) + { + ULONG nDragFullOptions = aStyleSettings.GetDragFullOptions(); + if ( bDragFull ) + 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 ); + } + + aStyleSettings.SetIconHorzSpace( GetSystemMetrics( SM_CXICONSPACING ) ); + aStyleSettings.SetIconVertSpace( GetSystemMetrics( SM_CYICONSPACING ) ); + if ( RegOpenKey( HKEY_CURRENT_USER, + "Control Panel\\International\\Calendars\\TwoDigitYearMax", + &hRegKey ) == ERROR_SUCCESS ) + { + BYTE aValueBuf[10]; + DWORD nValue; + DWORD nValueSize = sizeof( aValueBuf ); + DWORD nType; + if ( RegQueryValueEx( hRegKey, "1", 0, + &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS ) + { + if ( nType == REG_SZ ) + { + nValue = (ULONG)ImplA2I( aValueBuf ); + if ( (nValue > 1000) && (nValue < 10000) ) + { + MiscSettings aMiscSettings = rSettings.GetMiscSettings(); + aMiscSettings.SetTwoDigitYearStart( (USHORT)(nValue-99) ); + rSettings.SetMiscSettings( aMiscSettings ); + } + } + } + + RegCloseKey( hRegKey ); + } + + rSettings.SetMouseSettings( aMouseSettings ); + rSettings.SetStyleSettings( aStyleSettings ); +} + +// ----------------------------------------------------------------------- + +const SystemEnvData* SalFrame::GetSystemData() const +{ + return &maFrameData.maSysData; +} + +// ----------------------------------------------------------------------- + +void SalFrame::Beep( SoundType eSoundType ) +{ + static UINT aImplSoundTab[5] = + { + 0, // SOUND_DEFAULT + MB_ICONASTERISK, // SOUND_INFO + MB_ICONEXCLAMATION, // SOUND_WARNING + MB_ICONHAND, // SOUND_ERROR + MB_ICONQUESTION // SOUND_QUERY + }; + +#if SOUND_COUNT != 5 +#error New Sound must be defined! +#endif + + MessageBeep( aImplSoundTab[eSoundType] ); +} + +// ----------------------------------------------------------------------- + +void SalFrame::SetCallback( void* pInst, SALFRAMEPROC pProc ) +{ + maFrameData.mpInst = pInst; + if ( pProc ) + maFrameData.mpProc = pProc; + else + maFrameData.mpProc = ImplSalCallbackDummy; +} + +// ----------------------------------------------------------------------- + +static long ImplHandleMouseMsg( HWND hWnd, UINT nMsg, + WPARAM wParam, LPARAM lParam ) +{ + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( !pFrame ) + return 0; + + SalMouseEvent aMouseEvt; + long nRet; + USHORT nEvent; + BOOL bCall = TRUE; + + aMouseEvt.mnX = (short)LOWORD( lParam ); + aMouseEvt.mnY = (short)HIWORD( lParam ); + aMouseEvt.mnCode = 0; + aMouseEvt.mnTime = GetMessageTime(); + + // Wegen (Logitech-)MouseTreiber ueber GetKeyState() gehen, die auf + // mittlerer Maustaste Doppelklick simulieren und den KeyStatus nicht + // beruecksichtigen + + if ( GetKeyState( VK_LBUTTON ) & 0x8000 ) + aMouseEvt.mnCode |= MOUSE_LEFT; + if ( GetKeyState( VK_MBUTTON ) & 0x8000 ) + aMouseEvt.mnCode |= MOUSE_MIDDLE; + if ( GetKeyState( VK_RBUTTON ) & 0x8000 ) + aMouseEvt.mnCode |= MOUSE_RIGHT; + if ( GetKeyState( VK_SHIFT ) & 0x8000 ) + aMouseEvt.mnCode |= KEY_SHIFT; + if ( GetKeyState( VK_CONTROL ) & 0x8000 ) + aMouseEvt.mnCode |= KEY_MOD1; + if ( GetKeyState( VK_MENU ) & 0x8000 ) + aMouseEvt.mnCode |= KEY_MOD2; + + switch ( nMsg ) + { + case WM_MOUSEMOVE: + { + // 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) ) + { + MSG aTempMsg; + if ( ImplPeekMessage( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) ) + { + if ( (aTempMsg.message == WM_MOUSEMOVE) && + (aTempMsg.wParam == wParam) ) + return 1; + } + } + + SalData* pSalData = GetSalData(); + // Test for MouseLeave + if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) ) + ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() ); + pSalData->mhWantLeaveMsg = hWnd; + // 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 WM_NCMOUSEMOVE: + case SAL_MSG_MOUSELEAVE: + { + SalData* pSalData = GetSalData(); + if ( pSalData->mhWantLeaveMsg == hWnd ) + { + pSalData->mhWantLeaveMsg = 0; + if ( pSalData->mpMouseLeaveTimer ) + { + delete pSalData->mpMouseLeaveTimer; + pSalData->mpMouseLeaveTimer = NULL; + } + // Mouse-Coordinaates are relativ to the screen + POINT aPt; + aPt.x = (short)LOWORD( lParam ); + aPt.y = (short)HIWORD( lParam ); + ScreenToClient( hWnd, &aPt ); + aMouseEvt.mnX = aPt.x; + aMouseEvt.mnY = aPt.y; + aMouseEvt.mnButton = 0; + nEvent = SALEVENT_MOUSELEAVE; + } + else + bCall = FALSE; + } + break; + + case WM_LBUTTONDOWN: + aMouseEvt.mnButton = MOUSE_LEFT; + nEvent = SALEVENT_MOUSEBUTTONDOWN; + break; + + case WM_MBUTTONDOWN: + aMouseEvt.mnButton = MOUSE_MIDDLE; + nEvent = SALEVENT_MOUSEBUTTONDOWN; + break; + + case WM_RBUTTONDOWN: + aMouseEvt.mnButton = MOUSE_RIGHT; + nEvent = SALEVENT_MOUSEBUTTONDOWN; + break; + + case WM_LBUTTONUP: + aMouseEvt.mnButton = MOUSE_LEFT; + nEvent = SALEVENT_MOUSEBUTTONUP; + break; + + case WM_MBUTTONUP: + aMouseEvt.mnButton = MOUSE_MIDDLE; + nEvent = SALEVENT_MOUSEBUTTONUP; + break; + + case WM_RBUTTONUP: + aMouseEvt.mnButton = MOUSE_RIGHT; + nEvent = SALEVENT_MOUSEBUTTONUP; + break; + } + + if ( bCall ) + { + if ( nEvent == SALEVENT_MOUSEBUTTONDOWN ) + UpdateWindow( hWnd ); + + nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + nEvent, &aMouseEvt ); + if ( nMsg == WM_MOUSEMOVE ) + SetCursor( pFrame->maFrameData.mhCursor ); + } + else + nRet = 0; + + return nRet; +} + +// ----------------------------------------------------------------------- + +static long ImplHandleMouseActivateMsg( HWND hWnd ) +{ + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( !pFrame ) + return 0; + + SalMouseActivateEvent aMouseActivateEvt; + POINT aPt; + GetCursorPos( &aPt ); + ScreenToClient( hWnd, &aPt ); + aMouseActivateEvt.mnX = aPt.x; + aMouseActivateEvt.mnY = aPt.y; + return pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_MOUSEACTIVATE, &aMouseActivateEvt ); +} + +// ----------------------------------------------------------------------- + +static long ImplHandleWheelMsg( HWND hWnd, WPARAM wParam, LPARAM lParam ) +{ + ImplSalYieldMutexAcquireWithWait(); + + long nRet = 0; + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + WORD nWinModCode = LOWORD( wParam ); + POINT aWinPt; + aWinPt.x = (short)LOWORD( lParam ); + aWinPt.y = (short)HIWORD( lParam ); + ScreenToClient( hWnd, &aWinPt ); + + SalWheelMouseEvent aWheelEvt; + aWheelEvt.mnTime = GetMessageTime(); + aWheelEvt.mnX = aWinPt.x; + aWheelEvt.mnY = aWinPt.y; + aWheelEvt.mnCode = 0; + aWheelEvt.mnDelta = (short)HIWORD( wParam ); + aWheelEvt.mnNotchDelta = aWheelEvt.mnDelta/WHEEL_DELTA; + if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL ) + aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; + else + aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines; + aWheelEvt.mbHorz = FALSE; + + if ( nWinModCode & MK_SHIFT ) + aWheelEvt.mnCode |= KEY_SHIFT; + if ( nWinModCode & MK_CONTROL ) + aWheelEvt.mnCode |= KEY_MOD1; + if ( GetKeyState( VK_MENU ) & 0x8000 ) + aWheelEvt.mnCode |= KEY_MOD2; + + nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_WHEELMOUSE, &aWheelEvt ); + } + + ImplSalYieldMutexRelease(); + + return nRet; +} + +// ----------------------------------------------------------------------- + +static USHORT ImplSalGetKeyCode( WPARAM wParam ) +{ + USHORT nKeyCode; + + // convert KeyCode + if ( wParam < KEY_TAB_SIZE ) + nKeyCode = aImplTranslateKeyTab[wParam]; + else if ( wParam == aSalShlData.mnVKAdd ) + nKeyCode = KEY_ADD; + else if ( wParam == aSalShlData.mnVKSubtract ) + nKeyCode = KEY_SUBTRACT; + else if ( wParam == aSalShlData.mnVKMultiply ) + nKeyCode = KEY_MULTIPLY; + else if ( wParam == aSalShlData.mnVKDivide ) + nKeyCode = KEY_DIVIDE; + else if ( wParam == aSalShlData.mnVKPoint ) + nKeyCode = KEY_POINT; + else if ( wParam == aSalShlData.mnVKComma ) + nKeyCode = KEY_COMMA; + else if ( wParam == aSalShlData.mnVKLess ) + nKeyCode = KEY_LESS; + else if ( wParam == aSalShlData.mnVKGreater ) + nKeyCode = KEY_GREATER; + else if ( wParam == aSalShlData.mnVKEqual ) + nKeyCode = KEY_EQUAL; + else + nKeyCode = 0; + + return nKeyCode; +} + +// ----------------------------------------------------------------------- + +static UINT ImplStrToNum( const sal_Char* pStr ) +{ + USHORT n = 0; + + // Solange es sich um eine Ziffer handelt, String umwandeln + while( (*pStr >= 48) && (*pStr <= 57) ) + { + n *= 10; + n += ((*pStr) - 48); + pStr++; + } + + return n; +} + +// ----------------------------------------------------------------------- + +static sal_Unicode ImplGetCharCode( SalFrame* pFrame, WPARAM nCharCode ) +{ + // If we are on Windows NT we use Unicode FrameProcs and so we + // get Unicode charcodes directly from Windows + if ( aSalShlData.mbWNT ) + return (sal_Unicode)nCharCode; + + UINT nLang = LOWORD( GetKeyboardLayout( 0 ) ); + if ( !nLang ) + { + pFrame->maFrameData.mnInputLang = 0; + pFrame->maFrameData.mnInputCodePage = GetACP(); + } + else if ( nLang != pFrame->maFrameData.mnInputLang ) + { + pFrame->maFrameData.mnInputLang = nLang; + sal_Char aBuf[10]; + if ( GetLocaleInfoA( MAKELCID( nLang, SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE, + aBuf, sizeof(aBuf) ) > 0 ) + { + pFrame->maFrameData.mnInputCodePage = ImplStrToNum( aBuf ); + if ( !pFrame->maFrameData.mnInputCodePage ) + pFrame->maFrameData.mnInputCodePage = GetACP(); + } + else + pFrame->maFrameData.mnInputCodePage = GetACP(); + } + + sal_Char aCharBuf[2]; + int nCharLen; + WCHAR c; + if ( nCharCode > 0xFF ) + { + aCharBuf[0] = (sal_Char)(nCharCode>>8); + aCharBuf[1] = (sal_Char)nCharCode; + nCharLen = 2; + } + else + { + aCharBuf[0] = (sal_Char)nCharCode; + nCharLen = 1; + } + if ( ::MultiByteToWideChar( pFrame->maFrameData.mnInputCodePage, + MB_PRECOMPOSED, + aCharBuf, nCharLen, &c, 1 ) ) + return (sal_Unicode)c; + else + return (sal_Unicode)nCharCode; +} + +// ----------------------------------------------------------------------- + +static long ImplHandleKeyMsg( HWND hWnd, UINT nMsg, + WPARAM wParam, LPARAM lParam ) +{ + static BOOL bIgnoreCharMsg = FALSE; + static WPARAM nDeadChar = 0; + static WPARAM nLastVKChar = 0; + static USHORT nLastChar = 0; + USHORT nRepeat = LOWORD( lParam )-1; + USHORT nModCode = 0; + + // Key wurde evtl. durch SysChild an uns weitergeleitet und + // darf somit dann nicht doppelt verarbeitet werden + GetSalData()->mnSalObjWantKeyEvt = 0; + + if ( nMsg == WM_DEADCHAR ) + { + nDeadChar = wParam; + return 0; + } + + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( !pFrame ) + return 0; + + // Wir restaurieren den Background-Modus bei jeder Texteingabe, + // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen + if ( pFrame->maFrameData.mpGraphics && + pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC ) + SetBkMode( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC, TRANSPARENT ); + + // determine modifiers + if ( GetKeyState( VK_SHIFT ) & 0x8000 ) + nModCode |= KEY_SHIFT; + if ( GetKeyState( VK_CONTROL ) & 0x8000 ) + nModCode |= KEY_MOD1; + if ( GetKeyState( VK_MENU ) & 0x8000 ) + { + nModCode |= KEY_MOD2; + if ( !(nModCode & KEY_MOD1) && + ((nMsg == WM_SYSKEYDOWN) || (nMsg == WM_SYSKEYUP)) ) + nModCode |= KEY_CONTROLMOD; + } + + if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) ) + { + nDeadChar = 0; + + if ( bIgnoreCharMsg ) + { + bIgnoreCharMsg = FALSE; + return 0; + } + + // Backspace ignorieren wir als eigenstaendige Taste, + // damit wir keine Probleme in Kombination mit einem + // DeadKey bekommen + if ( wParam == 0x08 ) // BACKSPACE + return 0; + + // Hier kommen nur "freifliegende" WM_CHAR Message an, die durch + // eintippen einer ALT-NUMPAD Kombination erzeugt wurden + SalKeyEvent aKeyEvt; + + if ( (wParam >= '0') && (wParam <= '9') ) + aKeyEvt.mnCode = KEYGROUP_NUM + wParam - '0'; + else if ( (wParam >= 'A') && (wParam <= 'Z') ) + aKeyEvt.mnCode = KEYGROUP_ALPHA + wParam - 'A'; + else if ( (wParam >= 'a') && (wParam <= 'z') ) + aKeyEvt.mnCode = KEYGROUP_ALPHA + wParam - 'a'; + else if ( wParam == 0x0D ) // RETURN + aKeyEvt.mnCode = KEY_RETURN; + else if ( wParam == 0x1B ) // ESCAPE + aKeyEvt.mnCode = KEY_ESCAPE; + else if ( wParam == 0x09 ) // TAB + aKeyEvt.mnCode = KEY_TAB; + else if ( wParam == 0x20 ) // SPACE + aKeyEvt.mnCode = KEY_SPACE; + else + aKeyEvt.mnCode = 0; + + aKeyEvt.mnTime = GetMessageTime(); + aKeyEvt.mnCode |= nModCode; + aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, wParam ); + aKeyEvt.mnRepeat = nRepeat; + nLastChar = 0; + nLastVKChar = 0; + long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYINPUT, &aKeyEvt ); + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYUP, &aKeyEvt ); + return nRet; + } + else + { + // Bei Shift, Control und Menu schicken wir einen KeyModChange-Event + if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) ) + { + SalKeyModEvent aModEvt; + aModEvt.mnTime = GetMessageTime(); + aModEvt.mnCode = nModCode; + return pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYMODCHANGE, &aModEvt ); + } + else + { + SalKeyEvent aKeyEvt; + USHORT nEvent; + MSG aCharMsg; + WIN_BOOL bCharPeek = FALSE; + UINT nCharMsg = WM_CHAR; + BOOL bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP); + + aKeyEvt.mnCode = ImplSalGetKeyCode( wParam ); + if ( !bKeyUp ) + { + // check for charcode + // Mit Hilfe von PeekMessage holen wir uns jetzt die + // zugehoerige WM_CHAR Message, wenn vorhanden. + // Diese WM_CHAR Message steht immer am Anfang der + // Messagequeue. Ausserdem ist sichergestellt, dass immer + // nur eine WM_CHAR Message in der Queue steht. + bCharPeek = ImplPeekMessage( &aCharMsg, hWnd, + WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD ); + if ( bCharPeek && (nDeadChar == aCharMsg.wParam) ) + { + bCharPeek = FALSE; + nDeadChar = 0; + + if ( wParam == VK_BACK ) + { + ImplPeekMessage( &aCharMsg, hWnd, + nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD ); + return 0; + } + } + else + { + if ( !bCharPeek ) + { + bCharPeek = ImplPeekMessage( &aCharMsg, hWnd, + WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD ); + nCharMsg = WM_SYSCHAR; + } + } + if ( bCharPeek ) + aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam ); + else + aKeyEvt.mnCharCode = 0; + + nLastChar = aKeyEvt.mnCharCode; + nLastVKChar = wParam; + } + else + { + if ( wParam == nLastVKChar ) + { + aKeyEvt.mnCharCode = nLastChar; + nLastChar = 0; + nLastVKChar = 0; + } + } + + if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode ) + { + if ( bKeyUp ) + nEvent = SALEVENT_KEYUP; + else + nEvent = SALEVENT_KEYINPUT; + + aKeyEvt.mnTime = GetMessageTime(); + aKeyEvt.mnCode |= nModCode; + aKeyEvt.mnRepeat = nRepeat; + bIgnoreCharMsg = bCharPeek; + long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + nEvent, &aKeyEvt ); + bIgnoreCharMsg = FALSE; + + // char-message, than remove or ignore + if ( bCharPeek ) + { + nDeadChar = 0; + if ( nRet ) + { + ImplPeekMessage( &aCharMsg, hWnd, + nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD ); + } + else + bIgnoreCharMsg = TRUE; + } + + return nRet; + } + else + return 0; + } + } +} + +// ----------------------------------------------------------------------- + +long ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg, + WPARAM wParam, LPARAM lParam ) +{ + if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( !pFrame ) + return 0; + + USHORT nRepeat = LOWORD( lParam )-1; + USHORT nModCode = 0; + + // determine modifiers + if ( GetKeyState( VK_SHIFT ) & 0x8000 ) + nModCode |= KEY_SHIFT; + if ( GetKeyState( VK_CONTROL ) & 0x8000 ) + nModCode |= KEY_MOD1; + if ( GetKeyState( VK_MENU ) & 0x8000 ) + { + nModCode |= KEY_MOD2; + if ( !(nModCode & KEY_MOD1) ) + nModCode |= KEY_CONTROLMOD; + } + + if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) ) + { + SalKeyEvent aKeyEvt; + USHORT nEvent; + BOOL bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP); + + // convert KeyCode + aKeyEvt.mnCode = ImplSalGetKeyCode( wParam ); + aKeyEvt.mnCharCode = 0; + + if ( aKeyEvt.mnCode ) + { + if ( bKeyUp ) + nEvent = SALEVENT_KEYUP; + else + nEvent = SALEVENT_KEYINPUT; + + aKeyEvt.mnTime = GetMessageTime(); + aKeyEvt.mnCode |= nModCode; + aKeyEvt.mnRepeat = nRepeat; + long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + nEvent, &aKeyEvt ); + return nRet; + } + else + return 0; + } + } + + return 0; +} + +// ----------------------------------------------------------------------- + +long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam ) +{ + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( !pFrame ) + return 0; + + USHORT nRepeat = LOWORD( lParam )-1; + USHORT nModCode = 0; + USHORT cKeyCode = (USHORT)wParam; + + // determine modifiers + if ( GetKeyState( VK_SHIFT ) & 0x8000 ) + nModCode |= KEY_SHIFT; + if ( GetKeyState( VK_CONTROL ) & 0x8000 ) + nModCode |= KEY_MOD1; + nModCode |= KEY_MOD2; + if ( !(nModCode & KEY_MOD1) ) + nModCode |= KEY_CONTROLMOD; + + // KeyEvent zusammenbauen + SalKeyEvent aKeyEvt; + aKeyEvt.mnTime = GetMessageTime(); + if ( (cKeyCode >= 48) && (cKeyCode <= 57) ) + aKeyEvt.mnCode = KEY_0+(cKeyCode-48); + else if ( (cKeyCode >= 65) && (cKeyCode <= 90) ) + aKeyEvt.mnCode = KEY_A+(cKeyCode-65); + else if ( (cKeyCode >= 97) && (cKeyCode <= 122) ) + aKeyEvt.mnCode = KEY_A+(cKeyCode-97); + else + aKeyEvt.mnCode = 0; + aKeyEvt.mnCode |= nModCode; + aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, cKeyCode ); + aKeyEvt.mnRepeat = nRepeat; + long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYINPUT, &aKeyEvt ); + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYUP, &aKeyEvt ); + return nRet; +} + +// ----------------------------------------------------------------------- + +static void ImplHandlePaintMsg( HWND hWnd ) +{ + // Clip-Region muss zurueckgesetzt werden, da wir sonst kein + // ordentliches Bounding-Rectangle bekommen + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame && pFrame->maFrameData.mpGraphics ) + { + if ( pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion ) + SelectClipRgn( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC, 0 ); + } + ImplSalYieldMutexRelease(); + } + + // Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine + // Paint-Region anliegt + if ( !GetUpdateRect( hWnd, NULL, FALSE ) ) + return; + + // BeginPaint + PAINTSTRUCT aPs; + BeginPaint( hWnd, &aPs ); + + // Paint + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + // ClipRegion wieder herstellen + if ( pFrame->maFrameData.mpGraphics ) + { + if ( pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion ) + { + SelectClipRgn( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC, + pFrame->maFrameData.mpGraphics->maGraphicsData.mhRegion ); + } + } + + SalPaintEvent aPEvt; + aPEvt.mnBoundX = aPs.rcPaint.left; + aPEvt.mnBoundY = aPs.rcPaint.top; + aPEvt.mnBoundWidth = aPs.rcPaint.right-aPs.rcPaint.left; + aPEvt.mnBoundHeight = aPs.rcPaint.bottom-aPs.rcPaint.top; + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_PAINT, &aPEvt ); + } + + ImplSalYieldMutexRelease(); + } + else + { + RECT* pRect = new RECT; + *pRect = aPs.rcPaint; + ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 ); + } + + // EndPaint + EndPaint( hWnd, &aPs ); +} + +// ----------------------------------------------------------------------- + +static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect ) +{ + // Paint + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + SalPaintEvent aPEvt; + aPEvt.mnBoundX = pRect->left; + aPEvt.mnBoundY = pRect->top; + aPEvt.mnBoundWidth = pRect->right-pRect->left; + aPEvt.mnBoundHeight = pRect->bottom-pRect->top; + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_PAINT, &aPEvt ); + } + ImplSalYieldMutexRelease(); + delete pRect; + } + else + ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 ); +} + +// ----------------------------------------------------------------------- + +static void ImplHandleMoveMsg( HWND hWnd ) +{ + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + if ( GetWindowStyle( hWnd ) & WS_VISIBLE ) + pFrame->maFrameData.mbDefPos = FALSE; + + // Gegen moegliche Rekursionen sichern + if ( !pFrame->maFrameData.mbInMoveMsg ) + { + // Fenster im FullScreenModus wieder einpassen + pFrame->maFrameData.mbInMoveMsg = TRUE; + if ( pFrame->maFrameData.mbFullScreen ) + ImplSalFrameFullScreenPos( pFrame ); + pFrame->maFrameData.mbInMoveMsg = FALSE; + } + + // Status merken + ImplSaveFrameState( pFrame ); + } + + ImplSalYieldMutexRelease(); + } + else + ImplPostMessage( hWnd, SAL_MSG_POSTMOVE, 0, 0 ); +} + +// ----------------------------------------------------------------------- + +static void ImplCallSizeHdl( HWND hWnd ) +{ + // Da Windows diese Messages auch senden kann, muss hier auch die + // Solar-Semaphore beruecksichtigt werden + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_RESIZE, 0 ); + // Um doppelte Paints von VCL und SAL zu vermeiden + if ( IsWindowVisible( hWnd ) && !pFrame->maFrameData.mbInShow ) + UpdateWindow( hWnd ); + } + + ImplSalYieldMutexRelease(); + } + else + ImplPostMessage( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 ); +} + +// ----------------------------------------------------------------------- + +static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam ) +{ + if ( (wParam != SIZE_MAXSHOW) && (wParam != SIZE_MAXHIDE) ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + pFrame->maFrameData.mnWidth = (int)LOWORD(lParam); + pFrame->maFrameData.mnHeight = (int)HIWORD(lParam); + // Status merken + ImplSaveFrameState( pFrame ); + // Call Hdl + ImplCallSizeHdl( hWnd ); + } + } +} + +// ----------------------------------------------------------------------- + +static void ImplHandleFocusMsg( HWND hWnd ) +{ + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + // Query the actual status + if ( ::GetFocus() == hWnd ) + { + if ( IsWindowVisible( hWnd ) && !pFrame->maFrameData.mbInShow ) + UpdateWindow( hWnd ); + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_GETFOCUS, 0 ); + } + else + { + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_LOSEFOCUS, 0 ); + } + } + + ImplSalYieldMutexRelease(); + } + else + ImplPostMessage( hWnd, SAL_MSG_POSTFOCUS, 0, 0 ); +} + +// ----------------------------------------------------------------------- + +static void ImplHandleCloseMsg( HWND hWnd ) +{ + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_CLOSE, 0 ); + } + + ImplSalYieldMutexRelease(); + } + else + ImplPostMessage( hWnd, WM_CLOSE, 0, 0 ); +} + +// ----------------------------------------------------------------------- + +static long ImplHandleShutDownMsg( HWND hWnd ) +{ + ImplSalYieldMutexAcquireWithWait(); + long nRet = 0; + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_SHUTDOWN, 0 ); + } + ImplSalYieldMutexRelease(); + return nRet; +} + +// ----------------------------------------------------------------------- + +static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg, + WPARAM wParam, LPARAM lParam ) +{ + USHORT nSalEvent = SALEVENT_SETTINGSCHANGED; + + if ( nMsg == WM_DEVMODECHANGE ) + nSalEvent = SALEVENT_PRINTERCHANGED; +#ifdef WM_DISPLAYCHANGE + else if ( nMsg == WM_DISPLAYCHANGE ) + nSalEvent = SALEVENT_DISPLAYCHANGED; +#endif + else if ( nMsg == WM_FONTCHANGE ) + nSalEvent = SALEVENT_FONTCHANGED; + else if ( nMsg == WM_TIMECHANGE ) + nSalEvent = SALEVENT_DATETIMECHANGED; + else if ( nMsg == WM_WININICHANGE ) + { + if ( lParam ) + { + if ( aSalShlData.mbWNT ) + { + if ( ImplSalWICompareAscii( (const wchar_t*)lParam, "devices" ) == 0 ) + nSalEvent = SALEVENT_PRINTERCHANGED; + } + else + { + if ( stricmp( (const char*)lParam, "devices" ) == 0 ) + nSalEvent = SALEVENT_PRINTERCHANGED; + } + } + } + +#ifdef WM_SETTINGCHANGE + if ( nMsg == WM_SETTINGCHANGE ) + { + if ( wParam == SPI_SETWHEELSCROLLLINES ) + aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines(); + } +#endif + + if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal ) + ImplUpdateSysColorEntries(); + + ImplSalYieldMutexAcquireWithWait(); + + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) ) + { + if ( pFrame->maFrameData.mbFullScreen ) + ImplSalFrameFullScreenPos( pFrame ); + } + + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + nSalEvent, 0 ); + } + + ImplSalYieldMutexRelease(); +} + +// ----------------------------------------------------------------------- + +static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam ) +{ + ImplSalYieldMutexAcquireWithWait(); + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_USEREVENT, (void*)lParam ); + } + ImplSalYieldMutexRelease(); +} + +// ----------------------------------------------------------------------- + +static void ImplHandleForcePalette( HWND hWnd ) +{ + SalData* pSalData = GetSalData(); + HPALETTE hPal = pSalData->mhDitherPal; + if ( hPal ) + { + if ( !ImplSalYieldMutexTryToAcquire() ) + { + ImplPostMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 ); + return; + } + + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame && pFrame->maFrameData.mpGraphics ) + { + SalGraphics* pGraphics = pFrame->maFrameData.mpGraphics; + if ( pGraphics && pGraphics->maGraphicsData.mhDefPal ) + { + SelectPalette( pGraphics->maGraphicsData.mhDC, hPal, FALSE ); + if ( RealizePalette( pGraphics->maGraphicsData.mhDC ) ) + { + InvalidateRect( hWnd, NULL, FALSE ); + UpdateWindow( hWnd ); + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_DISPLAYCHANGED, 0 ); + } + } + } + + ImplSalYieldMutexRelease(); + } +} + +// ----------------------------------------------------------------------- + +static LRESULT ImplHandlePalette( BOOL bFrame, HWND hWnd, UINT nMsg, + WPARAM wParam, LPARAM lParam, int& rDef ) +{ + SalData* pSalData = GetSalData(); + HPALETTE hPal = pSalData->mhDitherPal; + if ( !hPal ) + return 0; + + rDef = FALSE; + if ( pSalData->mbInPalChange ) + return 0; + + if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) ) + { + if ( (HWND)wParam == hWnd ) + return 0; + } + + BOOL bReleaseMutex = FALSE; + if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) ) + { + // Da Windows diese Messages auch sendet, muss hier auch die + // Solar-Semaphore beruecksichtigt werden + if ( ImplSalYieldMutexTryToAcquire() ) + bReleaseMutex = TRUE; + else if ( nMsg == WM_QUERYNEWPALETTE ) + ImplPostMessage( hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam ); + else /* ( nMsg == WM_PALETTECHANGED ) */ + ImplPostMessage( hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam ); + } + + SalVirtualDevice* pTempVD; + SalFrame* pTempFrame; + SalGraphics* pGraphics; + HDC hDC; + HPALETTE hOldPal; + UINT nCols; + BOOL bStdDC; + BOOL bUpdate; + + pSalData->mbInPalChange = TRUE; + + // Alle Paletten in VirDevs und Frames zuruecksetzen + pTempVD = pSalData->mpFirstVD; + while ( pTempVD ) + { + pGraphics = pTempVD->maVirDevData.mpGraphics; + if ( pGraphics->maGraphicsData.mhDefPal ) + { + SelectPalette( pGraphics->maGraphicsData.mhDC, + pGraphics->maGraphicsData.mhDefPal, + TRUE ); + } + pTempVD = pTempVD->maVirDevData.mpNext; + } + pTempFrame = pSalData->mpFirstFrame; + while ( pTempFrame ) + { + pGraphics = pTempFrame->maFrameData.mpGraphics; + if ( pGraphics && pGraphics->maGraphicsData.mhDefPal ) + { + SelectPalette( pGraphics->maGraphicsData.mhDC, + pGraphics->maGraphicsData.mhDefPal, + TRUE ); + } + pTempFrame = pTempFrame->maFrameData.mpNextFrame; + } + + // Palette neu realizen + SalFrame* pFrame = NULL; + if ( bFrame ) + pFrame = GetWindowPtr( hWnd ); + if ( pFrame && pFrame->maFrameData.mpGraphics ) + { + hDC = pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC; + bStdDC = TRUE; + } + else + { + hDC = GetDC( hWnd ); + bStdDC = FALSE; + } + UnrealizeObject( hPal ); + hOldPal = SelectPalette( hDC, hPal, TRUE ); + nCols = RealizePalette( hDC ); + bUpdate = nCols != 0; + if ( !bStdDC ) + { + SelectPalette( hDC, hOldPal, TRUE ); + ReleaseDC( hWnd, hDC ); + } + + // Alle Paletten in VirDevs und Frames neu setzen + pTempVD = pSalData->mpFirstVD; + while ( pTempVD ) + { + pGraphics = pTempVD->maVirDevData.mpGraphics; + if ( pGraphics->maGraphicsData.mhDefPal ) + { + SelectPalette( pGraphics->maGraphicsData.mhDC, hPal, TRUE ); + RealizePalette( pGraphics->maGraphicsData.mhDC ); + } + pTempVD = pTempVD->maVirDevData.mpNext; + } + pTempFrame = pSalData->mpFirstFrame; + while ( pTempFrame ) + { + if ( pTempFrame != pFrame ) + { + pGraphics = pTempFrame->maFrameData.mpGraphics; + if ( pGraphics && pGraphics->maGraphicsData.mhDefPal ) + { + SelectPalette( pGraphics->maGraphicsData.mhDC, hPal, TRUE ); + if ( RealizePalette( pGraphics->maGraphicsData.mhDC ) ) + bUpdate = TRUE; + } + } + pTempFrame = pTempFrame->maFrameData.mpNextFrame; + } + + // Wenn sich Farben geaendert haben, dann die Fenster updaten + if ( bUpdate ) + { + pTempFrame = pSalData->mpFirstFrame; + while ( pTempFrame ) + { + pGraphics = pTempFrame->maFrameData.mpGraphics; + if ( pGraphics && pGraphics->maGraphicsData.mhDefPal ) + { + InvalidateRect( pTempFrame->maFrameData.mhWnd, NULL, FALSE ); + UpdateWindow( pTempFrame->maFrameData.mhWnd ); + pTempFrame->maFrameData.mpProc( pTempFrame->maFrameData.mpInst, pTempFrame, + SALEVENT_DISPLAYCHANGED, 0 ); + } + pTempFrame = pTempFrame->maFrameData.mpNextFrame; + } + } + + pSalData->mbInPalChange = FALSE; + + if ( bReleaseMutex ) + ImplSalYieldMutexRelease(); + + if ( nMsg == WM_PALETTECHANGED ) + return 0; + else + return nCols; +} + +// ----------------------------------------------------------------------- + +static int ImplHandleMinMax( HWND hWnd, LPARAM lParam ) +{ + int bRet = FALSE; + + if ( ImplSalYieldMutexTryToAcquire() ) + { + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + if ( pFrame->maFrameData.mbFullScreen ) + { + MINMAXINFO* pMinMax = (MINMAXINFO*)lParam; + int nX; + int nY; + int nDX; + int nDY; + ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY ); + + if ( pMinMax->ptMaxPosition.x > nX ) + pMinMax->ptMaxPosition.x = nX; + if ( pMinMax->ptMaxPosition.y > nY ) + pMinMax->ptMaxPosition.y = nY; + + if ( pMinMax->ptMaxSize.x < nDX ) + pMinMax->ptMaxSize.x = nDX; + if ( pMinMax->ptMaxSize.y < nDY ) + pMinMax->ptMaxSize.y = nDY; + if ( pMinMax->ptMaxTrackSize.x < nDX ) + pMinMax->ptMaxTrackSize.x = nDX; + if ( pMinMax->ptMaxTrackSize.y < nDY ) + pMinMax->ptMaxTrackSize.y = nDY; + + pMinMax->ptMinTrackSize.x = nDX; + pMinMax->ptMinTrackSize.y = nDY; + + bRet = TRUE; + } + } + + ImplSalYieldMutexRelease(); + } + + return bRet; +} + +// ----------------------------------------------------------------------- + +static int ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam ) +{ + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( !pFrame ) + return 0; + + WPARAM nCommand = wParam & 0xFFF0; + + if ( pFrame->maFrameData.mbFullScreen ) + { + WIN_BOOL bMaximize = IsZoomed( pFrame->maFrameData.mhWnd ); + WIN_BOOL bMinimize = IsIconic( pFrame->maFrameData.mhWnd ); + if ( (nCommand == SC_SIZE) || + (!bMinimize && (nCommand == SC_MOVE)) || + (!bMaximize && (nCommand == SC_MAXIMIZE)) || + (bMaximize && (nCommand == SC_RESTORE)) ) + { + MessageBeep( 0 ); + return TRUE; + } + } + + if ( nCommand == SC_KEYMENU ) + { + // Hier verarbeiten wir nur KeyMenu-Events fuer Alt um + // den MenuBar zu aktivieren, oder wenn ein SysChild-Fenster + // den Focus hat, da diese Alt+Tasten-Kombinationen nur + // ueber diesen Event verarbeitet werden + if ( !LOWORD( lParam ) ) + { + // Nur ausloesen, wenn keine weitere Taste gedrueckt ist. Im + // Gegensatz zur Doku wird in der X-Koordinaate der CharCode + // geliefert, der zusaetzlich gedrueckt ist + // Also 32 fuer Space, 99 fuer c, 100 fuer d, ... + // Da dies nicht dokumentiert ist, fragen wir vorsichtshalber + // auch den Status der Space-Taste ab + if ( GetKeyState( VK_SPACE ) & 0x8000 ) + return 0; + + // Damit nicht bei Alt+Maustaste auch der MenuBar aktiviert wird + if ( (GetKeyState( VK_LBUTTON ) & 0x8000) || + (GetKeyState( VK_RBUTTON ) & 0x8000) || + (GetKeyState( VK_MBUTTON ) & 0x8000) ) + return 1; + + SalKeyEvent aKeyEvt; + aKeyEvt.mnTime = GetMessageTime(); + aKeyEvt.mnCode = KEY_MENU; + aKeyEvt.mnCharCode = 0; + aKeyEvt.mnRepeat = 0; + long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYINPUT, &aKeyEvt ); + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYUP, &aKeyEvt ); + return (nRet != 0); + } + else + { + // Testen, ob ein SysChild den Focus hat + HWND hFocusWnd = ::GetFocus(); + if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) ) + { + char cKeyCode = (char)(unsigned char)LOWORD( lParam ); + // LowerCase + if ( (cKeyCode >= 65) && (cKeyCode <= 90) ) + cKeyCode += 32; + // Wir nehmen nur 0-9 und A-Z, alle anderen Tasten muessen durch + // den Hook vom SalObj verarbeitet werden + if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) || + ((cKeyCode >= 97) && (cKeyCode <= 122)) ) + { + USHORT nModCode = 0; + if ( GetKeyState( VK_SHIFT ) & 0x8000 ) + nModCode |= KEY_SHIFT; + if ( GetKeyState( VK_CONTROL ) & 0x8000 ) + nModCode |= KEY_MOD1; + nModCode |= KEY_MOD2; + if ( !(nModCode & KEY_MOD1) ) + nModCode |= KEY_CONTROLMOD; + + SalKeyEvent aKeyEvt; + aKeyEvt.mnTime = GetMessageTime(); + if ( (cKeyCode >= 48) && (cKeyCode <= 57) ) + aKeyEvt.mnCode = KEY_0+(cKeyCode-48); + else + aKeyEvt.mnCode = KEY_A+(cKeyCode-97); + aKeyEvt.mnCode |= nModCode; + aKeyEvt.mnCharCode = cKeyCode; + aKeyEvt.mnRepeat = 0; + long nRet = pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYINPUT, &aKeyEvt ); + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_KEYUP, &aKeyEvt ); + return (nRet != 0); + } + } + } + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +static void ImplHandleInputLangChange( HWND hWnd, WPARAM wParam, LPARAM lParam ) +{ + ImplSalYieldMutexAcquireWithWait(); + + // Feststellen, ob wir IME unterstuetzen + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame && pFrame->maFrameData.mbIME && pFrame->maFrameData.mhDefIMEContext ) + { + HWND hWnd = pFrame->maFrameData.mhWnd; + HKL hKL = (HKL)lParam; + UINT nImeProps = ImmGetProperty( hKL, IGP_PROPERTY ); + + pFrame->maFrameData.mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; + pFrame->maFrameData.mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; + pFrame->maFrameData.mbHandleIME = !pFrame->maFrameData.mbSpezIME; + } + + ImplSalYieldMutexRelease(); +} + +// ----------------------------------------------------------------------- + +static BOOL ImplHandleIMEStartComposition( HWND hWnd ) +{ + BOOL bDef = TRUE; + + ImplSalYieldMutexAcquireWithWait(); + + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + { + if ( pFrame->maFrameData.mbHandleIME ) + { + HIMC hIMC = ImmGetContext( hWnd ); + if ( hIMC ) + { + // Cursor-Position ermitteln und aus der die Default-Position fuer + // das Composition-Fenster berechnen + SalCursorPosEvent aCursorPosEvt; + pFrame->maFrameData.mpProc( pFrame->maFrameData.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 + + ImmReleaseContext( hWnd, hIMC ); + } + + pFrame->maFrameData.mbCompositionMode = TRUE; + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_STARTEXTTEXTINPUT, (void*)NULL ); + if ( pFrame->maFrameData.mbAtCursorIME ) + bDef = FALSE; + } + } + + ImplSalYieldMutexRelease(); + + return bDef; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplHandleIMEComposition( HWND hWnd, LPARAM lParam ) +{ + BOOL bDef = TRUE; + if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) ) + { + ImplSalYieldMutexAcquireWithWait(); + + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame && pFrame->maFrameData.mbHandleIME && + (pFrame->maFrameData.mbCompositionMode || !(lParam & GCS_RESULTSTR)) ) + { + HIMC hIMC = ImmGetContext( hWnd ); + if ( hIMC ) + { + SalExtTextInputEvent aEvt; + aEvt.mnTime = GetMessageTime(); + aEvt.mpTextAttr = NULL; + aEvt.mnCursorPos = 0; + aEvt.mnDeltaStart = 0; + aEvt.mbOnlyCursor = FALSE; + aEvt.mbCursorVisible = !pFrame->maFrameData.mbCandidateMode; + + LONG nTextLen; + xub_Unicode* pTextBuf = NULL; + LONG nAttrLen; + WIN_BYTE* pAttrBuf = NULL; + BOOL bLastCursor = FALSE; + if ( lParam & GCS_RESULTSTR ) + { + nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, 0, 0 ) / sizeof( WCHAR ); + if ( nTextLen >= 0 ) + { + pTextBuf = new xub_Unicode[nTextLen]; + ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf, nTextLen*sizeof( WCHAR ) ); + } + + bLastCursor = TRUE; + aEvt.mbCursorVisible = TRUE; + bDef = FALSE; + } + else if ( pFrame->maFrameData.mbAtCursorIME ) + { + bDef = FALSE; + if ( lParam & (GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) ) + { + nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ) / sizeof( WCHAR ); + if ( nTextLen >= 0 ) + { + pTextBuf = new xub_Unicode[nTextLen]; + ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf, nTextLen*sizeof( WCHAR ) ); + } + + nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, 0, 0 ); + if ( nAttrLen >= 0 ) + { + pAttrBuf = new WIN_BYTE[nAttrLen]; + ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf, nAttrLen ); + } + + aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) ); + aEvt.mnDeltaStart = LOWORD( ImmGetCompositionStringW( hIMC, GCS_DELTASTART, 0, 0 ) ); + + if ( lParam == GCS_CURSORPOS ) + aEvt.mbOnlyCursor = TRUE; + } + } + + USHORT* pSalAttrAry = NULL; + if ( pTextBuf ) + { + aEvt.maText = XubString( pTextBuf, (USHORT)nTextLen ); + delete pTextBuf; + if ( pAttrBuf ) + { + xub_StrLen nTextLen = aEvt.maText.Len(); + if ( nTextLen ) + { + pSalAttrAry = new USHORT[nTextLen]; + memset( pSalAttrAry, 0, nTextLen*sizeof( USHORT ) ); + for ( xub_StrLen i = 0; (i < nTextLen) && (i < nAttrLen); i++ ) + { + WIN_BYTE nWinAttr = pAttrBuf[i]; + USHORT nSalAttr; + if ( nWinAttr == ATTR_TARGET_CONVERTED ) + { + nSalAttr = SAL_EXTTEXTINPUT_ATTR_TARGETCONVERTED | SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT; + aEvt.mbCursorVisible = FALSE; + } + else if ( nWinAttr == ATTR_CONVERTED ) + nSalAttr = SAL_EXTTEXTINPUT_ATTR_CONVERTED | SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE; + else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED ) + nSalAttr = SAL_EXTTEXTINPUT_ATTR_TARGETNOTCONVERTED | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE; + else if ( nWinAttr == ATTR_INPUT_ERROR ) + nSalAttr = SAL_EXTTEXTINPUT_ATTR_INPUTERROR | SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE; + else /* ( nWinAttr == 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(); + } + + ImmReleaseContext( hWnd, hIMC ); + + // Handler rufen und wenn wir ein Attribute-Array haben, danach + // wieder zerstoeren + if ( !bDef ) + { + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_EXTTEXTINPUT, (void*)&aEvt ); + } + if ( pSalAttrAry ) + delete pSalAttrAry; + } + + ImplSalYieldMutexRelease(); + } + } + + return bDef; +} + +// ----------------------------------------------------------------------- + +static BOOL ImplHandleIMEEndComposition( HWND hWnd ) +{ + BOOL bDef = TRUE; + + ImplSalYieldMutexAcquireWithWait(); + + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame && pFrame->maFrameData.mbHandleIME ) + { + // Wir restaurieren den Background-Modus bei jeder Texteingabe, + // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen + if ( pFrame->maFrameData.mpGraphics && + pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC ) + SetBkMode( pFrame->maFrameData.mpGraphics->maGraphicsData.mhDC, TRANSPARENT ); + + pFrame->maFrameData.mbCompositionMode = FALSE; + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + SALEVENT_ENDEXTTEXTINPUT, (void*)NULL ); + if ( pFrame->maFrameData.mbAtCursorIME ) + bDef = FALSE; + } + + ImplSalYieldMutexRelease(); + + return bDef; +} + +// ----------------------------------------------------------------------- + +static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam ) +{ + if ( wParam == (WPARAM)IMN_OPENCANDIDATE ) + { + ImplSalYieldMutexAcquireWithWait(); + + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame && pFrame->maFrameData.mbHandleIME && + pFrame->maFrameData.mbAtCursorIME ) + { + // Wir wollen den Cursor hiden + pFrame->maFrameData.mbCandidateMode = TRUE; + ImplHandleIMEComposition( hWnd, GCS_CURSORPOS ); + + HWND hWnd = pFrame->maFrameData.mhWnd; + HIMC hIMC = ImmGetContext( hWnd ); + if ( hIMC ) + { + LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ); + if ( nBufLen >= 1 ) + { + USHORT nCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) ); + SalExtTextInputPosEvent aEvt; + aEvt.mnTime = GetMessageTime(); + aEvt.mnFirstPos = nCursorPos; + aEvt.mnChars = nBufLen/sizeof(sal_Unicode) - nCursorPos; + aEvt.mpPosAry = new SalExtCharPos[aEvt.mnChars]; + memset( aEvt.mpPosAry, 0, aEvt.mnChars*sizeof(SalExtCharPos) ); + + pFrame->maFrameData.mpProc( pFrame->maFrameData.mpInst, pFrame, + 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; + } + + CANDIDATEFORM aForm; + aForm.dwIndex = 0; + aForm.dwStyle = CFS_EXCLUDE; + aForm.ptCurrentPos.x = aEvt.mpPosAry[0].mnX; + aForm.ptCurrentPos.y = nMaxBottom+1; + aForm.rcArea.left = nMinLeft; + aForm.rcArea.top = nMinTop; + aForm.rcArea.right = nMaxRight+1; + aForm.rcArea.bottom = nMaxBottom+1; + ImmSetCandidateWindow( hIMC, &aForm ); + + delete aEvt.mpPosAry; + } + + ImmReleaseContext( hWnd, hIMC ); + } + } + + ImplSalYieldMutexRelease(); + } + else if ( wParam == (WPARAM)IMN_CLOSECANDIDATE ) + { + ImplSalYieldMutexAcquireWithWait(); + SalFrame* pFrame = GetWindowPtr( hWnd ); + if ( pFrame ) + pFrame->maFrameData.mbCandidateMode = FALSE; + ImplSalYieldMutexRelease(); + } +} + + +// ----------------------------------------------------------------------- + +void SalTestMouseLeave() +{ + SalData* pSalData = GetSalData(); + + if ( pSalData->mhWantLeaveMsg && !::GetCapture() ) + { + POINT aPt; + GetCursorPos( &aPt ); + if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) ) + ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) ); + } +} + +// ----------------------------------------------------------------------- + +static int ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam , + LRESULT& rResult ) +{ + POINT aPt; + POINT aScreenPt; + aScreenPt.x = (short)LOWORD( lParam ); + aScreenPt.y = (short)HIWORD( lParam ); + // Child-Fenster suchen, welches an der entsprechenden + // Position liegt + HWND hChildWnd; + HWND hWheelWnd = hWnd; + do + { + hChildWnd = hWheelWnd; + aPt = aScreenPt; + ScreenToClient( hChildWnd, &aPt ); + hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT ); + } + while ( hWheelWnd && (hWheelWnd != hChildWnd) ); + if ( hWheelWnd && (hWheelWnd != hWnd) && + (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) ) + { + rResult = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam ); + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------- + +LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ) +{ + LRESULT nRet = 0; + static int bInWheelMsg = FALSE; + + // By WM_CRETAE we connect the frame with the window handle + if ( nMsg == WM_CREATE ) + { + // Window-Instanz am Windowhandle speichern + // Can also be used for the W-Version, because the struct + // to access lpCreateParams is the same structure + CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam; + SalFrame* pFrame = (SalFrame*)pStruct->lpCreateParams; + SetWindowPtr( hWnd, pFrame ); + // HWND schon hier setzen, da schon auf den Instanzdaten + // gearbeitet werden kann, wenn Messages waehrend + // CreateWindow() gesendet werden + pFrame->maFrameData.mhWnd = hWnd; + pFrame->maFrameData.maSysData.hWnd = hWnd; + return 0; + } + + switch( nMsg ) + { + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_NCMOUSEMOVE: + case SAL_MSG_MOUSELEAVE: + ImplSalYieldMutexAcquireWithWait(); + rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam ); + ImplSalYieldMutexRelease(); + break; + + case WM_MOUSEACTIVATE: + if ( LOWORD( lParam ) == HTCLIENT ) + { + ImplSalYieldMutexAcquireWithWait(); + nRet = ImplHandleMouseActivateMsg( hWnd ); + ImplSalYieldMutexRelease(); + if ( nRet ) + { + nRet = MA_NOACTIVATE; + rDef = FALSE; + } + } + break; + + case WM_KEYDOWN: + case WM_KEYUP: + case WM_DEADCHAR: + case WM_CHAR: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_SYSCHAR: + ImplSalYieldMutexAcquireWithWait(); + rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam ); + ImplSalYieldMutexRelease(); + break; + + case WM_MOUSEWHEEL: + // Gegen Rekursion absichern, falls wir vom IE oder dem externen + // Fenster die Message wieder zurueckbekommen + if ( !bInWheelMsg ) + { + bInWheelMsg++; + rDef = !ImplHandleWheelMsg( hWnd, wParam, lParam ); + // Wenn wir die Message nicht ausgewertet haben, schauen wir + // noch einmal nach, ob dort ein geplugtes Fenster steht, + // welches wir dann benachrichtigen + if ( rDef ) + rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet ); + bInWheelMsg--; + } + break; + + case WM_SYSCOMMAND: + ImplSalYieldMutexAcquireWithWait(); + nRet = ImplHandleSysCommand( hWnd, wParam, lParam ); + ImplSalYieldMutexRelease(); + if ( nRet ) + rDef = FALSE; + break; + + case WM_MOVE: + case SAL_MSG_POSTMOVE: + ImplHandleMoveMsg( hWnd ); + rDef = FALSE; + break; + case WM_SIZE: + ImplHandleSizeMsg( hWnd, wParam, lParam ); + rDef = FALSE; + break; + case SAL_MSG_POSTCALLSIZE: + ImplCallSizeHdl( hWnd ); + rDef = FALSE; + break; + + case WM_GETMINMAXINFO: + if ( ImplHandleMinMax( hWnd, lParam ) ) + rDef = FALSE; + break; + + case WM_ERASEBKGND: + nRet = 1; + rDef = FALSE; + break; + case WM_PAINT: + ImplHandlePaintMsg( hWnd ); + rDef = FALSE; + break; + case SAL_MSG_POSTPAINT: + ImplHandlePaintMsg2( hWnd, (RECT*)wParam ); + rDef = FALSE; + break; + + case SAL_MSG_FORCEPALETTE: + ImplHandleForcePalette( hWnd ); + rDef = FALSE; + break; + + case WM_QUERYNEWPALETTE: + case SAL_MSG_POSTQUERYNEWPAL: + nRet = ImplHandlePalette( TRUE, hWnd, nMsg, wParam, lParam, rDef ); + break; + + case WM_ACTIVATE: + // Wenn wir aktiviert werden, dann wollen wir auch unsere + // Palette setzen. Wir machen dieses in Activate, + // damit andere externe Child-Fenster auch unsere Palette + // ueberschreiben koennen. So wird unsere jedenfalls nur einmal + // gesetzt und nicht immer rekursiv, da an allen anderen Stellen + // diese nur als Background-Palette gesetzt wird + if ( LOWORD( wParam ) != WA_INACTIVE ) + ImplSendMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 ); + break; + + case WM_SETFOCUS: + case WM_KILLFOCUS: + case SAL_MSG_POSTFOCUS: + ImplHandleFocusMsg( hWnd ); + rDef = FALSE; + break; + + case WM_CLOSE: + ImplHandleCloseMsg( hWnd ); + rDef = FALSE; + break; + + case WM_QUERYENDSESSION: + nRet = !ImplHandleShutDownMsg( hWnd ); + rDef = FALSE; + break; + +#ifdef WM_DISPLAYCHANGE + case WM_DISPLAYCHANGE: +#endif +#ifdef WM_SETTINGCHANGE + case WM_SETTINGCHANGE: +#else + case WM_WININICHANGE: +#endif + case WM_DEVMODECHANGE: + case WM_FONTCHANGE: + case WM_SYSCOLORCHANGE: + case WM_TIMECHANGE: + ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam ); + break; + + case SAL_MSG_USEREVENT: + ImplHandleUserEvent( hWnd, lParam ); + rDef = FALSE; + break; + + case SAL_MSG_CAPTUREMOUSE: + SetCapture( hWnd ); + rDef = FALSE; + break; + case SAL_MSG_RELEASEMOUSE: + if ( ::GetCapture() == hWnd ) + ReleaseCapture(); + rDef = FALSE; + break; + case SAL_MSG_TOTOP: + ImplSalToTop( hWnd, (USHORT)wParam ); + rDef = FALSE; + break; + case SAL_MSG_SHOW: + ImplSalShow( hWnd, (BOOL)wParam ); + rDef = FALSE; + break; + + case WM_INPUTLANGCHANGE: + ImplHandleInputLangChange( hWnd, wParam, lParam ); + break; + + case WM_IME_STARTCOMPOSITION: + rDef = ImplHandleIMEStartComposition( hWnd ); + break; + + case WM_IME_COMPOSITION: + rDef = ImplHandleIMEComposition( hWnd, lParam ); + break; + + case WM_IME_ENDCOMPOSITION: + rDef = ImplHandleIMEEndComposition( hWnd ); + break; + + case WM_IME_NOTIFY: + ImplHandleIMENotify( hWnd, wParam ); + break; + } + + // WheelMouse-Message abfangen + if ( rDef && (nMsg == aSalShlData.mnWheelMsgId) && aSalShlData.mnWheelMsgId ) + { + // Gegen Rekursion absichern, falls wir vom IE oder dem externen + // Fenster die Message wieder zurueckbekommen + if ( !bInWheelMsg ) + { + bInWheelMsg++; + // Zuerst wollen wir die Message dispatchen und dann darf auch + // das SystemWindow drankommen + WORD nKeyState = 0; + if ( GetKeyState( VK_SHIFT ) & 0x8000 ) + nKeyState |= MK_SHIFT; + if ( GetKeyState( VK_CONTROL ) & 0x8000 ) + nKeyState |= MK_CONTROL; + // Mutex handling is inside from this call + rDef = !ImplHandleWheelMsg( hWnd, MAKEWPARAM( nKeyState, (WORD)wParam ), lParam ); + if ( rDef ) + { + HWND hWheelWnd = ::GetFocus(); + if ( hWheelWnd && (hWheelWnd != hWnd) ) + { + nRet = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam ); + rDef = FALSE; + } + else + rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet ); + } + bInWheelMsg--; + } + } + + return nRet; +} + +LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam ); + return nRet; +} + +LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam ); + return nRet; +} + +// ----------------------------------------------------------------------- + +BOOL ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult ) +{ + // Hier verarbeiten wir alle Messages, die fuer alle Frame-Fenster gelten, + // damit diese nur einmal verarbeitet werden + // Must work for Unicode and none Unicode + if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) ) + { + int bDef = TRUE; + rlResult = ImplHandlePalette( FALSE, hWnd, nMsg, wParam, lParam, bDef ); + return (bDef != 0); + } + else + return FALSE; +} diff --git a/vcl/win/source/window/salobj.cxx b/vcl/win/source/window/salobj.cxx new file mode 100644 index 000000000000..39b233de05e6 --- /dev/null +++ b/vcl/win/source/window/salobj.cxx @@ -0,0 +1,873 @@ +/************************************************************************* + * + * $RCSfile: salobj.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:05:50 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> + +#ifndef _SVWIN_HXX +#include <tools/svwin.h> +#endif + +#define _SV_SALOBJ_CXX + +#ifndef _SV_WINCOMP_HXX +#include <wincomp.hxx> +#endif +#ifndef _SV_SALDATA_HXX +#include <saldata.hxx> +#endif +#ifndef _SV_SALINST_HXX +#include <salinst.hxx> +#endif +#ifndef _SV_SALFRAME_HXX +#include <salframe.hxx> +#endif +#ifndef _SV_SALOBJ_HXX +#include <salobj.hxx> +#endif + +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif + +// ======================================================================= + +static BOOL ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild ) +{ + if ( hWndParent == hWndChild ) + return TRUE; + + HWND hTempWnd = ::GetParent( hWndChild ); + while ( hTempWnd ) + { + // Ab nicht Child-Fenstern hoeren wir auf zu suchen + if ( !(GetWindowStyle( hTempWnd ) & WS_CHILD) ) + return FALSE; + if ( hTempWnd == hWndParent ) + return TRUE; + hTempWnd = ::GetParent( hTempWnd ); + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +SalObject* ImplFindSalObject( HWND hWndChild ) +{ + SalData* pSalData = GetSalData(); + SalObject* pObject = pSalData->mpFirstObject; + while ( pObject ) + { + if ( ImplIsSysWindowOrChild( pObject->maObjectData.mhWndChild, hWndChild ) ) + return pObject; + + pObject = pObject->maObjectData.mpNextObject; + } + + return NULL; +} + +// ----------------------------------------------------------------------- + +SalFrame* ImplFindSalObjectFrame( HWND hWnd ) +{ + SalFrame* pFrame = NULL; + SalObject* pObject = ImplFindSalObject( hWnd ); + if ( pObject ) + { + // Dazugehoerenden Frame suchen + HWND hWnd = ::GetParent( pObject->maObjectData.mhWnd ); + pFrame = GetSalData()->mpFirstFrame; + while ( pFrame ) + { + if ( pFrame->maFrameData.mhWnd == hWnd ) + break; + + pFrame = pFrame->maFrameData.mpNextFrame; + } + } + + return pFrame; +} + +// ----------------------------------------------------------------------- + +LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam ) +{ + // Used for Unicode and none Unicode + SalData* pSalData = GetSalData(); + + if ( (nCode >= 0) && lParam ) + { + CWPSTRUCT* pData = (CWPSTRUCT*)lParam; + if ( (pData->message != WM_KEYDOWN) && + (pData->message != WM_KEYUP) ) + pSalData->mnSalObjWantKeyEvt = 0; + + // Testen, ob wir Daten fuer ein SalObject-Fenster behandeln + // muessen + SalObject* pObject; + if ( pData->message == WM_SETFOCUS ) + { + pObject = ImplFindSalObject( pData->hwnd ); + if ( pObject ) + { + pObject->maObjectData.mhLastFocusWnd = pData->hwnd; + if ( ImplSalYieldMutexTryToAcquire() ) + { + pObject->maObjectData.mpProc( pObject->maObjectData.mpInst, pObject, + SALOBJ_EVENT_GETFOCUS, 0 ); + ImplSalYieldMutexRelease(); + } + else + ImplPostMessage( pObject->maObjectData.mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 ); + } + } + else if ( pData->message == WM_KILLFOCUS ) + { + pObject = ImplFindSalObject( pData->hwnd ); + if ( pObject && !ImplFindSalObject( (HWND)pData->wParam ) ) + { + // LoseFocus nur rufen, wenn wirklich kein ChildFenster + // den Focus bekommt + if ( !pData->wParam || !ImplFindSalObject( (HWND)pData->wParam ) ) + { + if ( ImplSalYieldMutexTryToAcquire() ) + { + pObject->maObjectData.mpProc( pObject->maObjectData.mpInst, pObject, + SALOBJ_EVENT_LOSEFOCUS, 0 ); + ImplSalYieldMutexRelease(); + } + else + ImplPostMessage( pObject->maObjectData.mhWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 ); + } + else + pObject->maObjectData.mhLastFocusWnd = (HWND)pData->wParam; + } + } + } + + return CallNextHookEx( pSalData->mhSalObjMsgHook, nCode, wParam, lParam ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplSalPreDispatchMsg( MSG* pMsg ) +{ + // Used for Unicode and none Unicode + SalData* pSalData = GetSalData(); + SalObject* pObject; + + if ( (pMsg->message == WM_LBUTTONDOWN) || + (pMsg->message == WM_RBUTTONDOWN) || + (pMsg->message == WM_MBUTTONDOWN) ) + { + ImplSalYieldMutexAcquireWithWait(); + pObject = ImplFindSalObject( pMsg->hwnd ); + if ( pObject ) + ImplPostMessage( pObject->maObjectData.mhWnd, SALOBJ_MSG_TOTOP, 0, 0 ); + ImplSalYieldMutexRelease(); + } + + if ( (pMsg->message == WM_KEYDOWN) || + (pMsg->message == WM_KEYUP) ) + { + // KeyEvents wollen wir nach Moeglichkeit auch abarbeiten, + // wenn das Control diese nicht selber auswertet + // SysKeys werden als WM_SYSCOMMAND verarbeitet + // Char-Events verarbeiten wir nicht, da wir nur + // Accelerator relevante Keys verarbeiten wollen + BOOL bWantedKeyCode = FALSE; + // A-Z, 0-9 nur in Verbindung mit Control-Taste + if ( ((pMsg->wParam >= 65) && (pMsg->wParam <= 90)) || + ((pMsg->wParam >= 48) && (pMsg->wParam <= 57)) ) + { + if ( GetKeyState( VK_CONTROL ) & 0x8000 ) + bWantedKeyCode = TRUE; + } + else if ( ((pMsg->wParam >= VK_F1) && (pMsg->wParam <= VK_F24)) || + ((pMsg->wParam >= VK_SPACE) && (pMsg->wParam <= VK_HELP)) || + (pMsg->wParam == VK_BACK) || (pMsg->wParam == VK_TAB) || + (pMsg->wParam == VK_CLEAR) || (pMsg->wParam == VK_RETURN) || + (pMsg->wParam == VK_ESCAPE) ) + bWantedKeyCode = TRUE; + if ( bWantedKeyCode ) + { + ImplSalYieldMutexAcquireWithWait(); + pObject = ImplFindSalObject( pMsg->hwnd ); + if ( pObject ) + pSalData->mnSalObjWantKeyEvt = pMsg->wParam; + ImplSalYieldMutexRelease(); + } + } + // Hier WM_SYSCHAR abfangen, um mit Alt+Taste evtl. Menu zu aktivieren + else if ( pMsg->message == WM_SYSCHAR ) + { + pSalData->mnSalObjWantKeyEvt = 0; + + USHORT nKeyCode = LOWORD( pMsg->wParam ); + // Nur 0-9 und A-Z + if ( ((nKeyCode >= 48) && (nKeyCode <= 57)) || + ((nKeyCode >= 65) && (nKeyCode <= 90)) || + ((nKeyCode >= 97) && (nKeyCode <= 122)) ) + { + BOOL bRet = FALSE; + ImplSalYieldMutexAcquireWithWait(); + pObject = ImplFindSalObject( pMsg->hwnd ); + if ( pObject ) + { + if ( pMsg->hwnd == ::GetFocus() ) + { + SalFrame* pFrame = ImplFindSalObjectFrame( pMsg->hwnd ); + if ( pFrame ) + { + if ( ImplHandleSalObjSysCharMsg( pFrame->maFrameData.mhWnd, pMsg->wParam, pMsg->lParam ) ) + bRet = TRUE; + } + } + } + ImplSalYieldMutexRelease(); + if ( bRet ) + return TRUE; + } + } + else + pSalData->mnSalObjWantKeyEvt = 0; + + return FALSE; +} + +// ----------------------------------------------------------------------- + +void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT /* nDispatchResult */ ) +{ + // Used for Unicode and none Unicode + SalData* pSalData = GetSalData(); + SalFrame* pFrame; + + if ( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_KEYUP) ) + { + if ( pSalData->mnSalObjWantKeyEvt == pMsg->wParam ) + { + pSalData->mnSalObjWantKeyEvt = 0; + if ( pMsg->hwnd == ::GetFocus() ) + { + ImplSalYieldMutexAcquireWithWait(); + pFrame = ImplFindSalObjectFrame( pMsg->hwnd ); + if ( pFrame ) + ImplHandleSalObjKeyMsg( pFrame->maFrameData.mhWnd, pMsg->message, pMsg->wParam, pMsg->lParam ); + ImplSalYieldMutexRelease(); + } + } + } + + pSalData->mnSalObjWantKeyEvt = 0; +} + +// ======================================================================= + +LRESULT CALLBACK SalSysObjWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ) +{ + SalObject* pSysObj; + LRESULT nRet = 0; + + switch( nMsg ) + { + case WM_ERASEBKGND: + nRet = 1; + rDef = FALSE; + break; + case WM_PAINT: + { + PAINTSTRUCT aPs; + BeginPaint( hWnd, &aPs ); + EndPaint( hWnd, &aPs ); + rDef = FALSE; + } + break; + + case WM_PARENTNOTIFY: + { + UINT nNotifyMsg = LOWORD( wParam ); + if ( (nNotifyMsg == WM_LBUTTONDOWN) || + (nNotifyMsg == WM_RBUTTONDOWN) || + (nNotifyMsg == WM_MBUTTONDOWN) ) + { + ImplSalYieldMutexAcquireWithWait(); + pSysObj = GetSalObjWindowPtr( hWnd ); + if ( pSysObj ) + pSysObj->maObjectData.mpProc( pSysObj->maObjectData.mpInst, pSysObj, SALOBJ_EVENT_TOTOP, 0 ); + ImplSalYieldMutexRelease(); + } + } + break; + + case WM_MOUSEACTIVATE: + ImplPostMessage( hWnd, SALOBJ_MSG_TOTOP, 0, 0 ); + break; + + case SALOBJ_MSG_TOTOP: + if ( ImplSalYieldMutexTryToAcquire() ) + { + pSysObj = GetSalObjWindowPtr( hWnd ); + pSysObj->maObjectData.mpProc( pSysObj->maObjectData.mpInst, pSysObj, + SALOBJ_EVENT_TOTOP, 0 ); + ImplSalYieldMutexRelease(); + rDef = FALSE; + } + else + ImplPostMessage( hWnd, SALOBJ_MSG_TOTOP, 0, 0 ); + break; + + case SALOBJ_MSG_POSTFOCUS: + if ( ImplSalYieldMutexTryToAcquire() ) + { + pSysObj = GetSalObjWindowPtr( hWnd ); + HWND hFocusWnd = ::GetFocus(); + USHORT nEvent; + if ( hFocusWnd && ImplIsSysWindowOrChild( hWnd, hFocusWnd ) ) + nEvent = SALOBJ_EVENT_GETFOCUS; + else + nEvent = SALOBJ_EVENT_LOSEFOCUS; + pSysObj->maObjectData.mpProc( pSysObj->maObjectData.mpInst, pSysObj, + nEvent, 0 ); + ImplSalYieldMutexRelease(); + } + else + ImplPostMessage( hWnd, SALOBJ_MSG_POSTFOCUS, 0, 0 ); + rDef = FALSE; + break; + + case WM_SIZE: + { + HWND hWndChild = GetWindow( hWnd, GW_CHILD ); + if ( hWndChild ) + { + SetWindowPos( hWndChild, + 0, 0, 0, (int)LOWORD( lParam ), (int)HIWORD( lParam ), + SWP_NOZORDER | SWP_NOACTIVATE ); + } + } + rDef = FALSE; + break; + + case WM_CREATE: + { + // Window-Instanz am Windowhandle speichern + // Can also be used for the W-Version, because the struct + // to access lpCreateParams is the same structure + CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam; + pSysObj = (SalObject*)pStruct->lpCreateParams; + SetSalObjWindowPtr( hWnd, pSysObj ); + // HWND schon hier setzen, da schon auf den Instanzdaten + // gearbeitet werden kann, wenn Messages waehrend + // CreateWindow() gesendet werden + pSysObj->maObjectData.mhWnd = hWnd; + rDef = FALSE; + } + break; + } + + return nRet; +} + +LRESULT CALLBACK SalSysObjWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalSysObjWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam ); + return nRet; +} + +LRESULT CALLBACK SalSysObjWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalSysObjWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam ); + return nRet; +} + +// ----------------------------------------------------------------------- + +LRESULT CALLBACK SalSysObjChildWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ) +{ + LRESULT nRet = 0; + + switch( nMsg ) + { + // Wegen PlugIn's loeschen wir erstmal den Hintergrund +/* + case WM_ERASEBKGND: + nRet = 1; + rDef = FALSE; + break; +*/ + case WM_PAINT: + { + PAINTSTRUCT aPs; + BeginPaint( hWnd, &aPs ); + EndPaint( hWnd, &aPs ); + rDef = FALSE; + } + break; + } + + return nRet; +} + +LRESULT CALLBACK SalSysObjChildWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalSysObjChildWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam ); + return nRet; +} + +LRESULT CALLBACK SalSysObjChildWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) +{ + int bDef = TRUE; + LRESULT nRet = SalSysObjChildWndProc( hWnd, nMsg, wParam, lParam, bDef ); + if ( bDef ) + nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam ); + return nRet; +} + +// ======================================================================= + +SalObject* ImplSalCreateObject( SalInstance* pInst, SalFrame* pParent ) +{ + SalData* pSalData = GetSalData(); + + // Hook installieren, wenn es das erste SalObject ist + if ( !pSalData->mpFirstObject ) + { + if ( aSalShlData.mbWNT ) + { + pSalData->mhSalObjMsgHook = SetWindowsHookExW( WH_CALLWNDPROC, + SalSysMsgProc, + pSalData->mhInst, + pSalData->mnAppThreadId ); + } + else + { + pSalData->mhSalObjMsgHook = SetWindowsHookExA( WH_CALLWNDPROC, + SalSysMsgProc, + pSalData->mhInst, + pSalData->mnAppThreadId ); + } + } + + if ( !pSalData->mbObjClassInit ) + { + if ( aSalShlData.mbWNT ) + { + WNDCLASSEXW aWndClassEx; + aWndClassEx.cbSize = sizeof( aWndClassEx ); + aWndClassEx.style = 0; + aWndClassEx.lpfnWndProc = SalSysObjWndProcW; + aWndClassEx.cbClsExtra = 0; + aWndClassEx.cbWndExtra = SAL_OBJECT_WNDEXTRA; + aWndClassEx.hInstance = pSalData->mhInst; + aWndClassEx.hIcon = 0; + aWndClassEx.hIconSm = 0; + aWndClassEx.hCursor = LoadCursor( 0, IDC_ARROW ); + aWndClassEx.hbrBackground = 0; + aWndClassEx.lpszMenuName = 0; + aWndClassEx.lpszClassName = SAL_OBJECT_CLASSNAMEW; + if ( RegisterClassExW( &aWndClassEx ) ) + { + // Wegen PlugIn's loeschen wir erstmal den Hintergrund + aWndClassEx.cbWndExtra = 0; + aWndClassEx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + aWndClassEx.lpfnWndProc = SalSysObjChildWndProcW; + aWndClassEx.lpszClassName = SAL_OBJECT_CHILDCLASSNAMEW; + if ( RegisterClassExW( &aWndClassEx ) ) + pSalData->mbObjClassInit = TRUE; + } + } + else + { + WNDCLASSEXA aWndClassEx; + aWndClassEx.cbSize = sizeof( aWndClassEx ); + aWndClassEx.style = 0; + aWndClassEx.lpfnWndProc = SalSysObjWndProcA; + aWndClassEx.cbClsExtra = 0; + aWndClassEx.cbWndExtra = SAL_OBJECT_WNDEXTRA; + aWndClassEx.hInstance = pSalData->mhInst; + aWndClassEx.hIcon = 0; + aWndClassEx.hIconSm = 0; + aWndClassEx.hCursor = LoadCursor( 0, IDC_ARROW ); + aWndClassEx.hbrBackground = 0; + aWndClassEx.lpszMenuName = 0; + aWndClassEx.lpszClassName = SAL_OBJECT_CLASSNAMEA; + if ( RegisterClassExA( &aWndClassEx ) ) + { + // Wegen PlugIn's loeschen wir erstmal den Hintergrund + aWndClassEx.cbWndExtra = 0; + aWndClassEx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + aWndClassEx.lpfnWndProc = SalSysObjChildWndProcA; + aWndClassEx.lpszClassName = SAL_OBJECT_CHILDCLASSNAMEA; + if ( RegisterClassExA( &aWndClassEx ) ) + pSalData->mbObjClassInit = TRUE; + } + } + } + + if ( pSalData->mbObjClassInit ) + { + SalObject* pObject = new SalObject; + HWND hWnd; + HWND hWndChild = 0; + if ( aSalShlData.mbWNT ) + { + hWnd = CreateWindowExW( 0, SAL_OBJECT_CLASSNAMEW, L"", + WS_CHILD, 0, 0, 0, 0, + pParent->maFrameData.mhWnd, 0, + pInst->maInstData.mhInst, (void*)pObject ); + if ( hWnd ) + { + hWndChild = CreateWindowExW( 0, SAL_OBJECT_CHILDCLASSNAMEW, L"", + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, + 0, 0, 0, 0, + hWnd, 0, + pInst->maInstData.mhInst, NULL ); + } + } + else + { + hWnd = CreateWindowExA( 0, SAL_OBJECT_CLASSNAMEA, "", + WS_CHILD, 0, 0, 0, 0, + pParent->maFrameData.mhWnd, 0, + pInst->maInstData.mhInst, (void*)pObject ); + if ( hWnd ) + { + hWndChild = CreateWindowExA( 0, SAL_OBJECT_CHILDCLASSNAMEA, "", + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, + 0, 0, 0, 0, + hWnd, 0, + pInst->maInstData.mhInst, NULL ); + } + } + if ( !hWndChild ) + { + delete pObject; + return NULL; + } + + if ( hWnd ) + { + pObject->maObjectData.mhWnd = hWnd; + pObject->maObjectData.mhWndChild = hWndChild; + pObject->maObjectData.maSysData.hWnd = hWndChild; + return pObject; + } + } + + return NULL; +} + +// ======================================================================= + +long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* ) +{ + return 0; +} + +// ======================================================================= + +SalObject::SalObject() +{ + SalData* pSalData = GetSalData(); + + maObjectData.mhWnd = 0; + maObjectData.mhWndChild = 0; + maObjectData.mhLastFocusWnd = 0; + maObjectData.maSysData.nSize = sizeof( SystemEnvData ); + maObjectData.mpInst = NULL; + maObjectData.mpProc = ImplSalObjCallbackDummy; + maObjectData.mpStdClipRgnData = NULL; + + // Insert object in objectlist + maObjectData.mpNextObject = pSalData->mpFirstObject; + pSalData->mpFirstObject = this; +} + +// ----------------------------------------------------------------------- + +SalObject::~SalObject() +{ + SalData* pSalData = GetSalData(); + + // remove frame from framelist + if ( this == pSalData->mpFirstObject ) + { + pSalData->mpFirstObject = maObjectData.mpNextObject; + + // Wenn letztes SalObject, dann Hook wieder entfernen + if ( !pSalData->mpFirstObject ) + UnhookWindowsHookEx( pSalData->mhSalObjMsgHook ); + } + else + { + SalObject* pTempObject = pSalData->mpFirstObject; + while ( pTempObject->maObjectData.mpNextObject != this ) + pTempObject = pTempObject->maObjectData.mpNextObject; + + pTempObject->maObjectData.mpNextObject = maObjectData.mpNextObject; + } + + // Cache-Daten zerstoeren + if ( maObjectData.mpStdClipRgnData ) + delete maObjectData.mpStdClipRgnData; + + HWND hWndParent = ::GetParent( maObjectData.mhWnd ); + + if ( maObjectData.mhWndChild ) + DestroyWindow( maObjectData.mhWndChild ); + if ( maObjectData.mhWnd ) + DestroyWindow( maObjectData.mhWnd ); + + // Palette wieder zuruecksetzen, wenn kein externes Child-Fenster + // mehr vorhanden ist, da diese unsere Palette ueberschrieben haben + // koennen + if ( hWndParent && + ::GetActiveWindow() == hWndParent && + !GetWindow( hWndParent, GW_CHILD ) ) + ImplSendMessage( hWndParent, SAL_MSG_FORCEPALETTE, 0, 0 ); +} + +// ----------------------------------------------------------------------- + +void SalObject::ResetClipRegion() +{ + SetWindowRgn( maObjectData.mhWnd, 0, TRUE ); +} + +// ----------------------------------------------------------------------- + +USHORT SalObject::GetClipRegionType() +{ + return SAL_OBJECT_CLIP_INCLUDERECTS; +} + +// ----------------------------------------------------------------------- + +void SalObject::BeginSetClipRegion( ULONG nRectCount ) +{ + ULONG nRectBufSize = sizeof(RECT)*nRectCount; + if ( nRectCount < SAL_CLIPRECT_COUNT ) + { + if ( !maObjectData.mpStdClipRgnData ) + maObjectData.mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))]; + maObjectData.mpClipRgnData = maObjectData.mpStdClipRgnData; + } + else + maObjectData.mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize]; + maObjectData.mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER ); + maObjectData.mpClipRgnData->rdh.iType = RDH_RECTANGLES; + maObjectData.mpClipRgnData->rdh.nCount = nRectCount; + maObjectData.mpClipRgnData->rdh.nRgnSize = nRectBufSize; + SetRectEmpty( &(maObjectData.mpClipRgnData->rdh.rcBound) ); + maObjectData.mpNextClipRect = (RECT*)(&(maObjectData.mpClipRgnData->Buffer)); + maObjectData.mbFirstClipRect = TRUE; +} + +// ----------------------------------------------------------------------- + +void SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + RECT* pRect = maObjectData.mpNextClipRect; + RECT* pBoundRect = &(maObjectData.mpClipRgnData->rdh.rcBound); + long nRight = nX + nWidth; + long nBottom = nY + nHeight; + + if ( maObjectData.mbFirstClipRect ) + { + pBoundRect->left = nX; + pBoundRect->top = nY; + pBoundRect->right = nRight; + pBoundRect->bottom = nBottom; + maObjectData.mbFirstClipRect = FALSE; + } + else + { + if ( nX < pBoundRect->left ) + pBoundRect->left = (int)nX; + + if ( nY < pBoundRect->top ) + pBoundRect->top = (int)nY; + + if ( nRight > pBoundRect->right ) + pBoundRect->right = (int)nRight; + + if ( nBottom > pBoundRect->bottom ) + pBoundRect->bottom = (int)nBottom; + } + + pRect->left = (int)nX; + pRect->top = (int)nY; + pRect->right = (int)nRight; + pRect->bottom = (int)nBottom; + maObjectData.mpNextClipRect++; +} + +// ----------------------------------------------------------------------- + +void SalObject::EndSetClipRegion() +{ + HRGN hRegion; + + // Aus den Region-Daten muessen wir jetzt eine ClipRegion erzeugen + if ( maObjectData.mpClipRgnData->rdh.nCount == 1 ) + { + RECT* pRect = &(maObjectData.mpClipRgnData->rdh.rcBound); + hRegion = CreateRectRgn( pRect->left, pRect->top, + pRect->right, pRect->bottom ); + } + else + { + ULONG nSize = maObjectData.mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER); + hRegion = ExtCreateRegion( NULL, nSize, maObjectData.mpClipRgnData ); + if ( maObjectData.mpClipRgnData != maObjectData.mpStdClipRgnData ) + delete maObjectData.mpClipRgnData; + } + + DBG_ASSERT( hRegion, "SalObject::EndSetClipRegion() - Can't create ClipRegion" ); + SetWindowRgn( maObjectData.mhWnd, hRegion, TRUE ); +} + +// ----------------------------------------------------------------------- + +void SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) +{ + ULONG nStyle = 0; + BOOL bVisible = (GetWindowStyle( maObjectData.mhWnd ) & WS_VISIBLE) != 0; + if ( bVisible ) + { + ShowWindow( maObjectData.mhWnd, SW_HIDE ); + nStyle |= SWP_SHOWWINDOW; + } + SetWindowPos( maObjectData.mhWnd, 0, + (int)nX, (int)nY, (int)nWidth, (int)nHeight, + SWP_NOZORDER | SWP_NOACTIVATE | nStyle ); +} + +// ----------------------------------------------------------------------- + +void SalObject::Show( BOOL bVisible ) +{ + if ( bVisible ) + ShowWindow( maObjectData.mhWnd, SW_SHOWNORMAL ); + else + ShowWindow( maObjectData.mhWnd, SW_HIDE ); +} + +// ----------------------------------------------------------------------- + +void SalObject::Enable( BOOL bEnable ) +{ + EnableWindow( maObjectData.mhWnd, bEnable ); +} + +// ----------------------------------------------------------------------- + +void SalObject::GrabFocus() +{ + if ( maObjectData.mhLastFocusWnd && + IsWindow( maObjectData.mhLastFocusWnd ) && + ImplIsSysWindowOrChild( maObjectData.mhWndChild, maObjectData.mhLastFocusWnd ) ) + ::SetFocus( maObjectData.mhLastFocusWnd ); + else + ::SetFocus( maObjectData.mhWndChild ); +} + +// ----------------------------------------------------------------------- + +void SalObject::SetBackground() +{ +} + +// ----------------------------------------------------------------------- + +void SalObject::SetBackground( SalColor nSalColor ) +{ +} + +// ----------------------------------------------------------------------- + +const SystemEnvData* SalObject::GetSystemData() const +{ + return &maObjectData.maSysData; +} + +// ----------------------------------------------------------------------- + +void SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc ) +{ + maObjectData.mpInst = pInst; + if ( pProc ) + maObjectData.mpProc = pProc; + else + maObjectData.mpProc = ImplSalObjCallbackDummy; +} |