1 Index: vcl/unx/source/gdi/makefile.mk
2 ===================================================================
3 RCS file: /cvs/gsl/vcl/unx/source/gdi/makefile.mk,v
4 retrieving revision 1.9
5 diff -u -p -u -r1.9 makefile.mk
6 --- vcl/unx/source/gdi/makefile.mk 27 Aug 2002 14:52:35 -0000 1.9
7 +++ vcl/unx/source/gdi/makefile.mk 29 May 2003 15:44:36 -0000
8 @@ -103,7 +103,8 @@ SLOFILES= \
9 CFLAGS+=-D_USE_PRINT_EXTENSION_=1
10 SLOFILES+=$(SLO)$/xprintext.obj
12 -SLOFILES+=$(SLO)$/salprnpsp.obj
13 +CFLAGS+= `pkg-config --cflags libgnomecups-1.0`
14 +SLOFILES+=$(SLO)$/salprncups.obj
17 .IF "$(OS)"=="SOLARIS"
18 Index: vcl/unx/inc/salprn.h
19 ===================================================================
20 RCS file: /cvs/gsl/vcl/unx/inc/salprn.h,v
21 retrieving revision 1.9
22 diff -u -p -u -r1.9 salprn.h
23 --- vcl/unx/inc/salprn.h 13 Nov 2002 20:24:03 -0000 1.9
24 +++ vcl/unx/inc/salprn.h 2 Jun 2003 11:56:15 -0000
25 @@ -85,8 +85,10 @@ struct SalInfoPrinterData
36 @@ -95,7 +97,8 @@ struct SalPrinterData
37 ::psp::PrinterJob m_aPrintJob;
38 ::psp::JobData m_aJobData;
39 ::psp::PrinterGfx m_aPrinterGfx;
42 + bool isPrintToFile() { return m_aFileName.Len() > 0; }
46 --- /dev/null 2003-01-30 10:24:37.000000000 +0000
47 +++ vcl/unx/source/gdi/salprncups.cxx 2003-05-29 16:48:01.000000000 +0100
49 +/*************************************************************************
55 + * last change: $Author$ $Date$
57 + * The Contents of this file are made available subject to the terms of
58 + * either of the following licenses
60 + * - GNU Lesser General Public License Version 2.1
61 + * - Sun Industry Standards Source License Version 1.1
63 + * Sun Microsystems Inc., October, 2000
65 + * GNU Lesser General Public License Version 2.1
66 + * =============================================
67 + * Copyright 2000 by Sun Microsystems, Inc.
68 + * 901 San Antonio Road, Palo Alto, CA 94303, USA
70 + * This library is free software; you can redistribute it and/or
71 + * modify it under the terms of the GNU Lesser General Public
72 + * License version 2.1, as published by the Free Software Foundation.
74 + * This library is distributed in the hope that it will be useful,
75 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
76 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
77 + * Lesser General Public License for more details.
79 + * You should have received a copy of the GNU Lesser General Public
80 + * License along with this library; if not, write to the Free Software
81 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
85 + * Sun Industry Standards Source License Version 1.1
86 + * =================================================
87 + * The contents of this file are subject to the Sun Industry Standards
88 + * Source License Version 1.1 (the "License"); You may not use this file
89 + * except in compliance with the License. You may obtain a copy of the
90 + * License at http://www.openoffice.org/license.html.
92 + * Software provided under this License is provided on an "AS IS" basis,
93 + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
94 + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
95 + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
96 + * See the License for the specific provisions governing your rights and
97 + * obligations concerning the Software.
99 + * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
101 + * Copyright: 2000 by Sun Microsystems, Inc.
103 + * All Rights Reserved.
105 + * Contributor(s): _______________________________________
108 + ************************************************************************/
111 + this file implements the sal printer interface ( SalPrinter, SalInfoPrinter
112 + and some printer relevant methods of SalInstance and SalGraphicsData )
114 + as aunderlying library the printer features of psprint are used.
116 + The query methods of a SalInfoPrinter are implemented by querying psprint
118 + The job methods of a SalPrinter are implemented by calling psprint
119 + printer job functions.
124 +#include <sys/wait.h>
126 +#ifndef _SV_JOBSET_H
129 +#ifndef _SV_SALINST_HXX
130 +#include <salinst.hxx>
132 +#ifndef _SV_SALPRN_HXX
133 +#include <salprn.hxx>
135 +#ifndef _SV_SALGDI_HXX
136 +#include <salgdi.hxx>
141 +#ifndef _SV_SALPTYPE_HXX
142 +#include <salptype.hxx>
144 +#ifndef _SV_SALFRAME_HXX
145 +#include <salframe.hxx>
147 +#ifndef _SV_SALDATA_HXX
148 +#include <saldata.hxx>
151 +#include <sys/types.h>
152 +#include <sys/stat.h>
158 +#include <psprint/printerinfomanager.hxx>
160 +#ifndef _PSPRINT_JOBDATA_HXX_
161 +#include <psprint/jobdata.hxx>
164 +#include <libgnomecups/gnome-cups-init.h>
165 +#include <libgnomecups/gnome-cups-printer.h>
167 +static bool cups_debug = false;
171 +using namespace cups;
172 +using namespace psp;
173 +using namespace rtl;
174 +using namespace osl;
178 + class PrinterInfoManagerCups : ::psp::PrinterInfoManager
180 + PrinterInfoManagerCups();
181 + void initialize ();
183 + ::psp::JobData m_aGlobalDefaults;
184 + ::rtl::OUString m_aDefaultPrinter;
185 + GList *m_aPrinterList;
186 + ::std::hash_map< ::rtl::OUString, ::psp::JobData, ::rtl::OUStringHash > m_aJobDataCache;
189 + void mergeToJobData ( ::psp::JobData &rJobInfo, const PPDParser *pParser );
190 + void mergeCupsSettings ( ::psp::JobData &rJobInfo );
192 + String m_aGlobalDriverName;
193 + static PrinterInfoManagerCups& getCups();
195 + bool isBuiltinGeneric() { return m_aPrinterList == NULL; };
197 + void listPrinters ( ::std::list< ::rtl::OUString >& rList ) const;
198 + ::psp::JobData getJobInfo ( const ::rtl::OUString& rPrinter );
199 + SalPrinterQueueInfo *getSalPrinterQueueInfo ( const ::rtl::OUString& rPrinter );
200 + bool checkPrintersChanged ();
201 + GnomeCupsPrinter *getGnomePrinter ( const ::rtl::OUString& rPrinter );
202 + GnomeCupsPrinter *getGnomePrinter ( SalPrinterQueueInfo *aQueueInfo )
203 + { return getGnomePrinter ( aQueueInfo->maPrinterName ); }
204 + const ::rtl::OUString& getDefaultPrinter () const
205 + { return m_aDefaultPrinter; }
206 + virtual const PPDParser *getParserForPrinter( ::rtl::OUString rPrinter );
207 + virtual ::std::hash_map< fontID, fontID > *getFontSubstitutesForPrinter( ::rtl::OUString rPrinter );
208 + virtual FILE *getPipeToPrinter( ::rtl::OUString rPrinter );
211 + PrinterInfoManagerCups& PrinterInfoManagerCups::getCups()
213 + static PrinterInfoManagerCups aManager;
220 + gcups_password_cb (const char *prompt,
223 + GnomeCupsAuthContext *ctxt)
225 + fprintf( stderr, "No authentication yet\n" );
230 + PrinterInfoManagerCups::PrinterInfoManagerCups()
232 + static bool cups_initialized = false;
233 + if (!cups_initialized) {
234 + cups_initialized = true;
235 + gnome_cups_init( gcups_password_cb );
236 + if (g_getenv ("CUPS_DEBUG") &&
237 + atoi (g_getenv ("CUPS_DEBUG")))
243 + const ::psp::PPDParser *
244 + PrinterInfoManagerCups::getParserForPrinter( ::rtl::OUString rPrinter )
246 + return getJobInfo( rPrinter ).m_pParser;
249 + ::std::hash_map< fontID, fontID > *
250 + PrinterInfoManagerCups::getFontSubstitutesForPrinter( ::rtl::OUString rPrinter )
251 + { // font mapping tables are a terrible idea.
256 + PrinterInfoManagerCups::getPipeToPrinter( ::rtl::OUString rPrinter )
257 + { // we always print to a file
261 + bool PrinterInfoManagerCups::checkPrintersChanged()
263 + bool different = false;
266 + /* gnome-cups does timeout polling */
267 + printers = gnome_cups_get_printers ();
268 + if (g_list_length (printers) != g_list_length (m_aPrinterList))
272 + for (l2 = m_aPrinterList, l1 = printers;
273 + l1 && l2; l1 = l1->next, l2 = l2->next) {
274 + if (strcmp ((char *) l1->data, (char *) l2->data)) {
287 + void PrinterInfoManagerCups::initialize()
289 + rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
290 + OUString aPrinterPath( getPrinterPath() );
291 + m_aJobDataCache.clear();
293 + // first initialize the global defaults
294 + m_aGlobalDefaults = JobData();
295 + m_aGlobalDriverName = String( RTL_CONSTASCII_USTRINGPARAM( "CUPS" ) );
297 + // g_warning ("We need to parse SGEN43.PS ... - how can we ship that ?");
298 + // need a parser for the PPDContext. generic printer should do.
299 + m_aGlobalDefaults.m_pParser = PPDParser::getParser
300 + ( String( RTL_CONSTASCII_USTRINGPARAM( "SGENPRT" ) ) );
301 + m_aGlobalDefaults.m_aContext.setParser( m_aGlobalDefaults.m_pParser );
303 + if( ! m_aGlobalDefaults.m_pParser )
305 + fprintf( stderr, "Error: no SGENPRT available, shutting down psprint...\n" );
310 + if (!(prnt = gnome_cups_get_default()))
311 + prnt = g_strdup("GenericPostscript");
312 + m_aDefaultPrinter = OUString( prnt, strlen( prnt ), RTL_TEXTENCODING_UTF8 );
315 + gnome_cups_printer_list_free( m_aPrinterList );
316 + m_aPrinterList = gnome_cups_get_printers();
320 + PrinterInfoManagerCups::listPrinters( ::std::list< OUString >& rList ) const
325 + if (m_aPrinterList)
327 + for (l = m_aPrinterList; l; l = l->next)
328 + rList.push_back( OUString( (char *)l->data,
329 + strlen( (char *) l->data ),
330 + RTL_TEXTENCODING_UTF8 ) );
334 + rList.push_back( ::rtl::OUString::createFromAscii( "GenericPostscript" ) );
339 + PrinterInfoManagerCups::getGnomePrinter ( const ::rtl::OUString& rPrinter )
341 + if (isBuiltinGeneric())
345 + OString name = OUStringToOString( rPrinter, RTL_TEXTENCODING_UTF8 );
346 + return gnome_cups_printer_get (name.getStr());
350 + SalPrinterQueueInfo*
351 + PrinterInfoManagerCups::getSalPrinterQueueInfo ( const ::rtl::OUString& rPrinter )
353 + GnomeCupsPrinter *printer = getGnomePrinter( rPrinter );
355 + OString name = OUStringToOString( rPrinter, RTL_TEXTENCODING_UTF8 );
356 + // fprintf (stderr, "Add printer '%s'\n", name.getStr());
358 + SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
359 + pInfo->maPrinterName = OUString (rPrinter);
360 + pInfo->maDriver = m_aGlobalDriverName;
361 + pInfo->maLocation = String
362 + ( printer ? gnome_cups_printer_get_location( printer ) : "", RTL_TEXTENCODING_UTF8);
363 + pInfo->maComment = String
364 + ( printer ? gnome_cups_printer_get_description (printer) : "", RTL_TEXTENCODING_UTF8);
365 + pInfo->mpSysData = NULL;
366 + pInfo->mnJobs = printer ? gnome_cups_printer_get_job_count (printer) : 0;
368 + gnome_cups_printer_unref( printer );
375 + PrinterInfoManagerCups::mergeToJobData ( ::psp::JobData &rJobInfo,
376 + const PPDParser *pParser )
378 + rJobInfo.m_pParser = pParser;
379 + rJobInfo.m_aContext.setParser( pParser );
381 + // merge the ppd context keys if the printer has the same keys and values
382 + // this is a bit tricky, since it involves mixing two PPDs
383 + // without constraints which might end up badly
384 + // this feature should be use with caution
385 + // it is mainly to select default paper sizes for new printers
386 + for( int nPPDValueModified = 0; nPPDValueModified < m_aGlobalDefaults.m_aContext.countValuesModified(); nPPDValueModified++ )
388 + const PPDKey* pDefKey = m_aGlobalDefaults.m_aContext.getModifiedKey( nPPDValueModified );
389 + const PPDValue* pDefValue = m_aGlobalDefaults.m_aContext.getValue( pDefKey );
390 + const PPDKey* pPrinterKey = pDefKey ? rJobInfo.m_pParser->getKey( pDefKey->getKey() ) : NULL;
391 + if( pDefKey && pPrinterKey )
392 + // at least the options exist in both PPDs
396 + const PPDValue* pPrinterValue = pPrinterKey->getValue( pDefValue->m_aOption );
397 + if( pPrinterValue )
398 + // the printer has a corresponding option for the key
399 + rJobInfo.m_aContext.setValue( pPrinterKey, pPrinterValue );
402 + rJobInfo.m_aContext.setValue( pPrinterKey, NULL );
408 + PrinterInfoManagerCups::mergeCupsSettings( ::psp::JobData &rJobInfo )
410 + GnomeCupsPrinter *printer;
412 + printer = getGnomePrinter( rJobInfo.m_aPrinterName );
415 + gnome_cups_printer_force_refresh( printer, GNOME_CUPS_PRINTER_REFRESH_OPTIONS );
416 + g_warning ("Forced printer option refresh");
419 + // Set the local cups options
423 + g_warning ("Refreshing user options ...");
425 + GList *user_options = gnome_cups_printer_get_options (printer);
427 + for (GList *l = user_options; l; l = l->next)
429 + GnomeCupsPrinterOptionChoice *opt = (GnomeCupsPrinterOptionChoice *) l->data;
431 + char *value = gnome_cups_printer_get_option_value (printer, opt->value);
434 + g_warning (" '%s' -> '%s'", opt->value, value);
436 + if (!opt->text || !value)
439 + const PPDKey* pKey;
441 + pKey = rJobInfo.m_pParser->getKey( String::CreateFromAscii( opt->value ) );
443 + const PPDValue* pValue;
445 + pValue = pKey->getValue( String( value, RTL_TEXTENCODING_UTF8 ) );
448 + rJobInfo.m_aContext.setValue( pKey, pValue );
450 + else if (cups_debug)
451 + g_warning ("No value '%s'", value);
453 + } else if (cups_debug)
454 + g_warning ("No key '%s'", opt->value);
456 + gnome_cups_printer_option_list_free (user_options);
458 + gnome_cups_printer_unref( printer );
460 + else if (cups_debug)
461 + g_warning ("No printer");
465 + PrinterInfoManagerCups::getJobInfo( const ::rtl::OUString& rPrinter )
467 + ::std::hash_map< OUString, ::psp::JobData, OUStringHash >::const_iterator it = m_aJobDataCache.find( rPrinter );
469 + if (it != m_aJobDataCache.end()) {
470 + ::psp::JobData aJobInfo = it->second;
471 + mergeCupsSettings( aJobInfo );
476 + ::psp::JobData aJobInfo = m_aGlobalDefaults;
478 + OString name = OUStringToOString( rPrinter, RTL_TEXTENCODING_UTF8 );
480 + aJobInfo.m_aPrinterName = OUString (rPrinter);
483 + if( cups_debug && (v = g_getenv( "PPD_DO" )) && atoi( v ) )
484 + g_warning ("--- ppd parsing disabled ---");
487 + GnomeCupsPrinter *printer = NULL;
488 + GnomeCupsPPDFile *ppd_file = NULL;
489 + char *ppd_fname = NULL;
490 + const PPDParser *pParser = NULL;
492 + if ( ( printer = getGnomePrinter( rPrinter ) ) &&
493 + ( ppd_file = gnome_cups_printer_get_ppd_file( printer ) ) &&
494 + ( ppd_fname = gnome_cups_ppd_file_get_name( ppd_file ) ) &&
495 + ( pParser = PPDParser::getParser ( String( ppd_fname, RTL_TEXTENCODING_UTF8 ) ) ) &&
499 + g_warning ("---- parse ppd ...----");
500 + mergeToJobData (aJobInfo, pParser);
502 + else if (cups_debug)
503 + g_warning ("---- failed to parse ppd '%s' ----", ppd_fname);
505 + g_free( ppd_fname );
506 + gnome_cups_ppd_file_release( ppd_file );
507 + gnome_cups_printer_unref( printer );
510 + mergeCupsSettings( aJobInfo );
513 + m_aJobDataCache[ rPrinter ] = aJobInfo;
518 +} /* namespace cups */
520 +inline int PtTo10Mu( int nPoints ) { return (int)(((double)nPoints)*35.27777778)+0.5; }
522 +inline int TenMuToPt( int nUnits ) { return (int)(((double)nUnits)/35.27777778)+0.5; }
533 + { 29700, 42000, "A3", 2, PAPER_A3 },
534 + { 21000, 29700, "A4", 2, PAPER_A4 },
535 + { 14800, 21000, "A5", 2, PAPER_A5 },
536 + { 25000, 35300, "B4", 2, PAPER_B4 },
537 + { 17600, 25000, "B5", 2, PAPER_B5 },
538 + { 21600, 27900, "Letter", 6, PAPER_LETTER },
539 + { 21600, 35600, "Legal", 5, PAPER_LEGAL },
540 + { 27900, 43100, "Tabloid", 7, PAPER_TABLOID },
541 + { 0, 0, "USER", 4, PAPER_USER }
544 +static Paper getPaperType( const String& rPaperName )
546 + ByteString aPaper( rPaperName, RTL_TEXTENCODING_ISO_8859_1 );
547 + for( int i = 0; i < sizeof( aPaperTab )/sizeof( aPaperTab[0] ); i++ )
549 + if( ! strcmp( aPaper.GetBuffer(), aPaperTab[i].name ) )
550 + return aPaperTab[i].paper;
555 +static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData )
558 + pJobSetup->meOrientation = (Orientation)(rData.m_eOrientation == orientation::Landscape ?
559 + ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT);
565 + rData.m_aContext.getPageSize( aPaper, width, height );
566 + pJobSetup->mePaperFormat = getPaperType( aPaper );
567 + pJobSetup->mnPaperWidth = 0;
568 + pJobSetup->mnPaperHeight = 0;
569 + if( pJobSetup->mePaperFormat == PAPER_USER )
571 + // transform to 100dth mm
572 + width = PtTo10Mu( width );
573 + height = PtTo10Mu( height );
575 + if( rData.m_eOrientation == psp::orientation::Portrait )
577 + pJobSetup->mnPaperWidth = width;
578 + pJobSetup->mnPaperHeight = height;
582 + pJobSetup->mnPaperWidth = height;
583 + pJobSetup->mnPaperHeight = width;
588 + const PPDKey* pKey;
589 + const PPDValue* pValue;
590 + ::std::list< const PPDValue* > aValues;
591 + ::std::list< const PPDValue* >::iterator it;
593 + pKey = rData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
594 + pValue = rData.m_aContext.getValue( pKey );
595 + rData.m_aContext.getUnconstrainedValues( pKey, aValues );
596 + pJobSetup->mnPaperBin = 0xffff;
597 + if ( pKey && pValue )
599 + for( pJobSetup->mnPaperBin = 0;
600 + pValue != pKey->getValue( pJobSetup->mnPaperBin ) &&
601 + pJobSetup->mnPaperBin < pKey->countValues();
602 + pJobSetup->mnPaperBin++ )
604 + if( pJobSetup->mnPaperBin >= pKey->countValues() || pValue == pKey->getDefaultValue() )
605 + pJobSetup->mnPaperBin = 0xffff;
607 + for( it = aValues.begin(); it != aValues.end(); ++it, pJobSetup->mnPaperBin++ )
608 + if( *it == pValue )
610 + if( it == aValues.end() )
611 + pJobSetup->mnPaperBin = 0xffff;
613 + // copy the whole context
614 + if( pJobSetup->mpDriverData )
615 + rtl_freeMemory( pJobSetup->mpDriverData );
618 + void* pBuffer = NULL;
619 + if( rData.getStreamBuffer( pBuffer, nBytes ) )
621 + pJobSetup->mnDriverDataLen = nBytes;
622 + pJobSetup->mpDriverData = (BYTE*)pBuffer;
626 + pJobSetup->mnDriverDataLen = 0;
627 + pJobSetup->mpDriverData = NULL;
635 +// -----------------------------------------------------------------------
637 +SalInfoPrinter* SalInstance::CreateInfoPrinter(
638 + SalPrinterQueueInfo *pQueueInfo,
639 + ImplJobSetup *pJobSetup )
641 + maInstData.mbPrinterInit = true;
643 + SalInfoPrinter* pPrinter = new SalInfoPrinter;
644 + PrinterInfoManagerCups& rManager( PrinterInfoManagerCups::getCups() );
645 + ::psp::JobData aJobInfo = rManager.getJobInfo( pQueueInfo->maPrinterName );
647 + pPrinter->maPrinterData.m_aJobData = aJobInfo;
648 + pPrinter->maPrinterData.m_aPrinterGfx.Init( pPrinter->maPrinterData.m_aJobData );
652 + if( pJobSetup->mpDriverData )
653 + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData,
654 + pJobSetup->mnDriverDataLen,
657 + pJobSetup->mnSystem = JOBSETUP_SYSTEM_UNIX;
658 + pJobSetup->maPrinterName = pQueueInfo->maPrinterName;
659 + pJobSetup->maDriver = rManager.m_aGlobalDriverName;
660 + copyJobDataToJobSetup( pJobSetup, aJobInfo );
666 +// -----------------------------------------------------------------------
668 +void SalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
673 +// -----------------------------------------------------------------------
675 +SalPrinter* SalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
677 + maInstData.mbPrinterInit = true;
678 + // create and initialize SalPrinter
679 + SalPrinter* pPrinter = new SalPrinter;
680 + pPrinter->maPrinterData.m_aJobData = pInfoPrinter->maPrinterData.m_aJobData;
685 +// -----------------------------------------------------------------------
687 +void SalInstance::DestroyPrinter( SalPrinter* pPrinter )
692 +// -----------------------------------------------------------------------
694 +void SalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
696 + maInstData.mbPrinterInit = true;
697 + PrinterInfoManagerCups& rManager( PrinterInfoManagerCups::getCups() );
698 + ::std::list< OUString > aPrinters;
699 + rManager.listPrinters( aPrinters );
701 + for( ::std::list< OUString >::iterator it = aPrinters.begin(); it != aPrinters.end(); ++it ) {
702 + SalPrinterQueueInfo *pInfo = rManager.getSalPrinterQueueInfo( *it );
703 + GetPrinterQueueState( pInfo );
704 + pList->Add( pInfo );
708 +// -----------------------------------------------------------------------
710 +void SalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
715 +// -----------------------------------------------------------------------
717 +void SalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
722 + GnomeCupsPrinter *printer;
723 + printer = PrinterInfoManagerCups::getCups().getGnomePrinter( pInfo );
726 + pInfo->mnStatus = QUEUE_STATUS_READY;
730 + switch (gnome_cups_printer_get_state (printer)) {
731 + case IPP_PRINTER_IDLE:
732 + pInfo->mnStatus = QUEUE_STATUS_READY;
734 + case IPP_PRINTER_PROCESSING:
735 + pInfo->mnStatus = QUEUE_STATUS_PROCESSING;
737 + case IPP_PRINTER_STOPPED:
739 + pInfo->mnStatus = QUEUE_STATUS_ERROR;
741 + GList *l, *reasons = gnome_cups_printer_get_state_reasons (printer);
742 + if (!reasons || !reasons->data)
745 + pInfo->mnStatus = 0;
746 + for (l = reasons; l; l = l->next) {
747 + GnomeCupsPrinterReason *reason = (GnomeCupsPrinterReason *) reasons->data;
749 +#define MAP_STATUS(str,en) \
750 + if (!strcmp (reason->keyword, (str))) \
751 + pInfo->mnStatus |= QUEUE_STATUS_##en;
753 + /* cf. RFC 2911.txt 4.4.12 */
754 + MAP_STATUS ("stopping", PENDING_DELETION);
755 + MAP_STATUS ("timed-out", ERROR);
756 + MAP_STATUS ("media-empty", PAPER_PROBLEM);
757 + MAP_STATUS ("connecting-to-device", IO_ACTIVE);
758 + MAP_STATUS ("output-tray-area-full", OUTPUT_BIN_FULL);
759 + MAP_STATUS ("marker-supply-low", TONER_LOW);
760 + MAP_STATUS ("marker-supply-empty", NO_TONER);
761 + MAP_STATUS ("developer-low", TONER_LOW);
762 + MAP_STATUS ("developer-empty", NO_TONER);
763 + MAP_STATUS ("marker-waste-full", USER_INTERVENTION);
764 + MAP_STATUS ("door-open", DOOR_OPEN);
765 + MAP_STATUS ("cover-open", DOOR_OPEN);
766 + MAP_STATUS ("interlock-open", DOOR_OPEN);
767 + MAP_STATUS ("input-tray-missing", DOOR_OPEN);
768 + MAP_STATUS ("output-tray-missing", DOOR_OPEN);
769 + MAP_STATUS ("none", ERROR); // ?
770 + MAP_STATUS ("other", ERROR);
771 + MAP_STATUS ("paused", PAUSED);
772 + MAP_STATUS ("moving-to-paused", PAUSED);
773 + MAP_STATUS ("shutdown", OFFLINE);
774 + MAP_STATUS ("media-jam", PAPER_JAM);
775 + MAP_STATUS ("media-needed", PAPER_OUT);
776 + MAP_STATUS ("media-low", READY); // PAPER_PROBLEM
777 + MAP_STATUS ("output-tray-area-almost-full", READY); // OUTPUT_BIN_FULL
778 + MAP_STATUS ("marker-waste-almost-full", READY); // USER_INTERVENTION
782 + if ( !pInfo->mnStatus )
783 + pInfo->mnStatus = QUEUE_STATUS_ERROR;
785 + gnome_cups_printer_free_reasons( reasons );
788 + gnome_cups_printer_unref( printer );
791 +// -----------------------------------------------------------------------
793 +String SalInstance::GetDefaultPrinter()
795 + maInstData.mbPrinterInit = true;
796 + PrinterInfoManagerCups& rManager( PrinterInfoManagerCups::getCups() );
797 + return rManager.getDefaultPrinter();
800 +// =======================================================================
802 +SalInfoPrinter::SalInfoPrinter()
804 + maPrinterData.m_pGraphics = NULL;
805 + m_bPapersInit = false;
808 +// -----------------------------------------------------------------------
810 +SalInfoPrinter::~SalInfoPrinter()
812 + if( maPrinterData.m_pGraphics )
814 + delete maPrinterData.m_pGraphics;
815 + maPrinterData.m_pGraphics = NULL;
819 +// -----------------------------------------------------------------------
822 +void SalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData )
824 + m_aPaperFormats.clear();
825 + m_bPapersInit = true;
827 + if( maPrinterData.m_aJobData.m_pParser )
829 + const PPDKey* pKey = maPrinterData.m_aJobData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
832 + int nValues = pKey->countValues();
833 + for( int i = 0; i < nValues; i++ )
835 + const PPDValue* pValue = pKey->getValue( i );
836 + vcl::PaperInfo aInfo;
837 + aInfo.m_aPaperName = pValue->m_aOptionTranslation;
838 + if( ! aInfo.m_aPaperName.Len() )
839 + aInfo.m_aPaperName = pValue->m_aOption;
840 + int nWidth = 0, nHeight = 0;
841 + maPrinterData.m_aJobData.m_pParser->getPaperDimension( pValue->m_aOption, nWidth, nHeight );
842 + aInfo.m_nPaperWidth = (unsigned long)((PtTo10Mu( nWidth )+50)/100);
843 + aInfo.m_nPaperHeight = (unsigned long)((PtTo10Mu( nHeight )+50)/100);
844 + m_aPaperFormats.push_back( aInfo );
850 +// -----------------------------------------------------------------------
852 +int SalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData )
857 +// -----------------------------------------------------------------------
859 +SalGraphics* SalInfoPrinter::GetGraphics()
861 + // return a valid pointer only once
862 + // the reasoning behind this is that we could have different
863 + // SalGraphics that can run in multiple threads
865 + SalGraphics* pRet = NULL;
866 + if( ! maPrinterData.m_pGraphics )
868 + maPrinterData.m_pGraphics = new SalGraphics;
869 + maPrinterData.m_pGraphics->maGraphicsData.m_pJobData = &maPrinterData.m_aJobData;
870 + maPrinterData.m_pGraphics->maGraphicsData.m_pPrinterGfx = &maPrinterData.m_aPrinterGfx;
871 + maPrinterData.m_pGraphics->maGraphicsData.bPrinter_ = TRUE;
872 + pRet = maPrinterData.m_pGraphics;
877 +// -----------------------------------------------------------------------
879 +void SalInfoPrinter::ReleaseGraphics( SalGraphics* pGraphics )
881 + if( pGraphics == maPrinterData.m_pGraphics )
884 + maPrinterData.m_pGraphics = NULL;
888 +// -----------------------------------------------------------------------
892 +BOOL SalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pJobSetup )
894 + if( ! pFrame || ! pJobSetup )
897 + OString str = OUStringToOString (maPrinterData.m_aJobData.m_aPrinterName, RTL_TEXTENCODING_UTF8);
898 + const char *argv[] = { "gnome-cups-manager", "--properties", NULL, NULL };
899 + argv [2] = str.getStr ();
903 + fprintf (stderr, "Setup ... [ properties on '%s' ]\n", str.getStr ());
905 + success = g_spawn_async (NULL, (gchar **)argv,
906 + NULL, G_SPAWN_SEARCH_PATH,
907 + NULL, NULL, NULL, NULL);
912 +// -----------------------------------------------------------------------
914 +// This function gets the driver data and puts it into pJobSetup
915 +// If pJobSetup->mpDriverData is NOT NULL, then the independend
916 +// data should be merged into the driver data
917 +// If pJobSetup->mpDriverData IS NULL, then the driver defaults
918 +// should be merged into the independent data
919 +BOOL SalInfoPrinter::SetPrinterData( ImplJobSetup* pJobSetup )
922 + fprintf (stderr, "--- re-fetch data from cupsd ---\n");
923 + if( pJobSetup->mpDriverData )
924 + return SetData( ~0, pJobSetup );
926 + copyJobDataToJobSetup( pJobSetup, maPrinterData.m_aJobData );
930 +// -----------------------------------------------------------------------
932 +// This function merges the independ driver data
933 +// and sets the new independ data in pJobSetup
934 +// Only the data must be changed, where the bit
935 +// in nGetDataFlags is set
936 +BOOL SalInfoPrinter::SetData(
937 + ULONG nSetDataFlags,
938 + ImplJobSetup* pJobSetup )
941 + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
943 + if( aData.m_pParser )
945 + const PPDKey* pKey;
946 + const PPDValue* pValue;
948 + // merge papersize if necessary
949 + if( nSetDataFlags & SAL_JOBSET_PAPERSIZE )
951 + int nWidth, nHeight;
952 + if( pJobSetup->meOrientation == ORIENTATION_PORTRAIT )
954 + nWidth = pJobSetup->mnPaperWidth;
955 + nHeight = pJobSetup->mnPaperHeight;
959 + nWidth = pJobSetup->mnPaperHeight;
960 + nHeight = pJobSetup->mnPaperWidth;
963 + if( pJobSetup->mePaperFormat == PAPER_USER )
964 + aPaper = aData.m_pParser->matchPaper(
965 + TenMuToPt( pJobSetup->mnPaperWidth ),
966 + TenMuToPt( pJobSetup->mnPaperHeight ) );
968 + aPaper = String( ByteString( aPaperTab[ pJobSetup->mePaperFormat ].name ), RTL_TEXTENCODING_ISO_8859_1 );
969 + pKey = aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) );
970 + pValue = pKey ? pKey->getValue( aPaper ) : NULL;
971 + if( ! ( pKey && pValue && aData.m_aContext.setValue( pKey, pValue, false ) == pValue ) )
975 + // merge paperbin if necessary
976 + if( nSetDataFlags & SAL_JOBSET_PAPERBIN )
978 + pKey = aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) );
981 + int nPaperBin = pJobSetup->mnPaperBin;
982 + if( nPaperBin == 0xffff )
983 + pValue = pKey->getDefaultValue();
985 + pValue = pKey->getValue( pJobSetup->mnPaperBin );
987 + // may fail due to constraints;
988 + // real paper bin is copied back to jobsetup in that case
989 + aData.m_aContext.setValue( pKey, pValue );
991 + // if printer has no InputSlot key simply ignore this setting
992 + // (e.g. SGENPRT has no InputSlot)
995 + // merge orientation if necessary
996 + if( nSetDataFlags & SAL_JOBSET_ORIENTATION )
997 + aData.m_eOrientation = pJobSetup->meOrientation == ORIENTATION_LANDSCAPE ? orientation::Landscape : orientation::Portrait;
999 + maPrinterData.m_aJobData = aData;
1000 + copyJobDataToJobSetup( pJobSetup, aData );
1007 +// -----------------------------------------------------------------------
1009 +void SalInfoPrinter::GetPageInfo(
1010 + const ImplJobSetup* pJobSetup,
1011 + long& rOutWidth, long& rOutHeight,
1012 + long& rPageOffX, long& rPageOffY,
1013 + long& rPageWidth, long& rPageHeight )
1019 + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
1021 + // get the selected page size
1022 + if( aData.m_pParser )
1025 + int width, height;
1026 + int left = 0, top = 0, right = 0, bottom = 0;
1027 + int nDPI = aData.m_aContext.getRenderResolution();
1030 + if( aData.m_eOrientation == psp::orientation::Portrait )
1032 + aData.m_aContext.getPageSize( aPaper, width, height );
1033 + aData.m_pParser->getMargins( aPaper, left, right, top, bottom );
1037 + aData.m_aContext.getPageSize( aPaper, height, width );
1038 + aData.m_pParser->getMargins( aPaper, bottom, top, left, right );
1040 + rPageWidth = width * nDPI / 72;
1041 + rPageHeight = height * nDPI / 72;
1042 + rPageOffX = left * nDPI / 72;
1043 + rPageOffY = top * nDPI / 72;
1044 + rOutWidth = ( width - left - right ) * nDPI / 72;
1045 + rOutHeight = ( height - top - bottom ) * nDPI / 72;
1048 + g_warning ("SalInfoPrinter:: GetPageInfo ... margins: %ld %ld %ld %ld",
1049 + rPageOffX, rPageOffY, rPageWidth - rOutWidth, rPageHeight - rOutHeight);
1053 +// -----------------------------------------------------------------------
1055 +ULONG SalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pJobSetup )
1061 + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
1063 + const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL;
1065 + return pKey ? pKey->countValues() : 0;
1068 +// -----------------------------------------------------------------------
1070 +String SalInfoPrinter::GetPaperBinName( const ImplJobSetup* pJobSetup, ULONG nPaperBin )
1073 + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
1076 + if( aData.m_pParser )
1078 + const PPDKey* pKey = aData.m_pParser ? aData.m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "InputSlot" ) ) ): NULL;
1079 + if( nPaperBin == 0xffff || !pKey )
1080 + aRet = aData.m_pParser->getDefaultInputSlot();
1083 + const PPDValue* pValue = pKey->getValue( nPaperBin );
1085 + aRet = pValue->m_aOptionTranslation.Len() ? pValue->m_aOptionTranslation : pValue->m_aOption;
1092 +// -----------------------------------------------------------------------
1094 +ULONG SalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, USHORT nType )
1096 + /* FIXME: surely we can do better here */
1099 + case PRINTER_CAPABILITIES_SUPPORTDIALOG:
1101 + case PRINTER_CAPABILITIES_COPIES:
1103 + case PRINTER_CAPABILITIES_COLLATECOPIES:
1105 + case PRINTER_CAPABILITIES_SETORIENTATION:
1107 + case PRINTER_CAPABILITIES_SETPAPERBIN:
1109 + case PRINTER_CAPABILITIES_SETPAPERSIZE:
1111 + case PRINTER_CAPABILITIES_SETPAPER:
1113 + case PRINTER_CAPABILITIES_FAX:
1120 +// =======================================================================
1126 +SalPrinter::SalPrinter()
1130 +// -----------------------------------------------------------------------
1132 +SalPrinter::~SalPrinter()
1136 +// -----------------------------------------------------------------------
1138 +static inline String getTmpName()
1144 + tmp_name = g_strdup_printf( "%s/ooo-ps-XXXXXX",
1145 + g_get_tmp_dir() );
1147 + if ((fd = g_mkstemp (tmp_name)))
1151 + g_warning ("Failed to create tmpfile '%s'", tmp_name);
1155 + ret = String( ByteString( tmp_name ), RTL_TEXTENCODING_UTF8 );
1157 + g_free (tmp_name);
1162 +BOOL SalPrinter::StartJob(
1163 + const XubString* pFileName,
1164 + const XubString& rJobName,
1165 + const XubString& rAppName,
1166 + ULONG nCopies, BOOL bCollate,
1167 + ImplJobSetup* pJobSetup )
1170 + vcl_sal::PrinterUpdate::jobStarted();
1172 + maPrinterData.m_bFax = false;
1173 + maPrinterData.m_bPdf = false;
1174 + maPrinterData.m_aFileName = pFileName ? *pFileName : String();
1175 + maPrinterData.m_aJobName = rJobName;
1176 + maPrinterData.m_aTmpFile = String();
1177 + maPrinterData.m_nCopies = nCopies;
1179 + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen,
1180 + maPrinterData.m_aJobData );
1181 + if( maPrinterData.m_nCopies > 1 )
1182 + // in case user did not do anything (m_nCopies=1)
1183 + // take the default from jobsetup
1184 + maPrinterData.m_aJobData.m_nCopies = maPrinterData.m_nCopies;
1186 + maPrinterData.m_aTmpFile = getTmpName();
1187 + if (!maPrinterData.m_aTmpFile.Len())
1191 + if (maPrinterData.isPrintToFile ())
1193 + ::std::hash_map< ::rtl::OUString, ::rtl::OUString, ::rtl::OUStringHash >::const_iterator it;
1194 + it = pJobSetup->maValueMap.find( ::rtl::OUString::createFromAscii( "Filter#" ) );
1195 + nMode = S_IRUSR | S_IWUSR;
1196 + if( it != pJobSetup->maValueMap.end() )
1198 + OUString aFilter = it->second;
1199 + maPrinterData.m_bPdf = !aFilter.compareToAscii( "PDF" );
1202 + if (maPrinterData.m_bPdf)
1203 + printTo = maPrinterData.m_aTmpFile;
1205 + printTo = maPrinterData.m_aFileName;
1208 + printTo = maPrinterData.m_aTmpFile;
1210 + maPrinterData.m_aPrinterGfx.Init( maPrinterData.m_aJobData );
1213 + if (PrinterInfoManagerCups::getCups().isBuiltinGeneric() &&
1214 + !maPrinterData.m_aFileName.Len())
1216 +#ifdef SAL_PRINTER_ERROR_NO_PRINTER
1217 + maPrinterData.m_nError = SAL_PRINTER_ERROR_NO_PRINTER;
1220 + g_warning ("Can't print with generic printer");
1224 + return maPrinterData.m_aPrintJob.StartJob
1225 + ( printTo, nMode, rJobName, rAppName, maPrinterData.m_aJobData,
1226 + &maPrinterData.m_aPrinterGfx ) ? TRUE : FALSE;
1229 +// -----------------------------------------------------------------------
1231 +BOOL SalPrinter::EndJob()
1233 + BOOL bSuccess = maPrinterData.m_aPrintJob.EndJob();
1234 + BOOL bUnlink = FALSE;
1235 + OString aTmpName = OUStringToOString
1236 + ( maPrinterData.m_aTmpFile, RTL_TEXTENCODING_UTF8 );
1240 + if (maPrinterData.isPrintToFile ())
1242 + if (maPrinterData.m_bPdf)
1245 + g_warning ("Print to PDF...");
1246 + String aCommandLine = String( RTL_CONSTASCII_USTRINGPARAM(
1247 + "/usr/bin/gs -q -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=\"(OUTFILE)\" (INFILE)" ) );
1249 + if (g_getenv ("SAL_PDF_CONVERT_CMD"))
1250 + aCommandLine.AssignAscii (g_getenv ("SAL_PDF_CONVERT_CMD"));
1252 +#define REPLACE(a,b) \
1253 + while( aCommandLine.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( a ) ), b ) != STRING_NOTFOUND );
1255 + REPLACE ("(OUTFILE)", maPrinterData.m_aFileName);
1256 + REPLACE ("(INFILE)", maPrinterData.m_aTmpFile);
1258 + OString aSystemCmd = OUStringToOString ( aCommandLine, RTL_TEXTENCODING_UTF8 );
1259 + gint exit_status = 0;
1260 + if (!g_spawn_command_line_sync (aSystemCmd.getStr (), NULL, NULL, &exit_status, NULL))
1263 + bSuccess = !exit_status;
1265 + else if (cups_debug)
1266 + g_warning ("Print to PS file...");
1270 + OString aJobTitle = OUStringToOString
1271 + ( maPrinterData.m_aJobName, RTL_TEXTENCODING_UTF8 );
1274 + g_warning( "Printing file '%s' name '%s' to '%s'",
1275 + (const sal_Char *)aTmpName,
1276 + (const sal_Char *)OUStringToOString
1277 + ( maPrinterData.m_aJobName, RTL_TEXTENCODING_UTF8 ),
1278 + (const sal_Char *)OUStringToOString
1279 + ( maPrinterData.m_aJobData.m_aPrinterName, RTL_TEXTENCODING_UTF8 ) );
1281 + GError *error = NULL;
1282 + GList *print_options = NULL;
1283 + GnomeCupsPrinter *printer;
1285 + printer = PrinterInfoManagerCups::getCups().getGnomePrinter
1286 + ( maPrinterData.m_aJobData.m_aPrinterName );
1288 +#ifdef USE_CUPS_OPTIONS
1289 + gnome_cups_printer_force_refresh
1290 + ( printer, GNOME_CUPS_PRINTER_REFRESH_OPTIONS );
1291 + print_options = gnome_cups_printer_get_options( printer );
1293 + bSuccess = gnome_cups_printer_print_file
1294 + ( printer, (const sal_Char *) aTmpName,
1295 + (const sal_Char *) aJobTitle, print_options, &error) != 0;
1299 + g_warning ("Error printing '%s' ... (0x%x)",
1300 + aTmpName.getStr(), error ? error->code : -1);
1301 + // We can map the IPP status type in error->code but
1302 + // since we can only map it to 2 errors, why bother
1303 + maPrinterData.m_nError = PRINTER_GENERALERROR;
1306 +#ifdef USE_CUPS_OPTIONS
1307 + gnome_cups_printer_option_list_free( print_options );
1310 + gnome_cups_printer_unref( printer );
1313 + else if (cups_debug)
1314 + g_warning ("Internal printing was not a success");
1316 + if (maPrinterData.m_aTmpFile.Len())
1319 + g_warning ("Unlinking tmpfile");
1320 + unlink( (const sal_Char *) aTmpName );
1323 + vcl_sal::PrinterUpdate::jobEnded();
1326 + g_warning ("::EndJob returns %d", bSuccess);
1330 +// -----------------------------------------------------------------------
1332 +BOOL SalPrinter::AbortJob()
1334 + BOOL bAbort = maPrinterData.m_aPrintJob.AbortJob() ? TRUE : FALSE;
1335 + vcl_sal::PrinterUpdate::jobEnded();
1339 +// -----------------------------------------------------------------------
1341 +SalGraphics* SalPrinter::StartPage( ImplJobSetup* pJobSetup, BOOL bNewJobData )
1343 + JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, maPrinterData.m_aJobData );
1344 + maPrinterData.m_pGraphics = new SalGraphics();
1345 + maPrinterData.m_pGraphics->maGraphicsData.m_pJobData = &maPrinterData.m_aJobData;
1346 + maPrinterData.m_pGraphics->maGraphicsData.m_pPrinterGfx = &maPrinterData.m_aPrinterGfx;
1347 + maPrinterData.m_pGraphics->maGraphicsData.bPrinter_ = true;
1348 + maPrinterData.m_pGraphics->maGraphicsData.m_pPhoneNr = maPrinterData.m_bFax ? &maPrinterData.m_aFaxNr : NULL;
1349 + maPrinterData.m_pGraphics->maGraphicsData.m_bSwallowFaxNo = maPrinterData.m_bSwallowFaxNo;
1350 + if( maPrinterData.m_nCopies > 1 )
1351 + // in case user did not do anything (m_nCopies=1)
1352 + // take the default from jobsetup
1353 + maPrinterData.m_aJobData.m_nCopies = maPrinterData.m_nCopies;
1355 + maPrinterData.m_aPrintJob.StartPage( maPrinterData.m_aJobData, bNewJobData ? sal_True : sal_False );
1356 + maPrinterData.m_aPrinterGfx.Init( maPrinterData.m_aPrintJob );
1358 + return maPrinterData.m_pGraphics;
1361 +// -----------------------------------------------------------------------
1363 +BOOL SalPrinter::EndPage()
1365 + sal_Bool bResult = maPrinterData.m_aPrintJob.EndPage();
1366 + maPrinterData.m_aPrinterGfx.Clear();
1367 + return bResult ? TRUE : FALSE;
1370 +// -----------------------------------------------------------------------
1372 +ULONG SalPrinter::GetErrorCode()
1374 + return maPrinterData.m_nError;
1378 + * vcl::PrinterUpdate
1381 +Timer* vcl_sal::PrinterUpdate::pPrinterUpdateTimer = NULL;
1382 +int vcl_sal::PrinterUpdate::nActiveJobs = 0;
1384 +void vcl_sal::PrinterUpdate::doUpdate()
1386 + ::cups::PrinterInfoManagerCups& rManager( ::cups::PrinterInfoManagerCups::getCups() );
1387 + if( rManager.checkPrintersChanged() )
1389 + SalFrame* pFrame = GetSalData()->pFirstFrame_;
1392 + pFrame->maFrameData.Call( SALEVENT_PRINTERCHANGED, NULL );
1393 + pFrame = pFrame->maFrameData.GetNextFrame();
1398 +// -----------------------------------------------------------------------
1400 +IMPL_STATIC_LINK( vcl_sal::PrinterUpdate, UpdateTimerHdl, void*, pDummy )
1402 + if( nActiveJobs < 1 )
1405 + delete pPrinterUpdateTimer;
1406 + pPrinterUpdateTimer = NULL;
1409 + pPrinterUpdateTimer->Start();
1414 +// -----------------------------------------------------------------------
1416 +void vcl_sal::PrinterUpdate::update()
1418 + if( nActiveJobs < 1 )
1420 + else if( ! pPrinterUpdateTimer )
1422 + pPrinterUpdateTimer = new Timer();
1423 + pPrinterUpdateTimer->SetTimeout( 500 );
1424 + pPrinterUpdateTimer->SetTimeoutHdl( STATIC_LINK( NULL, vcl_sal::PrinterUpdate, UpdateTimerHdl ) );
1425 + pPrinterUpdateTimer->Start();
1429 +// -----------------------------------------------------------------------
1431 +void vcl_sal::PrinterUpdate::jobEnded()
1434 + if( nActiveJobs < 1 )
1436 + if( pPrinterUpdateTimer )
1438 + pPrinterUpdateTimer->Stop();
1439 + delete pPrinterUpdateTimer;
1440 + pPrinterUpdateTimer = NULL;
1445 Index: vcl/util/makefile.mk
1446 ===================================================================
1447 RCS file: /cvs/gsl/vcl/util/makefile.mk,v
1448 retrieving revision 1.46.2.3
1449 diff -u -p -u -r1.46.2.3 makefile.mk
1450 --- vcl/util/makefile.mk 31 Jul 2003 15:28:43 -0000 1.46.2.3
1451 +++ vcl/util/makefile.mk 29 Aug 2003 14:34:04 -0000
1452 @@ -275,6 +275,8 @@ SHL1STDLIBS += -framework Cocoa
1454 .IF "$(GUIBASE)"=="unx"
1456 +SHL1STDLIBS += `pkg-config --libs libgnomecups-1.0`
1458 .IF "$(WITH_LIBSN)"=="YES"
1459 SHL1STDLIBS+=$(LIBSN_LIBS)