2 * lpr for cygwin/windows
4 * Copyright (C) 2000-2003 Rick Rankin
5 * http://www.cygwin.com/ml/cygwin/2000-07/msg00320.html
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation in version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "src/lpr/Printer.hh"
22 #include "src/lpr/Win32Utils.hh"
24 inline LPTSTR
tstr(const string
& str
)
26 return const_cast<char*>(str
.c_str());
29 Printer::Printer(const string
&name
, bool debugFlag
)
30 throw(PrinterException
)
32 m_debugFlag(debugFlag
),
33 m_devHandle(INVALID_HANDLE_VALUE
),
40 m_buffer
= new unsigned char[m_bufferSize
];
45 // Initialize the DEVMODE structure
46 // Get the amount of space needed for the buffer.
47 DWORD needed
= DocumentProperties(NULL
, m_devHandle
, tstr(m_devName
),
50 m_devMode
= reinterpret_cast<DEVMODE
*>(new unsigned char[needed
]);
52 // Get the default DEVMODE for the printer.
53 DWORD ret
= DocumentProperties(NULL
, m_devHandle
, tstr(m_devName
),
54 m_devMode
, NULL
, DM_OUT_BUFFER
);
56 throw PrinterException("error getting the default device mode: " +
57 Win32Utils::getErrorMessage());
59 // Close the printer, because we'll need to reopen it later, passing it
60 // the DEVMODE structure with any optional changes by the user.
75 if (m_devHandle
!= INVALID_HANDLE_VALUE
)
77 ClosePrinter(m_devHandle
);
78 m_devHandle
= INVALID_HANDLE_VALUE
;
82 void Printer::endDoc()
83 throw(PrinterException
)
85 if (!EndDocPrinter(m_devHandle
))
86 throw PrinterException("EndDocPrinter error: " +
87 Win32Utils::getErrorMessage());
90 void Printer::endPage()
91 throw(PrinterException
)
93 cout
<< "Printer::endPage()" << endl
;
94 if (!EndPagePrinter(m_devHandle
))
95 throw PrinterException("EndPagePrinter error: " +
96 Win32Utils::getErrorMessage());
99 void Printer::flush(void)
100 throw(PrinterException
)
102 if (m_bufferIndex
> 0)
104 write(m_buffer
, m_bufferIndex
);
109 bool Printer::getRawFlag() const
114 void Printer::print(istream
& in
, const string
& docName
)
115 throw(PrinterException
)
124 if (!m_rawFlag
&& ch
== '\n' && lastCh
!= '\r')
133 void Printer::put(unsigned char ch
)
134 throw(PrinterException
)
136 if (m_bufferIndex
== m_bufferSize
)
138 m_buffer
[m_bufferIndex
++] = ch
;
141 void Printer::setRawFlag(bool flag
)
146 void Printer::startDoc(const string
& docName
)
147 throw(PrinterException
)
153 di1
.pDocName
= tstr(docName
);
155 di1
.pDatatype
= "RAW";
157 if (StartDocPrinter(m_devHandle
, 1, (LPBYTE
) &di1
) == 0)
158 throw PrinterException("StartDocPrinter error: " +
159 Win32Utils::getErrorMessage());
162 void Printer::startPage()
163 throw(PrinterException
)
165 cout
<< "Printer::startPage()" << endl
;
166 if (!StartPagePrinter(m_devHandle
))
167 throw PrinterException("StartPagePrinter error: " +
168 Win32Utils::getErrorMessage());
171 void Printer::write(unsigned char *buf
, unsigned int size
)
172 throw(PrinterException
)
175 if (!WritePrinter(m_devHandle
, buf
, size
, &written
))
176 throw PrinterException("error writing to device '" + m_devName
+ "': " +
177 Win32Utils::getErrorMessage());
180 //***************************************************************************
182 // Private operations
184 //***************************************************************************
186 Printer::PrinterList
Printer::enumPrinters(DWORD flags
, LPTSTR name
)
187 throw(PrinterException
)
191 EnumPrinters(flags
, name
, 5, 0, 0, &bytesNeeded
, &numPrinters
);
192 auto_ptr
<BYTE
> enumBuffer(new BYTE
[bytesNeeded
]);
193 if (!EnumPrinters(flags
, name
, 5, enumBuffer
.get(), bytesNeeded
,
194 &bytesNeeded
, &numPrinters
))
195 throw PrinterException("unable to enumerate printers: " +
196 Win32Utils::getErrorMessage());
198 PRINTER_INFO_5
*pi
= reinterpret_cast<PRINTER_INFO_5
*>(enumBuffer
.get());
201 for (unsigned int ii
= 0; ii
< numPrinters
; ++ii
)
204 cerr
<< "Printer name: '" << pi
->pPrinterName
<< "', "
205 << "Port name: '" << pi
->pPortName
<< "'" << endl
;
206 list
.push_back(*pi
++);
212 void Printer::mapPortName()
213 throw(PrinterException
)
217 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
219 bool isWindows9x
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
&&
220 (osvi
.dwMajorVersion
> 4 ||
221 (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
> 0)));
223 bool isWindows2K_NT4
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
&&
224 osvi
.dwMajorVersion
>= 4);
227 cout
<< "isWindows9x = " << isWindows9x
<< ", "
228 << "isWindows2K_NT4 = " << isWindows2K_NT4
<< endl
;
233 PrinterList list
= enumPrinters(PRINTER_ENUM_NAME
, "");
234 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
236 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
239 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
241 m_devName
= it
->pPrinterName
;
247 else if (isWindows2K_NT4
)
249 PrinterList list
= enumPrinters(PRINTER_ENUM_LOCAL
, 0);
250 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
252 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
255 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
257 m_devName
= it
->pPrinterName
;
262 list
= enumPrinters(PRINTER_ENUM_CONNECTIONS
, 0);
263 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
265 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
268 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
270 m_devName
= it
->pPrinterName
;
278 throw(PrinterException
)
280 PRINTER_DEFAULTS prDef
;
282 prDef
.pDatatype
= "RAW";
283 prDef
.pDevMode
= m_devMode
;
284 prDef
.DesiredAccess
= PRINTER_ACCESS_USE
;
286 if (m_devHandle
== INVALID_HANDLE_VALUE
&&
287 !OpenPrinter(tstr(m_devName
), &m_devHandle
, &prDef
))
288 throw PrinterException("can't open '" + m_devName
+ "' for writing: " +
289 Win32Utils::getErrorMessage());