| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <string.h> |
| |
| #include <osl/module.h> |
| |
| #include <tools/urlobj.hxx> |
| #include <tools/svwin.h> |
| #ifdef __MINGW32__ |
| #include <excpt.h> |
| #endif |
| |
| #include <win/wincomp.hxx> |
| #include <win/saldata.hxx> |
| #include <win/salinst.h> |
| #include <win/salgdi.h> |
| #include <win/salframe.h> |
| #include <win/salprn.h> |
| |
| #include <salptype.hxx> |
| #include <print.h> |
| #include <jobset.h> |
| |
| #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> |
| #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> |
| #include <com/sun/star/ui/dialogs/XFilePicker.hpp> |
| #include <com/sun/star/ui/dialogs/XFilterManager.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/lang/XInitialization.hpp> |
| #include <comphelper/processfactory.hxx> |
| |
| #include <malloc.h> |
| |
| #ifdef __MINGW32__ |
| #define CATCH_DRIVER_EX_BEGIN \ |
| jmp_buf jmpbuf; \ |
| __SEHandler han; \ |
| if (__builtin_setjmp(jmpbuf) == 0) \ |
| { \ |
| han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER) |
| |
| #define CATCH_DRIVER_EX_END(mes, p) \ |
| } \ |
| han.Reset() |
| #define CATCH_DRIVER_EX_END_2(mes) \ |
| } \ |
| han.Reset() |
| #else |
| #define CATCH_DRIVER_EX_BEGIN \ |
| __try \ |
| { |
| #define CATCH_DRIVER_EX_END(mes, p) \ |
| } \ |
| __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\ |
| { \ |
| DBG_ERROR( mes ); \ |
| p->markInvalid(); \ |
| } |
| #define CATCH_DRIVER_EX_END_2(mes) \ |
| } \ |
| __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\ |
| { \ |
| DBG_ERROR( mes ); \ |
| } |
| #endif |
| |
| |
| using namespace com::sun::star; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::lang; |
| using namespace com::sun::star::ui::dialogs; |
| using namespace rtl; |
| |
| // ======================================================================= |
| |
| static char aImplWindows[] = "windows"; |
| static char aImplDevices[] = "devices"; |
| static char aImplDevice[] = "device"; |
| |
| static LPDEVMODEA SAL_DEVMODE_A( const ImplJobSetup* pSetupData ) |
| { |
| LPDEVMODEA pRet = NULL; |
| SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData; |
| if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_A && |
| pSetupData->mnDriverDataLen >= sizeof(DEVMODEA)+sizeof(SalDriverData)-1 |
| ) |
| pRet = ((LPDEVMODEA)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset))); |
| return pRet; |
| } |
| |
| static LPDEVMODEW SAL_DEVMODE_W( const ImplJobSetup* pSetupData ) |
| { |
| LPDEVMODEW pRet = NULL; |
| SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData; |
| if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_W && |
| pSetupData->mnDriverDataLen >= sizeof(DEVMODEW)+sizeof(SalDriverData)-1 |
| ) |
| pRet = ((LPDEVMODEW)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset))); |
| return pRet; |
| } |
| |
| // ======================================================================= |
| |
| static sal_uLong ImplWinQueueStatusToSal( DWORD nWinStatus ) |
| { |
| sal_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; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static void getPrinterQueueInfoOldStyle( ImplPrnQueueList* pList ) |
| { |
| DWORD i; |
| DWORD n; |
| DWORD nBytes = 0; |
| DWORD nInfoPrn2; |
| sal_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*) rtl_allocateMemory( 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; |
| } |
| } |
| |
| // read printers from win.ini |
| // TODO: MSDN: GetProfileString() should not be called from server |
| // code because it is just there for WIN16 compatibility |
| 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 ); |
| } |
| |
| // extract printer names from buffer and fill list |
| char* pName = pBuf; |
| while ( *pName ) |
| { |
| char* pPortName; |
| char* pTmp; |
| char aPortBuf[256]; |
| GetProfileStringA( aImplDevices, pName, "", aPortBuf, sizeof( aPortBuf ) ); |
| |
| pPortName = aPortBuf; |
| |
| // create name |
| xub_StrLen nNameLen = sal::static_int_cast<xub_StrLen>(strlen( pName )); |
| XubString aName( ImplSalGetUniString( pName, nNameLen ) ); |
| |
| // get driver name |
| pTmp = pPortName; |
| while ( *pTmp != ',' ) |
| pTmp++; |
| XubString aDriver( ImplSalGetUniString( pPortName, (sal_uInt16)(pTmp-pPortName) ) ); |
| pPortName = pTmp; |
| |
| // get port names |
| do |
| { |
| pPortName++; |
| pTmp = pPortName; |
| while ( *pTmp && (*pTmp != ',') ) |
| pTmp++; |
| |
| String aPortName( ImplSalGetUniString( pPortName, (sal_uInt16)(pTmp-pPortName) ) ); |
| |
| // create new entry |
| // look up if printer was already found in first loop |
| sal_Bool bAdd = TRUE; |
| if ( pWinInfo2 ) |
| { |
| pGetInfo2 = pWinInfo2; |
| for ( n = 0; n < nInfoPrn2; n++ ) |
| { |
| if ( aName.EqualsIgnoreCaseAscii( pGetInfo2->pPrinterName ) ) |
| { |
| bAdd = FALSE; |
| break; |
| } |
| pGetInfo2++; |
| } |
| } |
| // if it's a new printer, add it |
| 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; |
| rtl_freeMemory( pWinInfo2 ); |
| } |
| |
| void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList ) |
| { |
| if( ! aSalShlData.mbWPrinter ) |
| { |
| getPrinterQueueInfoOldStyle( pList ); |
| return; |
| } |
| DWORD i; |
| DWORD nBytes = 0; |
| DWORD nInfoPrn4 = 0; |
| PRINTER_INFO_4W* pWinInfo4 = NULL; |
| EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0, &nBytes, &nInfoPrn4 ); |
| if ( nBytes ) |
| { |
| pWinInfo4 = (PRINTER_INFO_4W*) rtl_allocateMemory( nBytes ); |
| if ( EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, (LPBYTE)pWinInfo4, nBytes, &nBytes, &nInfoPrn4 ) ) |
| { |
| for ( i = 0; i < nInfoPrn4; i++ ) |
| { |
| SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo; |
| pInfo->maPrinterName = UniString( reinterpret_cast< const sal_Unicode* >(pWinInfo4[i].pPrinterName) ); |
| pInfo->mnStatus = 0; |
| pInfo->mnJobs = 0; |
| pInfo->mpSysData = NULL; |
| pList->Add( pInfo ); |
| } |
| } |
| rtl_freeMemory( pWinInfo4 ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static void getPrinterQueueStateOldStyle( SalPrinterQueueInfo* pInfo ) |
| { |
| 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*) rtl_allocateMemory( 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.Len() == 0 || |
| pInfo->maDriver.EqualsAscii( 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; |
| if( ! pInfo->mpSysData ) |
| pInfo->mpSysData = new XubString( aPortName ); |
| break; |
| } |
| |
| pGetInfo2++; |
| } |
| } |
| |
| rtl_freeMemory( pWinInfo2 ); |
| } |
| } |
| |
| void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo ) |
| { |
| if( ! aSalShlData.mbWPrinter ) |
| { |
| getPrinterQueueStateOldStyle( pInfo ); |
| return; |
| } |
| |
| HANDLE hPrinter = 0; |
| LPWSTR pPrnName = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pInfo->maPrinterName.GetBuffer())); |
| if( OpenPrinterW( pPrnName, &hPrinter, NULL ) ) |
| { |
| DWORD nBytes = 0; |
| GetPrinterW( hPrinter, 2, NULL, 0, &nBytes ); |
| if( nBytes ) |
| { |
| PRINTER_INFO_2W* pWinInfo2 = (PRINTER_INFO_2W*)rtl_allocateMemory(nBytes); |
| if( GetPrinterW( hPrinter, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes ) ) |
| { |
| if( pWinInfo2->pDriverName ) |
| pInfo->maDriver = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pDriverName) ); |
| XubString aPortName; |
| if ( pWinInfo2->pPortName ) |
| aPortName = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pPortName) ); |
| // pLocation can be 0 (the Windows docu doesn't describe this) |
| if ( pWinInfo2->pLocation && *pWinInfo2->pLocation ) |
| pInfo->maLocation = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pLocation) ); |
| else |
| pInfo->maLocation = aPortName; |
| // pComment can be 0 (the Windows docu doesn't describe this) |
| if ( pWinInfo2->pComment ) |
| pInfo->maComment = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pComment) ); |
| pInfo->mnStatus = ImplWinQueueStatusToSal( pWinInfo2->Status ); |
| pInfo->mnJobs = pWinInfo2->cJobs; |
| if( ! pInfo->mpSysData ) |
| pInfo->mpSysData = new XubString( aPortName ); |
| } |
| rtl_freeMemory(pWinInfo2); |
| } |
| ClosePrinter( hPrinter ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) |
| { |
| delete (String*)(pInfo->mpSysData); |
| delete pInfo; |
| } |
| |
| // ----------------------------------------------------------------------- |
| XubString WinSalInstance::GetDefaultPrinter() |
| { |
| static bool bGetDefPrtAPI = true; |
| static sal_Bool(WINAPI*pGetDefaultPrinter)(LPWSTR,LPDWORD) = NULL; |
| // try to use GetDefaultPrinter API (not available prior to W2000) |
| if( bGetDefPrtAPI ) |
| { |
| bGetDefPrtAPI = false; |
| // check for W2k and XP |
| if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 ) |
| { |
| oslModule pLib = osl_loadAsciiModule( "winspool.drv", SAL_LOADMODULE_DEFAULT ); |
| oslGenericFunction pFunc = NULL; |
| if( pLib ) |
| pFunc = osl_getAsciiFunctionSymbol( pLib, "GetDefaultPrinterW" ); |
| |
| pGetDefaultPrinter = (sal_Bool(WINAPI*)(LPWSTR,LPDWORD)) pFunc; |
| } |
| } |
| if( pGetDefaultPrinter ) |
| { |
| DWORD nChars = 0; |
| pGetDefaultPrinter( NULL, &nChars ); |
| if( nChars ) |
| { |
| LPWSTR pStr = (LPWSTR)rtl_allocateMemory(nChars*sizeof(WCHAR)); |
| XubString aDefPrt; |
| if( pGetDefaultPrinter( pStr, &nChars ) ) |
| { |
| aDefPrt = reinterpret_cast<sal_Unicode* >(pStr); |
| } |
| rtl_freeMemory( pStr ); |
| if( aDefPrt.Len() ) |
| return aDefPrt; |
| } |
| } |
| |
| // get default printer from win.ini |
| 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( WinSalInfoPrinter* pPrinter, WORD nCaps, |
| BYTE* pOutput, const ImplJobSetup* pSetupData ) |
| { |
| if( aSalShlData.mbWPrinter ) |
| { |
| DEVMODEW* pDevMode; |
| if ( !pSetupData || !pSetupData->mpDriverData ) |
| pDevMode = NULL; |
| else |
| pDevMode = SAL_DEVMODE_W( pSetupData ); |
| |
| return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR>(pPrinter->maDeviceName.GetBuffer()), |
| reinterpret_cast<LPCWSTR>(pPrinter->maPortName.GetBuffer()), |
| nCaps, (LPWSTR)pOutput, pDevMode ); |
| } |
| else |
| { |
| DEVMODEA* pDevMode; |
| if ( !pSetupData || !pSetupData->mpDriverData ) |
| pDevMode = NULL; |
| else |
| pDevMode = SAL_DEVMODE_A( pSetupData ); |
| |
| return DeviceCapabilitiesA( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(), |
| ImplSalGetWinAnsiString( pPrinter->maPortName, TRUE ).GetBuffer(), |
| nCaps, (LPSTR)pOutput, pDevMode ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static sal_Bool ImplTestSalJobSetup( WinSalInfoPrinter* pPrinter, |
| ImplJobSetup* pSetupData, sal_Bool bDelete ) |
| { |
| if ( pSetupData && pSetupData->mpDriverData ) |
| { |
| // signature and size must fit to avoid using |
| // JobSetups from a wrong system |
| |
| // initialize versions from jobsetup |
| // those will be overwritten with driver's version |
| DEVMODEA* pDevModeA = NULL; |
| DEVMODEW* pDevModeW = NULL; |
| LONG dmSpecVersion = -1; |
| LONG dmDriverVersion = -1; |
| SalDriverData* pSalDriverData = (SalDriverData*)pSetupData->mpDriverData; |
| BYTE* pDriverData = ((BYTE*)pSalDriverData) + pSalDriverData->mnDriverOffset; |
| if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_W ) |
| { |
| if( aSalShlData.mbWPrinter ) |
| pDevModeW = (DEVMODEW*)pDriverData; |
| } |
| else if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_A ) |
| { |
| if( ! aSalShlData.mbWPrinter ) |
| pDevModeA = (DEVMODEA*)pDriverData; |
| } |
| |
| long nSysJobSize = -1; |
| if( pPrinter && ( pDevModeA || pDevModeW ) ) |
| { |
| // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!! |
| // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we |
| // can avoid potential driver crashes as their jobsetups are often not compatible |
| // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375# |
| ByteString aPrinterNameA= ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ); |
| HANDLE hPrn; |
| LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer())); |
| if ( ! aSalShlData.mbWPrinter ) |
| { |
| if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) ) |
| return FALSE; |
| } |
| else |
| if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) ) |
| return FALSE; |
| |
| // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded! |
| if( hPrn == HGDI_ERROR ) |
| return FALSE; |
| |
| if( aSalShlData.mbWPrinter ) |
| { |
| nSysJobSize = DocumentPropertiesW( 0, hPrn, |
| pPrinterNameW, |
| NULL, NULL, 0 ); |
| } |
| else |
| { |
| nSysJobSize = DocumentPropertiesA( 0, hPrn, |
| (LPSTR)aPrinterNameA.GetBuffer(), |
| NULL, NULL, 0 ); |
| } |
| |
| if( nSysJobSize < 0 ) |
| { |
| ClosePrinter( hPrn ); |
| return FALSE; |
| } |
| BYTE *pBuffer = (BYTE*)_alloca( nSysJobSize ); |
| LONG nRet = -1; |
| if( aSalShlData.mbWPrinter ) |
| { |
| nRet = DocumentPropertiesW( 0, hPrn, |
| pPrinterNameW, |
| (LPDEVMODEW)pBuffer, NULL, DM_OUT_BUFFER ); |
| } |
| else |
| { |
| nRet = DocumentPropertiesA( 0, hPrn, |
| (LPSTR)aPrinterNameA.GetBuffer(), |
| (LPDEVMODEA)pBuffer, NULL, DM_OUT_BUFFER ); |
| } |
| if( nRet < 0 ) |
| { |
| ClosePrinter( hPrn ); |
| return FALSE; |
| } |
| |
| // the spec version differs between the windows platforms, ie 98,NT,2000/XP |
| // this allows us to throw away printer settings from other platforms that might crash a buggy driver |
| // we check the driver version as well |
| dmSpecVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmSpecVersion : ((DEVMODEA*)pBuffer)->dmSpecVersion; |
| dmDriverVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmDriverVersion : ((DEVMODEA*)pBuffer)->dmDriverVersion; |
| |
| ClosePrinter( hPrn ); |
| } |
| SalDriverData* pSetupDriverData = (SalDriverData*)(pSetupData->mpDriverData); |
| if ( (pSetupData->mnSystem == JOBSETUP_SYSTEM_WINDOWS) && |
| (pPrinter->maDriverName == pSetupData->maDriver) && |
| (pSetupData->mnDriverDataLen > sizeof( SalDriverData )) && |
| (long)(pSetupData->mnDriverDataLen - pSetupDriverData->mnDriverOffset) == nSysJobSize && |
| pSetupDriverData->mnSysSignature == SAL_DRIVERDATA_SYSSIGN ) |
| { |
| if( pDevModeA && |
| (dmSpecVersion == pDevModeA->dmSpecVersion) && |
| (dmDriverVersion == pDevModeA->dmDriverVersion) ) |
| return TRUE; |
| if( pDevModeW && |
| (dmSpecVersion == pDevModeW->dmSpecVersion) && |
| (dmDriverVersion == pDevModeW->dmDriverVersion) ) |
| return TRUE; |
| } |
| if ( bDelete ) |
| { |
| rtl_freeMemory( pSetupData->mpDriverData ); |
| pSetupData->mpDriverData = NULL; |
| pSetupData->mnDriverDataLen = 0; |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static sal_Bool ImplUpdateSalJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, |
| sal_Bool bIn, WinSalFrame* pVisibleDlgParent ) |
| { |
| ByteString aPrinterNameA = ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ); |
| HANDLE hPrn; |
| LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer())); |
| if( aSalShlData.mbWPrinter ) |
| { |
| if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) ) |
| return FALSE; |
| } |
| else |
| { |
| if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) ) |
| return FALSE; |
| } |
| // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded! |
| if( hPrn == HGDI_ERROR ) |
| return FALSE; |
| |
| LONG nRet; |
| LONG nSysJobSize = -1; |
| HWND hWnd = 0; |
| DWORD nMode = DM_OUT_BUFFER; |
| sal_uLong nDriverDataLen = 0; |
| SalDriverData* pOutBuffer = NULL; |
| BYTE* pInBuffer = NULL; |
| |
| if( aSalShlData.mbWPrinter ) |
| { |
| nSysJobSize = DocumentPropertiesW( hWnd, hPrn, |
| pPrinterNameW, |
| NULL, NULL, 0 ); |
| } |
| else |
| nSysJobSize = DocumentPropertiesA( hWnd, hPrn, |
| (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(), |
| NULL, NULL, 0 ); |
| if ( nSysJobSize < 0 ) |
| { |
| ClosePrinter( hPrn ); |
| return FALSE; |
| } |
| |
| // Outputbuffer anlegen |
| nDriverDataLen = sizeof(SalDriverData) + nSysJobSize-1; |
| pOutBuffer = (SalDriverData*)rtl_allocateZeroMemory( nDriverDataLen ); |
| pOutBuffer->mnSysSignature = SAL_DRIVERDATA_SYSSIGN; |
| pOutBuffer->mnVersion = aSalShlData.mbWPrinter ? SAL_DRIVERDATA_VERSION_W : SAL_DRIVERDATA_VERSION_A; |
| // calculate driver data offset including structure padding |
| pOutBuffer->mnDriverOffset = sal::static_int_cast<sal_uInt16>( |
| (char*)pOutBuffer->maDriverData - |
| (char*)pOutBuffer ); |
| |
| // Testen, ob wir einen geeigneten Inputbuffer haben |
| if ( bIn && ImplTestSalJobSetup( pPrinter, pSetupData, FALSE ) ) |
| { |
| pInBuffer = (BYTE*)pSetupData->mpDriverData + ((SalDriverData*)pSetupData->mpDriverData)->mnDriverOffset; |
| nMode |= DM_IN_BUFFER; |
| } |
| |
| // Testen, ob Dialog angezeigt werden soll |
| if ( pVisibleDlgParent ) |
| { |
| hWnd = pVisibleDlgParent->mhWnd; |
| nMode |= DM_IN_PROMPT; |
| } |
| |
| // Release mutex, in the other case we don't get paints and so on |
| sal_uLong nMutexCount=0; |
| if ( pVisibleDlgParent ) |
| nMutexCount = ImplSalReleaseYieldMutex(); |
| |
| BYTE* pOutDevMode = (((BYTE*)pOutBuffer) + pOutBuffer->mnDriverOffset); |
| if( aSalShlData.mbWPrinter ) |
| { |
| nRet = DocumentPropertiesW( hWnd, hPrn, |
| pPrinterNameW, |
| (LPDEVMODEW)pOutDevMode, (LPDEVMODEW)pInBuffer, nMode ); |
| } |
| else |
| { |
| nRet = DocumentPropertiesA( hWnd, hPrn, |
| (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(), |
| (LPDEVMODEA)pOutDevMode, (LPDEVMODEA)pInBuffer, nMode ); |
| } |
| if ( pVisibleDlgParent ) |
| ImplSalAcquireYieldMutex( nMutexCount ); |
| ClosePrinter( hPrn ); |
| |
| if( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) ) |
| { |
| rtl_freeMemory( pOutBuffer ); |
| return FALSE; |
| } |
| |
| // fill up string buffers with 0 so they do not influence a JobSetup's memcmp |
| if( aSalShlData.mbWPrinter ) |
| { |
| if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 64 ) |
| { |
| sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmDeviceName ); |
| if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )/sizeof(sal_Unicode) ) |
| memset( ((LPDEVMODEW)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )-(nLen*sizeof(sal_Unicode)) ); |
| } |
| if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 166 ) |
| { |
| sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmFormName ); |
| if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )/sizeof(sal_Unicode) ) |
| memset( ((LPDEVMODEW)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )-(nLen*sizeof(sal_Unicode)) ); |
| } |
| } |
| else |
| { |
| if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 32 ) |
| { |
| sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmDeviceName ); |
| if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName ) ) |
| memset( ((LPDEVMODEA)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName )-nLen ); |
| } |
| if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 102 ) |
| { |
| sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmFormName ); |
| if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName ) ) |
| memset( ((LPDEVMODEA)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName )-nLen ); |
| } |
| } |
| |
| // update data |
| if ( pSetupData->mpDriverData ) |
| rtl_freeMemory( pSetupData->mpDriverData ); |
| pSetupData->mnDriverDataLen = nDriverDataLen; |
| pSetupData->mpDriverData = (BYTE*)pOutBuffer; |
| pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS; |
| |
| return TRUE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| #define DECLARE_DEVMODE( i )\ |
| DEVMODEA* pDevModeA = SAL_DEVMODE_A(i);\ |
| DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\ |
| if( pDevModeA == NULL && pDevModeW == NULL )\ |
| return |
| |
| #define CHOOSE_DEVMODE(i)\ |
| (pDevModeW ? pDevModeW->i : pDevModeA->i) |
| |
| static void ImplDevModeToJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, sal_uLong nFlags ) |
| { |
| if ( !pSetupData || !pSetupData->mpDriverData ) |
| return; |
| |
| DECLARE_DEVMODE( pSetupData ); |
| |
| // Orientation |
| if ( nFlags & SAL_JOBSET_ORIENTATION ) |
| { |
| if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_PORTRAIT ) |
| pSetupData->meOrientation = ORIENTATION_PORTRAIT; |
| else if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_LANDSCAPE ) |
| pSetupData->meOrientation = ORIENTATION_LANDSCAPE; |
| } |
| |
| // PaperBin |
| if ( nFlags & SAL_JOBSET_PAPERBIN ) |
| { |
| sal_uLong nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData ); |
| |
| if ( nCount && (nCount != GDI_ERROR) ) |
| { |
| WORD* pBins = (WORD*)rtl_allocateZeroMemory( nCount*sizeof(WORD) ); |
| ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData ); |
| pSetupData->mnPaperBin = 0; |
| |
| // search the right bin and assign index to mnPaperBin |
| for( sal_uLong i = 0; i < nCount; i++ ) |
| { |
| if( CHOOSE_DEVMODE(dmDefaultSource) == pBins[ i ] ) |
| { |
| pSetupData->mnPaperBin = (sal_uInt16)i; |
| break; |
| } |
| } |
| |
| rtl_freeMemory( pBins ); |
| } |
| } |
| |
| // PaperSize |
| if ( nFlags & SAL_JOBSET_PAPERSIZE ) |
| { |
| if( (CHOOSE_DEVMODE(dmFields) & (DM_PAPERWIDTH|DM_PAPERLENGTH)) == (DM_PAPERWIDTH|DM_PAPERLENGTH) ) |
| { |
| pSetupData->mnPaperWidth = CHOOSE_DEVMODE(dmPaperWidth)*10; |
| pSetupData->mnPaperHeight = CHOOSE_DEVMODE(dmPaperLength)*10; |
| } |
| else |
| { |
| sal_uLong nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData ); |
| WORD* pPapers = NULL; |
| sal_uLong nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData ); |
| POINT* pPaperSizes = NULL; |
| if ( nPaperCount && (nPaperCount != GDI_ERROR) ) |
| { |
| pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD)); |
| ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData ); |
| } |
| if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) ) |
| { |
| pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT)); |
| ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData ); |
| } |
| if( nPaperSizeCount == nPaperCount && pPaperSizes && pPapers ) |
| { |
| for( sal_uLong i = 0; i < nPaperCount; i++ ) |
| { |
| if( pPapers[ i ] == CHOOSE_DEVMODE(dmPaperSize) ) |
| { |
| pSetupData->mnPaperWidth = pPaperSizes[ i ].x*10; |
| pSetupData->mnPaperHeight = pPaperSizes[ i ].y*10; |
| break; |
| } |
| } |
| } |
| if( pPapers ) |
| rtl_freeMemory( pPapers ); |
| if( pPaperSizes ) |
| rtl_freeMemory( pPaperSizes ); |
| } |
| switch( CHOOSE_DEVMODE(dmPaperSize) ) |
| { |
| case( DMPAPER_LETTER ): |
| pSetupData->mePaperFormat = PAPER_LETTER; |
| break; |
| case( DMPAPER_TABLOID ): |
| pSetupData->mePaperFormat = PAPER_TABLOID; |
| break; |
| case( DMPAPER_LEDGER ): |
| pSetupData->mePaperFormat = PAPER_LEDGER; |
| break; |
| case( DMPAPER_LEGAL ): |
| pSetupData->mePaperFormat = PAPER_LEGAL; |
| break; |
| case( DMPAPER_STATEMENT ): |
| pSetupData->mePaperFormat = PAPER_STATEMENT; |
| break; |
| case( DMPAPER_EXECUTIVE ): |
| pSetupData->mePaperFormat = PAPER_EXECUTIVE; |
| break; |
| case( DMPAPER_A3 ): |
| pSetupData->mePaperFormat = PAPER_A3; |
| break; |
| case( DMPAPER_A4 ): |
| pSetupData->mePaperFormat = PAPER_A4; |
| break; |
| case( DMPAPER_A5 ): |
| pSetupData->mePaperFormat = PAPER_A5; |
| break; |
| //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize |
| //i.e. |
| //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx |
| //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm |
| //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf |
| //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And |
| //matches our Excel filter's belief about the matching XlPaperSize |
| //enumeration. |
| // |
| //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said |
| ////"DMPAPER_B4 12 B4 (JIS) 250 x 354" |
| //which is bogus as it's either JIS 257 × 364 or ISO 250 × 353 |
| //(cmc) |
| case( DMPAPER_B4 ): |
| pSetupData->mePaperFormat = PAPER_B4_JIS; |
| break; |
| case( DMPAPER_B5 ): |
| pSetupData->mePaperFormat = PAPER_B5_JIS; |
| break; |
| case( DMPAPER_QUARTO ): |
| pSetupData->mePaperFormat = PAPER_QUARTO; |
| break; |
| case( DMPAPER_10X14 ): |
| pSetupData->mePaperFormat = PAPER_10x14; |
| break; |
| case( DMPAPER_NOTE ): |
| pSetupData->mePaperFormat = PAPER_LETTER; |
| break; |
| case( DMPAPER_ENV_9 ): |
| pSetupData->mePaperFormat = PAPER_ENV_9; |
| break; |
| case( DMPAPER_ENV_10 ): |
| pSetupData->mePaperFormat = PAPER_ENV_10; |
| break; |
| case( DMPAPER_ENV_11 ): |
| pSetupData->mePaperFormat = PAPER_ENV_11; |
| break; |
| case( DMPAPER_ENV_12 ): |
| pSetupData->mePaperFormat = PAPER_ENV_12; |
| break; |
| case( DMPAPER_ENV_14 ): |
| pSetupData->mePaperFormat = PAPER_ENV_14; |
| break; |
| case( DMPAPER_CSHEET ): |
| pSetupData->mePaperFormat = PAPER_C; |
| break; |
| case( DMPAPER_DSHEET ): |
| pSetupData->mePaperFormat = PAPER_D; |
| break; |
| case( DMPAPER_ESHEET ): |
| pSetupData->mePaperFormat = PAPER_E; |
| break; |
| case( DMPAPER_ENV_DL): |
| pSetupData->mePaperFormat = PAPER_ENV_DL; |
| break; |
| case( DMPAPER_ENV_C5): |
| pSetupData->mePaperFormat = PAPER_ENV_C5; |
| break; |
| case( DMPAPER_ENV_C3): |
| pSetupData->mePaperFormat = PAPER_ENV_C3; |
| break; |
| case( DMPAPER_ENV_C4): |
| pSetupData->mePaperFormat = PAPER_ENV_C4; |
| break; |
| case( DMPAPER_ENV_C6): |
| pSetupData->mePaperFormat = PAPER_ENV_C6; |
| break; |
| case( DMPAPER_ENV_C65): |
| pSetupData->mePaperFormat = PAPER_ENV_C65; |
| break; |
| case( DMPAPER_ENV_ITALY ): |
| pSetupData->mePaperFormat = PAPER_ENV_ITALY; |
| break; |
| case( DMPAPER_ENV_MONARCH ): |
| pSetupData->mePaperFormat = PAPER_ENV_MONARCH; |
| break; |
| case( DMPAPER_ENV_PERSONAL ): |
| pSetupData->mePaperFormat = PAPER_ENV_PERSONAL; |
| break; |
| case( DMPAPER_FANFOLD_US ): |
| pSetupData->mePaperFormat = PAPER_FANFOLD_US; |
| break; |
| case( DMPAPER_FANFOLD_STD_GERMAN ): |
| pSetupData->mePaperFormat = PAPER_FANFOLD_DE; |
| break; |
| case( DMPAPER_FANFOLD_LGL_GERMAN ): |
| pSetupData->mePaperFormat = PAPER_FANFOLD_LEGAL_DE; |
| break; |
| case( DMPAPER_ISO_B4 ): |
| pSetupData->mePaperFormat = PAPER_B4_ISO; |
| break; |
| case( DMPAPER_JAPANESE_POSTCARD ): |
| pSetupData->mePaperFormat = PAPER_POSTCARD_JP; |
| break; |
| case( DMPAPER_9X11 ): |
| pSetupData->mePaperFormat = PAPER_9x11; |
| break; |
| case( DMPAPER_10X11 ): |
| pSetupData->mePaperFormat = PAPER_10x11; |
| break; |
| case( DMPAPER_15X11 ): |
| pSetupData->mePaperFormat = PAPER_15x11; |
| break; |
| case( DMPAPER_ENV_INVITE ): |
| pSetupData->mePaperFormat = PAPER_ENV_INVITE; |
| break; |
| case( DMPAPER_A_PLUS ): |
| pSetupData->mePaperFormat = PAPER_A_PLUS; |
| break; |
| case( DMPAPER_B_PLUS ): |
| pSetupData->mePaperFormat = PAPER_B_PLUS; |
| break; |
| case( DMPAPER_LETTER_PLUS ): |
| pSetupData->mePaperFormat = PAPER_LETTER_PLUS; |
| break; |
| case( DMPAPER_A4_PLUS ): |
| pSetupData->mePaperFormat = PAPER_A4_PLUS; |
| break; |
| case( DMPAPER_A2 ): |
| pSetupData->mePaperFormat = PAPER_A2; |
| break; |
| case( DMPAPER_DBL_JAPANESE_POSTCARD ): |
| pSetupData->mePaperFormat = PAPER_DOUBLEPOSTCARD_JP; |
| break; |
| case( DMPAPER_A6 ): |
| pSetupData->mePaperFormat = PAPER_A6; |
| break; |
| case( DMPAPER_B6_JIS ): |
| pSetupData->mePaperFormat = PAPER_B6_JIS; |
| break; |
| case( DMPAPER_12X11 ): |
| pSetupData->mePaperFormat = PAPER_12x11; |
| break; |
| default: |
| pSetupData->mePaperFormat = PAPER_USER; |
| break; |
| } |
| } |
| |
| if( nFlags & SAL_JOBSET_DUPLEXMODE ) |
| { |
| DuplexMode eDuplex = DUPLEX_UNKNOWN; |
| if( (CHOOSE_DEVMODE(dmFields) & DM_DUPLEX) ) |
| { |
| if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_SIMPLEX ) |
| eDuplex = DUPLEX_OFF; |
| else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_VERTICAL ) |
| eDuplex = DUPLEX_LONGEDGE; |
| else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_HORIZONTAL ) |
| eDuplex = DUPLEX_SHORTEDGE; |
| } |
| pSetupData->meDuplexMode = eDuplex; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static void ImplJobSetupToDevMode( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, sal_uLong nFlags ) |
| { |
| if ( !pSetupData || !pSetupData->mpDriverData ) |
| return; |
| |
| DECLARE_DEVMODE( pSetupData ); |
| |
| // Orientation |
| if ( nFlags & SAL_JOBSET_ORIENTATION ) |
| { |
| CHOOSE_DEVMODE(dmFields) |= DM_ORIENTATION; |
| if ( pSetupData->meOrientation == ORIENTATION_PORTRAIT ) |
| CHOOSE_DEVMODE(dmOrientation) = DMORIENT_PORTRAIT; |
| else |
| CHOOSE_DEVMODE(dmOrientation) = DMORIENT_LANDSCAPE; |
| } |
| |
| // PaperBin |
| if ( nFlags & SAL_JOBSET_PAPERBIN ) |
| { |
| sal_uLong nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData ); |
| |
| if ( nCount && (nCount != GDI_ERROR) ) |
| { |
| WORD* pBins = (WORD*)rtl_allocateZeroMemory(nCount*sizeof(WORD)); |
| ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData ); |
| CHOOSE_DEVMODE(dmFields) |= DM_DEFAULTSOURCE; |
| CHOOSE_DEVMODE(dmDefaultSource) = pBins[ pSetupData->mnPaperBin ]; |
| rtl_freeMemory( pBins ); |
| } |
| } |
| |
| // PaperSize |
| if ( nFlags & SAL_JOBSET_PAPERSIZE ) |
| { |
| CHOOSE_DEVMODE(dmFields) |= DM_PAPERSIZE; |
| CHOOSE_DEVMODE(dmPaperWidth) = 0; |
| CHOOSE_DEVMODE(dmPaperLength) = 0; |
| |
| switch( pSetupData->mePaperFormat ) |
| { |
| case( PAPER_A2 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A2; |
| break; |
| case( PAPER_A3 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A3; |
| break; |
| case( PAPER_A4 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4; |
| break; |
| case( PAPER_A5 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A5; |
| break; |
| case( PAPER_B4_ISO): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ISO_B4; |
| break; |
| case( PAPER_LETTER ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER; |
| break; |
| case( PAPER_LEGAL ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEGAL; |
| break; |
| case( PAPER_TABLOID ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_TABLOID; |
| break; |
| #if 0 |
| //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx |
| //DMPAPER_ENV_B6 is documented as: |
| //"DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm" |
| //which is the wrong way around, it is surely 125 x 176, i.e. |
| //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as |
| //DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm |
| //DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm |
| case( PAPER_B6_ISO ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_B6; |
| break; |
| #endif |
| case( PAPER_ENV_C4 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C4; |
| break; |
| case( PAPER_ENV_C5 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C5; |
| break; |
| case( PAPER_ENV_C6 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C6; |
| break; |
| case( PAPER_ENV_C65 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C65; |
| break; |
| case( PAPER_ENV_DL ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_DL; |
| break; |
| case( PAPER_C ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_CSHEET; |
| break; |
| case( PAPER_D ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DSHEET; |
| break; |
| case( PAPER_E ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ESHEET; |
| break; |
| case( PAPER_EXECUTIVE ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_EXECUTIVE; |
| break; |
| case( PAPER_FANFOLD_LEGAL_DE ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_LGL_GERMAN; |
| break; |
| case( PAPER_ENV_MONARCH ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_MONARCH; |
| break; |
| case( PAPER_ENV_PERSONAL ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_PERSONAL; |
| break; |
| case( PAPER_ENV_9 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_9; |
| break; |
| case( PAPER_ENV_10 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_10; |
| break; |
| case( PAPER_ENV_11 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_11; |
| break; |
| case( PAPER_ENV_12 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_12; |
| break; |
| //See the comments on DMPAPER_B4 above |
| case( PAPER_B4_JIS ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B4; |
| break; |
| case( PAPER_B5_JIS ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B5; |
| break; |
| case( PAPER_B6_JIS ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B6_JIS; |
| break; |
| case( PAPER_LEDGER ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEDGER; |
| break; |
| case( PAPER_STATEMENT ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_STATEMENT; |
| break; |
| case( PAPER_10x14 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X14; |
| break; |
| case( PAPER_ENV_14 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_14; |
| break; |
| case( PAPER_ENV_C3 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C3; |
| break; |
| case( PAPER_ENV_ITALY ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_ITALY; |
| break; |
| case( PAPER_FANFOLD_US ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_US; |
| break; |
| case( PAPER_FANFOLD_DE ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_STD_GERMAN; |
| break; |
| case( PAPER_POSTCARD_JP ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_JAPANESE_POSTCARD; |
| break; |
| case( PAPER_9x11 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_9X11; |
| break; |
| case( PAPER_10x11 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X11; |
| break; |
| case( PAPER_15x11 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_15X11; |
| break; |
| case( PAPER_ENV_INVITE ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_INVITE; |
| break; |
| case( PAPER_A_PLUS ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A_PLUS; |
| break; |
| case( PAPER_B_PLUS ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B_PLUS; |
| break; |
| case( PAPER_LETTER_PLUS ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER_PLUS; |
| break; |
| case( PAPER_A4_PLUS ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4_PLUS; |
| break; |
| case( PAPER_DOUBLEPOSTCARD_JP ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DBL_JAPANESE_POSTCARD; |
| break; |
| case( PAPER_A6 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A6; |
| break; |
| case( PAPER_12x11 ): |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_12X11; |
| break; |
| default: |
| { |
| short nPaper = 0; |
| sal_uLong nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData ); |
| WORD* pPapers = NULL; |
| sal_uLong nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData ); |
| POINT* pPaperSizes = NULL; |
| DWORD nLandscapeAngle = ImplDeviceCaps( pPrinter, DC_ORIENTATION, NULL, pSetupData ); |
| if ( nPaperCount && (nPaperCount != GDI_ERROR) ) |
| { |
| pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD)); |
| ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData ); |
| } |
| if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) ) |
| { |
| pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT)); |
| ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData ); |
| } |
| if ( (nPaperSizeCount == nPaperCount) && pPapers && pPaperSizes ) |
| { |
| PaperInfo aInfo(pSetupData->mnPaperWidth, pSetupData->mnPaperHeight); |
| // compare paper formats and select a good match |
| for ( sal_uLong i = 0; i < nPaperCount; i++ ) |
| { |
| if ( aInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10))) |
| { |
| nPaper = pPapers[i]; |
| break; |
| } |
| } |
| |
| // If the printer supports landscape orientation, check paper sizes again |
| // with landscape orientation. This is necessary as a printer driver provides |
| // all paper sizes with portrait orientation only!! |
| if ( !nPaper && nLandscapeAngle != 0 ) |
| { |
| PaperInfo aRotatedInfo(pSetupData->mnPaperHeight, pSetupData->mnPaperWidth); |
| for ( sal_uLong i = 0; i < nPaperCount; i++ ) |
| { |
| if ( aRotatedInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)) ) |
| { |
| nPaper = pPapers[i]; |
| break; |
| } |
| } |
| } |
| |
| if ( nPaper ) |
| CHOOSE_DEVMODE(dmPaperSize) = nPaper; |
| } |
| |
| if ( !nPaper ) |
| { |
| CHOOSE_DEVMODE(dmFields) |= DM_PAPERLENGTH | DM_PAPERWIDTH; |
| CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_USER; |
| CHOOSE_DEVMODE(dmPaperWidth) = (short)(pSetupData->mnPaperWidth/10); |
| CHOOSE_DEVMODE(dmPaperLength) = (short)(pSetupData->mnPaperHeight/10); |
| } |
| |
| if ( pPapers ) |
| rtl_freeMemory(pPapers); |
| if ( pPaperSizes ) |
| rtl_freeMemory(pPaperSizes); |
| |
| break; |
| } |
| } |
| } |
| if( (nFlags & SAL_JOBSET_DUPLEXMODE) ) |
| { |
| switch( pSetupData->meDuplexMode ) |
| { |
| case DUPLEX_OFF: |
| CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX; |
| CHOOSE_DEVMODE(dmDuplex) = DMDUP_SIMPLEX; |
| break; |
| case DUPLEX_SHORTEDGE: |
| CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX; |
| CHOOSE_DEVMODE(dmDuplex) = DMDUP_HORIZONTAL; |
| break; |
| case DUPLEX_LONGEDGE: |
| CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX; |
| CHOOSE_DEVMODE(dmDuplex) = DMDUP_VERTICAL; |
| break; |
| case DUPLEX_UNKNOWN: |
| break; |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static HDC ImplCreateICW_WithCatch( LPWSTR pDriver, |
| LPCWSTR pDevice, |
| LPDEVMODEW pDevMode ) |
| { |
| HDC hDC = 0; |
| CATCH_DRIVER_EX_BEGIN; |
| hDC = CreateICW( pDriver, pDevice, 0, pDevMode ); |
| CATCH_DRIVER_EX_END_2( "exception in CreateICW" ); |
| return hDC; |
| } |
| |
| static HDC ImplCreateICA_WithCatch( char* pDriver, |
| char* pDevice, |
| LPDEVMODEA pDevMode ) |
| { |
| HDC hDC = 0; |
| CATCH_DRIVER_EX_BEGIN; |
| hDC = CreateICA( pDriver, pDevice, 0, pDevMode ); |
| CATCH_DRIVER_EX_END_2( "exception in CreateICW" ); |
| return hDC; |
| } |
| |
| |
| static HDC ImplCreateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData ) |
| { |
| HDC hDC = 0; |
| if( aSalShlData.mbWPrinter ) |
| { |
| LPDEVMODEW pDevMode; |
| if ( pSetupData && pSetupData->mpDriverData ) |
| pDevMode = SAL_DEVMODE_W( pSetupData ); |
| else |
| pDevMode = NULL; |
| // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space |
| // pl: does this hold true for Unicode functions ? |
| if( pPrinter->maDriverName.Len() > 2048 || pPrinter->maDeviceName.Len() > 2048 ) |
| return 0; |
| sal_Unicode pDriverName[ 4096 ]; |
| sal_Unicode pDeviceName[ 4096 ]; |
| rtl_copyMemory( pDriverName, pPrinter->maDriverName.GetBuffer(), pPrinter->maDriverName.Len()*sizeof(sal_Unicode)); |
| memset( pDriverName+pPrinter->maDriverName.Len(), 0, 32 ); |
| rtl_copyMemory( pDeviceName, pPrinter->maDeviceName.GetBuffer(), pPrinter->maDeviceName.Len()*sizeof(sal_Unicode)); |
| memset( pDeviceName+pPrinter->maDeviceName.Len(), 0, 32 ); |
| hDC = ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR >(pDriverName), |
| reinterpret_cast< LPCWSTR >(pDeviceName), |
| pDevMode ); |
| } |
| else |
| { |
| LPDEVMODEA pDevMode; |
| if ( pSetupData && pSetupData->mpDriverData ) |
| pDevMode = SAL_DEVMODE_A( pSetupData ); |
| else |
| pDevMode = NULL; |
| // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space |
| ByteString aDriver ( ImplSalGetWinAnsiString( pPrinter->maDriverName, TRUE ) ); |
| ByteString aDevice ( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ) ); |
| int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len(); |
| // #125813# under some circumstances many printer drivers really |
| // seem to have a problem with the names and their conversions. |
| // We need to get on to of this, but haven't been able to reproduce |
| // the problem yet. Put the names on the stack so we get them |
| // with an eventual crash report. |
| if( n >= 2048 ) |
| return 0; |
| n += 2048; |
| char lpszDriverName[ 4096 ]; |
| char lpszDeviceName[ 4096 ]; |
| strncpy( lpszDriverName, aDriver.GetBuffer(), n ); |
| strncpy( lpszDeviceName, aDevice.GetBuffer(), n ); |
| // HDU: the crashes usually happen in a MBCS to unicode conversion, |
| // so I suspect the MBCS string's end is not properly recognized. |
| // The longest MBCS encoding I'm aware of has six bytes per code |
| // => add a couple of zeroes... |
| memset( lpszDriverName+aDriver.Len(), 0, 16 ); |
| memset( lpszDeviceName+aDevice.Len(), 0, 16 ); |
| hDC = ImplCreateICA_WithCatch( lpszDriverName, |
| lpszDeviceName, |
| pDevMode ); |
| } |
| return hDC; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static WinSalGraphics* ImplCreateSalPrnGraphics( HDC hDC ) |
| { |
| WinSalGraphics* pGraphics = new WinSalGraphics; |
| pGraphics->SetLayout( 0 ); |
| pGraphics->setHDC(hDC); |
| pGraphics->mhWnd = 0; |
| pGraphics->mbPrinter = TRUE; |
| pGraphics->mbVirDev = FALSE; |
| pGraphics->mbWindow = FALSE; |
| pGraphics->mbScreen = FALSE; |
| ImplSalInitGraphics( pGraphics ); |
| return pGraphics; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static sal_Bool ImplUpdateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData ) |
| { |
| HDC hNewDC = ImplCreateSalPrnIC( pPrinter, pSetupData ); |
| if ( !hNewDC ) |
| return FALSE; |
| |
| if ( pPrinter->mpGraphics ) |
| { |
| ImplSalDeInitGraphics( pPrinter->mpGraphics ); |
| DeleteDC( pPrinter->mpGraphics->getHDC() ); |
| delete pPrinter->mpGraphics; |
| } |
| |
| pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hNewDC ); |
| pPrinter->mhDC = hNewDC; |
| |
| return TRUE; |
| } |
| |
| // ======================================================================= |
| |
| SalInfoPrinter* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, |
| ImplJobSetup* pSetupData ) |
| { |
| WinSalInfoPrinter* pPrinter = new WinSalInfoPrinter; |
| if( ! pQueueInfo->mpSysData ) |
| GetPrinterQueueState( pQueueInfo ); |
| pPrinter->maDriverName = pQueueInfo->maDriver; |
| pPrinter->maDeviceName = pQueueInfo->maPrinterName; |
| pPrinter->maPortName = pQueueInfo->mpSysData ? |
| *(String*)(pQueueInfo->mpSysData) |
| : String(); |
| |
| // check if the provided setup data match the actual printer |
| ImplTestSalJobSetup( pPrinter, pSetupData, TRUE ); |
| |
| HDC hDC = ImplCreateSalPrnIC( pPrinter, pSetupData ); |
| if ( !hDC ) |
| { |
| delete pPrinter; |
| return NULL; |
| } |
| |
| pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hDC ); |
| pPrinter->mhDC = hDC; |
| if ( !pSetupData->mpDriverData ) |
| ImplUpdateSalJobSetup( pPrinter, pSetupData, FALSE, NULL ); |
| ImplDevModeToJobSetup( pPrinter, pSetupData, SAL_JOBSET_ALL ); |
| pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS; |
| |
| return pPrinter; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) |
| { |
| delete pPrinter; |
| } |
| |
| // ======================================================================= |
| |
| WinSalInfoPrinter::WinSalInfoPrinter() : |
| mpGraphics( NULL ), |
| mhDC( 0 ), |
| mbGraphics( FALSE ) |
| { |
| m_bPapersInit = FALSE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| WinSalInfoPrinter::~WinSalInfoPrinter() |
| { |
| if ( mpGraphics ) |
| { |
| ImplSalDeInitGraphics( mpGraphics ); |
| DeleteDC( mpGraphics->getHDC() ); |
| delete mpGraphics; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData ) |
| { |
| m_aPaperFormats.clear(); |
| |
| DWORD nCount = ImplDeviceCaps( this, DC_PAPERSIZE, NULL, pSetupData ); |
| if( nCount == GDI_ERROR ) |
| nCount = 0; |
| |
| POINT* pPaperSizes = NULL; |
| if( nCount ) |
| { |
| pPaperSizes = (POINT*)rtl_allocateZeroMemory(nCount*sizeof(POINT)); |
| ImplDeviceCaps( this, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData ); |
| |
| if( aSalShlData.mbWPrinter ) |
| { |
| sal_Unicode* pNamesBuffer = (sal_Unicode*)rtl_allocateMemory(nCount*64*sizeof(sal_Unicode)); |
| ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData ); |
| for( DWORD i = 0; i < nCount; ++i ) |
| { |
| PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10); |
| m_aPaperFormats.push_back( aInfo ); |
| } |
| rtl_freeMemory( pNamesBuffer ); |
| } |
| else |
| { |
| char* pNamesBuffer = (char*)rtl_allocateMemory(nCount*64); |
| ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData ); |
| for( DWORD i = 0; i < nCount; ++i ) |
| { |
| PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10); |
| m_aPaperFormats.push_back( aInfo ); |
| } |
| rtl_freeMemory( pNamesBuffer ); |
| } |
| rtl_freeMemory( pPaperSizes ); |
| } |
| |
| m_bPapersInit = true; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| int WinSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData ) |
| { |
| int nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData ); |
| |
| if( nRet != GDI_ERROR ) |
| return nRet * 10; |
| else |
| return 900; // guess |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| SalGraphics* WinSalInfoPrinter::GetGraphics() |
| { |
| if ( mbGraphics ) |
| return NULL; |
| |
| if ( mpGraphics ) |
| mbGraphics = TRUE; |
| |
| return mpGraphics; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalInfoPrinter::ReleaseGraphics( SalGraphics* ) |
| { |
| mbGraphics = FALSE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData ) |
| { |
| if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, static_cast<WinSalFrame*>(pFrame) ) ) |
| { |
| ImplDevModeToJobSetup( this, pSetupData, SAL_JOBSET_ALL ); |
| return ImplUpdateSalPrnIC( this, pSetupData ); |
| } |
| |
| return FALSE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData ) |
| { |
| if ( !ImplTestSalJobSetup( this, pSetupData, FALSE ) ) |
| return FALSE; |
| return ImplUpdateSalPrnIC( this, pSetupData ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalInfoPrinter::SetData( sal_uLong nFlags, ImplJobSetup* pSetupData ) |
| { |
| ImplJobSetupToDevMode( this, pSetupData, nFlags ); |
| if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, NULL ) ) |
| { |
| ImplDevModeToJobSetup( this, pSetupData, nFlags ); |
| return ImplUpdateSalPrnIC( this, pSetupData ); |
| } |
| |
| return FALSE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uLong WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pSetupData ) |
| { |
| DWORD nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| return nRet; |
| else |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString WinSalInfoPrinter::GetPaperBinName( const ImplJobSetup* pSetupData, sal_uLong nPaperBin ) |
| { |
| XubString aPaperBinName; |
| |
| DWORD nBins = ImplDeviceCaps( this, DC_BINNAMES, NULL, pSetupData ); |
| if ( (nPaperBin < nBins) && (nBins != GDI_ERROR) ) |
| { |
| if( aSalShlData.mbWPrinter ) |
| { |
| sal_Unicode* pBuffer = new sal_Unicode[nBins*24]; |
| DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| aPaperBinName = pBuffer + (nPaperBin*24); |
| delete [] pBuffer; |
| } |
| else |
| { |
| char* pBuffer = new char[nBins*24]; |
| DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| aPaperBinName = ImplSalGetUniString( (const char*)(pBuffer + (nPaperBin*24)) ); |
| delete [] pBuffer; |
| } |
| } |
| |
| return aPaperBinName; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uLong WinSalInfoPrinter::GetCapabilities( const ImplJobSetup* pSetupData, sal_uInt16 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 != GDI_ERROR) ) |
| return nRet; |
| return 0; |
| case PRINTER_CAPABILITIES_COLLATECOPIES: |
| if ( aSalShlData.mbW40 ) |
| { |
| nRet = ImplDeviceCaps( this, DC_COLLATE, NULL, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| { |
| nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| return nRet; |
| } |
| } |
| return 0; |
| |
| case PRINTER_CAPABILITIES_SETORIENTATION: |
| nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| return TRUE; |
| return FALSE; |
| |
| case PRINTER_CAPABILITIES_SETPAPERBIN: |
| nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| return TRUE; |
| return FALSE; |
| |
| case PRINTER_CAPABILITIES_SETPAPERSIZE: |
| case PRINTER_CAPABILITIES_SETPAPER: |
| nRet = ImplDeviceCaps( this, DC_PAPERS, NULL, pSetupData ); |
| if ( nRet && (nRet != GDI_ERROR) ) |
| return TRUE; |
| return FALSE; |
| } |
| |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup*, |
| long& rOutWidth, long& rOutHeight, |
| long& rPageOffX, long& rPageOffY, |
| long& rPageWidth, long& rPageHeight ) |
| { |
| HDC hDC = 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* WinSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter ) |
| { |
| WinSalPrinter* pPrinter = new WinSalPrinter; |
| pPrinter->mpInfoPrinter = static_cast<WinSalInfoPrinter*>(pInfoPrinter); |
| return pPrinter; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalInstance::DestroyPrinter( SalPrinter* pPrinter ) |
| { |
| delete pPrinter; |
| } |
| |
| // ======================================================================= |
| |
| BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ ) |
| { |
| SalData* pSalData = GetSalData(); |
| WinSalPrinter* pPrinter; |
| sal_Bool bWhile = TRUE; |
| int i = 0; |
| |
| do |
| { |
| // Messages verarbeiten |
| MSG aMsg; |
| if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) ) |
| { |
| if ( !ImplInterceptChildWindowKeyDown( aMsg ) ) |
| { |
| TranslateMessage( &aMsg ); |
| ImplDispatchMessage( &aMsg ); |
| } |
| i++; |
| if ( i > 15 ) |
| bWhile = FALSE; |
| } |
| else |
| bWhile = FALSE; |
| |
| pPrinter = pSalData->mpFirstPrinter; |
| while ( pPrinter ) |
| { |
| if( pPrinter->mhDC == hPrnDC ) |
| break; |
| |
| pPrinter = pPrinter->mpNextPrinter; |
| } |
| |
| if ( !pPrinter || pPrinter->mbAbort ) |
| return FALSE; |
| } |
| while ( bWhile ); |
| |
| return TRUE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static LPDEVMODEA ImplSalSetCopies( LPDEVMODEA pDevMode, sal_uLong nCopies, sal_Bool bCollate ) |
| { |
| LPDEVMODEA pNewDevMode = pDevMode; |
| if ( pDevMode && (nCopies > 1) ) |
| { |
| if ( nCopies > 32765 ) |
| nCopies = 32765; |
| sal_uLong nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra; |
| pNewDevMode = (LPDEVMODEA)rtl_allocateMemory( nDevSize ); |
| memcpy( pNewDevMode, pDevMode, nDevSize ); |
| pDevMode = pNewDevMode; |
| pDevMode->dmFields |= DM_COPIES; |
| pDevMode->dmCopies = (short)(sal_uInt16)nCopies; |
| if ( aSalShlData.mbW40 ) |
| { |
| pDevMode->dmFields |= DM_COLLATE; |
| if ( bCollate ) |
| pDevMode->dmCollate = DMCOLLATE_TRUE; |
| else |
| pDevMode->dmCollate = DMCOLLATE_FALSE; |
| } |
| } |
| |
| return pNewDevMode; |
| } |
| |
| static LPDEVMODEW ImplSalSetCopies( LPDEVMODEW pDevMode, sal_uLong nCopies, sal_Bool bCollate ) |
| { |
| LPDEVMODEW pNewDevMode = pDevMode; |
| if ( pDevMode && (nCopies > 1) ) |
| { |
| if ( nCopies > 32765 ) |
| nCopies = 32765; |
| sal_uLong nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra; |
| pNewDevMode = (LPDEVMODEW)rtl_allocateMemory( nDevSize ); |
| memcpy( pNewDevMode, pDevMode, nDevSize ); |
| pDevMode = pNewDevMode; |
| pDevMode->dmFields |= DM_COPIES; |
| pDevMode->dmCopies = (short)(sal_uInt16)nCopies; |
| if ( aSalShlData.mbW40 ) |
| { |
| pDevMode->dmFields |= DM_COLLATE; |
| if ( bCollate ) |
| pDevMode->dmCollate = DMCOLLATE_TRUE; |
| else |
| pDevMode->dmCollate = DMCOLLATE_FALSE; |
| } |
| } |
| |
| return pNewDevMode; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| WinSalPrinter::WinSalPrinter() : |
| mpGraphics( NULL ), |
| mpInfoPrinter( NULL ), |
| mpNextPrinter( NULL ), |
| mhDC( 0 ), |
| mnError( 0 ), |
| mnCopies( 0 ), |
| mbCollate( FALSE ), |
| mbAbort( FALSE ), |
| mbValid( true ) |
| { |
| SalData* pSalData = GetSalData(); |
| // insert printer in printerlist |
| mpNextPrinter = pSalData->mpFirstPrinter; |
| pSalData->mpFirstPrinter = this; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| WinSalPrinter::~WinSalPrinter() |
| { |
| SalData* pSalData = GetSalData(); |
| |
| // release DC if there is one still around because of AbortJob |
| HDC hDC = mhDC; |
| if ( hDC ) |
| { |
| if ( mpGraphics ) |
| { |
| ImplSalDeInitGraphics( mpGraphics ); |
| delete mpGraphics; |
| } |
| |
| DeleteDC( hDC ); |
| } |
| |
| // remove printer from printerlist |
| if ( this == pSalData->mpFirstPrinter ) |
| pSalData->mpFirstPrinter = mpNextPrinter; |
| else |
| { |
| WinSalPrinter* pTempPrinter = pSalData->mpFirstPrinter; |
| |
| while( pTempPrinter->mpNextPrinter != this ) |
| pTempPrinter = pTempPrinter->mpNextPrinter; |
| |
| pTempPrinter->mpNextPrinter = mpNextPrinter; |
| } |
| mbValid = false; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalPrinter::markInvalid() |
| { |
| mbValid = false; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| // need wrappers for StarTocW/A to use structured exception handling |
| // since SEH does not mix with standard exception handling's cleanup |
| static int lcl_StartDocW( HDC hDC, DOCINFOW* pInfo, WinSalPrinter* pPrt ) |
| { |
| int nRet = 0; |
| CATCH_DRIVER_EX_BEGIN; |
| nRet = ::StartDocW( hDC, pInfo ); |
| CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt ); |
| return nRet; |
| } |
| |
| static int lcl_StartDocA( HDC hDC, DOCINFOA* pInfo, WinSalPrinter* pPrt ) |
| { |
| int nRet = 0; |
| CATCH_DRIVER_EX_BEGIN; |
| nRet = ::StartDocA( hDC, pInfo ); |
| CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt ); |
| return nRet; |
| } |
| |
| sal_Bool WinSalPrinter::StartJob( const XubString* pFileName, |
| const XubString& rJobName, |
| const XubString&, |
| sal_uLong nCopies, |
| bool bCollate, |
| bool /*bDirect*/, |
| ImplJobSetup* pSetupData ) |
| { |
| mnError = 0; |
| mbAbort = FALSE; |
| mnCopies = nCopies; |
| mbCollate = bCollate; |
| |
| LPDEVMODEA pOrgDevModeA = NULL; |
| LPDEVMODEA pDevModeA = NULL; |
| LPDEVMODEW pOrgDevModeW = NULL; |
| LPDEVMODEW pDevModeW = NULL; |
| HDC hDC = 0; |
| if( aSalShlData.mbWPrinter ) |
| { |
| if ( pSetupData && pSetupData->mpDriverData ) |
| { |
| pOrgDevModeW = SAL_DEVMODE_W( pSetupData ); |
| pDevModeW = ImplSalSetCopies( pOrgDevModeW, nCopies, bCollate ); |
| } |
| else |
| pDevModeW = NULL; |
| |
| // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space |
| sal_Unicode aDrvBuf[4096]; |
| sal_Unicode aDevBuf[4096]; |
| rtl_copyMemory( aDrvBuf, mpInfoPrinter->maDriverName.GetBuffer(), (mpInfoPrinter->maDriverName.Len()+1)*sizeof(sal_Unicode)); |
| rtl_copyMemory( aDevBuf, mpInfoPrinter->maDeviceName.GetBuffer(), (mpInfoPrinter->maDeviceName.Len()+1)*sizeof(sal_Unicode)); |
| hDC = CreateDCW( reinterpret_cast<LPCWSTR>(aDrvBuf), |
| reinterpret_cast<LPCWSTR>(aDevBuf), |
| NULL, |
| pDevModeW ); |
| |
| if ( pDevModeW != pOrgDevModeW ) |
| rtl_freeMemory( pDevModeW ); |
| } |
| else |
| { |
| if ( pSetupData && pSetupData->mpDriverData ) |
| { |
| pOrgDevModeA = SAL_DEVMODE_A( pSetupData ); |
| pDevModeA = ImplSalSetCopies( pOrgDevModeA, nCopies, bCollate ); |
| } |
| else |
| pDevModeA = NULL; |
| |
| // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space |
| ByteString aDriver ( ImplSalGetWinAnsiString( mpInfoPrinter->maDriverName, TRUE ) ); |
| ByteString aDevice ( ImplSalGetWinAnsiString( mpInfoPrinter->maDeviceName, TRUE ) ); |
| int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len(); |
| n += 2048; |
| char *lpszDriverName = new char[n]; |
| char *lpszDeviceName = new char[n]; |
| strncpy( lpszDriverName, aDriver.GetBuffer(), n ); |
| strncpy( lpszDeviceName, aDevice.GetBuffer(), n ); |
| hDC = CreateDCA( lpszDriverName, |
| lpszDeviceName, |
| NULL, |
| pDevModeA ); |
| |
| delete [] lpszDriverName; |
| delete [] lpszDeviceName; |
| |
| if ( pDevModeA != pOrgDevModeA ) |
| rtl_freeMemory( pDevModeA ); |
| } |
| |
| if ( !hDC ) |
| { |
| mnError = SAL_PRINTER_ERROR_GENERALERROR; |
| return FALSE; |
| } |
| |
| // make sure mhDC is set before the printer driver may call our abortproc |
| mhDC = hDC; |
| if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 ) |
| { |
| mnError = SAL_PRINTER_ERROR_GENERALERROR; |
| return FALSE; |
| } |
| |
| mnError = 0; |
| mbAbort = FALSE; |
| |
| // Wegen Telocom Balloon Fax-Treiber, der uns unsere Messages |
| // ansonsten oefters schickt, versuchen wir vorher alle |
| // zu verarbeiten und dann eine Dummy-Message reinstellen |
| sal_Bool bWhile = TRUE; |
| int i = 0; |
| do |
| { |
| // Messages verarbeiten |
| MSG aMsg; |
| if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) ) |
| { |
| if ( !ImplInterceptChildWindowKeyDown( aMsg ) ) |
| { |
| TranslateMessage( &aMsg ); |
| ImplDispatchMessage( &aMsg ); |
| } |
| |
| i++; |
| if ( i > 15 ) |
| bWhile = FALSE; |
| } |
| else |
| bWhile = FALSE; |
| } |
| while ( bWhile ); |
| ImplPostMessage( GetSalData()->mpFirstInstance->mhComWnd, SAL_MSG_DUMMY, 0, 0 ); |
| |
| // bring up a file choser if printing to file port but no file name given |
| OUString aOutFileName; |
| if( mpInfoPrinter->maPortName.EqualsIgnoreCaseAscii( "FILE:" ) && !(pFileName && pFileName->Len()) ) |
| { |
| |
| uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); |
| if( xFactory.is() ) |
| { |
| uno::Reference< XFilePicker > xFilePicker( xFactory->createInstance( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ) ), |
| UNO_QUERY ); |
| DBG_ASSERT( xFilePicker.is(), "could not get FilePicker service" ); |
| |
| uno::Reference< XInitialization > xInit( xFilePicker, UNO_QUERY ); |
| uno::Reference< XFilterManager > xFilterMgr( xFilePicker, UNO_QUERY ); |
| if( xInit.is() && xFilePicker.is() && xFilterMgr.is() ) |
| { |
| Sequence< Any > aServiceType( 1 ); |
| aServiceType[0] <<= TemplateDescription::FILESAVE_SIMPLE; |
| xInit->initialize( aServiceType ); |
| if( xFilePicker->execute() == ExecutableDialogResults::OK ) |
| { |
| Sequence< OUString > aPathSeq( xFilePicker->getFiles() ); |
| INetURLObject aObj( aPathSeq[0] ); |
| // we're using ansi calls (StartDocA) so convert the string |
| aOutFileName = aObj.PathToFileName(); |
| } |
| else |
| { |
| mnError = SAL_PRINTER_ERROR_ABORT; |
| return FALSE; |
| } |
| } |
| } |
| } |
| |
| if( aSalShlData.mbWPrinter ) |
| { |
| DOCINFOW aInfo; |
| memset( &aInfo, 0, sizeof( DOCINFOW ) ); |
| aInfo.cbSize = sizeof( aInfo ); |
| aInfo.lpszDocName = (LPWSTR)rJobName.GetBuffer(); |
| if ( pFileName || aOutFileName.getLength() ) |
| { |
| if ( (pFileName && pFileName->Len()) || aOutFileName.getLength() ) |
| { |
| aInfo.lpszOutput = (LPWSTR)( (pFileName && pFileName->Len()) ? pFileName->GetBuffer() : aOutFileName.getStr()); |
| } |
| else |
| aInfo.lpszOutput = L"FILE:"; |
| } |
| else |
| aInfo.lpszOutput = NULL; |
| |
| // start Job |
| int nRet = lcl_StartDocW( hDC, &aInfo, this ); |
| |
| if ( nRet <= 0 ) |
| { |
| long nError = GetLastError(); |
| if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) ) |
| mnError = SAL_PRINTER_ERROR_ABORT; |
| else |
| mnError = SAL_PRINTER_ERROR_GENERALERROR; |
| return FALSE; |
| } |
| } |
| else |
| { |
| // Both strings must exist, if StartJob() is called |
| ByteString aJobName( ImplSalGetWinAnsiString( rJobName, TRUE ) ); |
| ByteString aFileName; |
| |
| DOCINFOA aInfo; |
| memset( &aInfo, 0, sizeof( DOCINFOA ) ); |
| aInfo.cbSize = sizeof( aInfo ); |
| aInfo.lpszDocName = (LPCSTR)aJobName.GetBuffer(); |
| if ( pFileName || aOutFileName.getLength() ) |
| { |
| if ( pFileName->Len() || aOutFileName.getLength() ) |
| { |
| aFileName = ImplSalGetWinAnsiString( pFileName ? *pFileName : static_cast<const XubString>(aOutFileName), TRUE ); |
| aInfo.lpszOutput = (LPCSTR)aFileName.GetBuffer(); |
| } |
| else |
| aInfo.lpszOutput = "FILE:"; |
| } |
| else |
| aInfo.lpszOutput = NULL; |
| |
| // start Job |
| int nRet = lcl_StartDocA( hDC, &aInfo, this ); |
| if ( nRet <= 0 ) |
| { |
| long nError = GetLastError(); |
| if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) ) |
| mnError = SAL_PRINTER_ERROR_ABORT; |
| else |
| mnError = SAL_PRINTER_ERROR_GENERALERROR; |
| return FALSE; |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalPrinter::EndJob() |
| { |
| DWORD err = 0; |
| HDC hDC = mhDC; |
| if ( isValid() && hDC ) |
| { |
| if ( mpGraphics ) |
| { |
| ImplSalDeInitGraphics( mpGraphics ); |
| delete mpGraphics; |
| mpGraphics = NULL; |
| } |
| |
| // #i54419# Windows fax printer brings up a dialog in EndDoc |
| // which text previously copied in soffice process can be |
| // pasted to -> deadlock due to mutex not released. |
| // it should be safe to release the yield mutex over the EndDoc |
| // call, however the real solution is supposed to be the threading |
| // framework yet to come. |
| SalData* pSalData = GetSalData(); |
| sal_uLong nAcquire = pSalData->mpFirstInstance->ReleaseYieldMutex(); |
| CATCH_DRIVER_EX_BEGIN; |
| if( ::EndDoc( hDC ) <= 0 ) |
| err = GetLastError(); |
| CATCH_DRIVER_EX_END( "exception in EndDoc", this ); |
| |
| pSalData->mpFirstInstance->AcquireYieldMutex( nAcquire ); |
| DeleteDC( hDC ); |
| mhDC = 0; |
| } |
| |
| return TRUE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalPrinter::AbortJob() |
| { |
| mbAbort = TRUE; |
| |
| // Abort asyncron ausloesen |
| HDC hDC = mhDC; |
| if ( hDC ) |
| { |
| SalData* pSalData = GetSalData(); |
| ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, |
| SAL_MSG_PRINTABORTJOB, (WPARAM)hDC, 0 ); |
| } |
| |
| return TRUE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplSalPrinterAbortJobAsync( HDC hPrnDC ) |
| { |
| SalData* pSalData = GetSalData(); |
| WinSalPrinter* pPrinter = pSalData->mpFirstPrinter; |
| |
| // Feststellen, ob Printer noch existiert |
| while ( pPrinter ) |
| { |
| if ( pPrinter->mhDC == hPrnDC ) |
| break; |
| |
| pPrinter = pPrinter->mpNextPrinter; |
| } |
| |
| // Wenn Printer noch existiert, dann den Job abbrechen |
| if ( pPrinter ) |
| { |
| HDC hDC = pPrinter->mhDC; |
| if ( hDC ) |
| { |
| if ( pPrinter->mpGraphics ) |
| { |
| ImplSalDeInitGraphics( pPrinter->mpGraphics ); |
| delete pPrinter->mpGraphics; |
| pPrinter->mpGraphics = NULL; |
| } |
| |
| CATCH_DRIVER_EX_BEGIN; |
| ::AbortDoc( hDC ); |
| CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter ); |
| |
| DeleteDC( hDC ); |
| pPrinter->mhDC = 0; |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| SalGraphics* WinSalPrinter::StartPage( ImplJobSetup* pSetupData, sal_Bool bNewJobData ) |
| { |
| if( ! isValid() || mhDC == 0 ) |
| return NULL; |
| |
| HDC hDC = mhDC; |
| if ( pSetupData && pSetupData->mpDriverData && bNewJobData ) |
| { |
| if( aSalShlData.mbWPrinter ) |
| { |
| LPDEVMODEW pOrgDevModeW; |
| LPDEVMODEW pDevModeW; |
| pOrgDevModeW = SAL_DEVMODE_W( pSetupData ); |
| pDevModeW = ImplSalSetCopies( pOrgDevModeW, mnCopies, mbCollate ); |
| ResetDCW( hDC, pDevModeW ); |
| if ( pDevModeW != pOrgDevModeW ) |
| rtl_freeMemory( pDevModeW ); |
| } |
| else |
| { |
| LPDEVMODEA pOrgDevModeA; |
| LPDEVMODEA pDevModeA; |
| pOrgDevModeA = SAL_DEVMODE_A( pSetupData ); |
| pDevModeA = ImplSalSetCopies( pOrgDevModeA, mnCopies, mbCollate ); |
| ResetDCA( hDC, pDevModeA ); |
| if ( pDevModeA != pOrgDevModeA ) |
| rtl_freeMemory( pDevModeA ); |
| } |
| } |
| int nRet = 0; |
| CATCH_DRIVER_EX_BEGIN; |
| nRet = ::StartPage( hDC ); |
| CATCH_DRIVER_EX_END( "exception in StartPage", this ); |
| |
| if ( nRet <= 0 ) |
| { |
| GetLastError(); |
| mnError = SAL_PRINTER_ERROR_GENERALERROR; |
| return NULL; |
| } |
| |
| // Hack to work around old PostScript printer drivers optimizing away empty pages |
| // TODO: move into ImplCreateSalPrnGraphics()? |
| 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 ); |
| |
| mpGraphics = ImplCreateSalPrnGraphics( hDC ); |
| return mpGraphics; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalPrinter::EndPage() |
| { |
| HDC hDC = mhDC; |
| if ( hDC && mpGraphics ) |
| { |
| ImplSalDeInitGraphics( mpGraphics ); |
| delete mpGraphics; |
| mpGraphics = NULL; |
| } |
| |
| if( ! isValid() ) |
| return FALSE; |
| |
| int nRet = 0; |
| CATCH_DRIVER_EX_BEGIN; |
| nRet = ::EndPage( hDC ); |
| CATCH_DRIVER_EX_END( "exception in EndPage", this ); |
| |
| if ( nRet > 0 ) |
| return TRUE; |
| else |
| { |
| GetLastError(); |
| mnError = SAL_PRINTER_ERROR_GENERALERROR; |
| return FALSE; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uLong WinSalPrinter::GetErrorCode() |
| { |
| return mnError; |
| } |