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, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * See the COPYING file for full license information.
23 #include "src/lpr/Printer.hh"
24 #include "src/lpr/Win32Utils.hh"
27 inline LPTSTR
tstr(const string
& str
)
29 return const_cast<char*>(str
.c_str());
32 Printer::Printer(const string
&name
, bool debugFlag
) throw(PrinterException
)
34 m_debugFlag(debugFlag
),
35 m_devHandle(INVALID_HANDLE_VALUE
),
42 m_buffer
= new unsigned char[m_bufferSize
];
47 // Initialize the DEVMODE structure
48 // Get the amount of space needed for the buffer.
49 DWORD needed
= DocumentProperties(NULL
, m_devHandle
, tstr(m_devName
),
52 m_devMode
= reinterpret_cast<DEVMODE
*>(new unsigned char[needed
]);
54 // Get the default DEVMODE for the printer.
55 DWORD ret
= DocumentProperties(NULL
, m_devHandle
, tstr(m_devName
),
56 m_devMode
, NULL
, DM_OUT_BUFFER
);
58 throw PrinterException("error getting the default device mode: " +
59 Win32Utils::getErrorMessage());
61 // Close the printer, because we'll need to reopen it later, passing it
62 // the DEVMODE structure with any optional changes by the user.
77 if (m_devHandle
!= INVALID_HANDLE_VALUE
)
79 ClosePrinter(m_devHandle
);
80 m_devHandle
= INVALID_HANDLE_VALUE
;
84 void Printer::endDoc() throw(PrinterException
)
86 if (!EndDocPrinter(m_devHandle
))
87 throw PrinterException("EndDocPrinter error: " +
88 Win32Utils::getErrorMessage());
91 void Printer::endPage() 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) throw(PrinterException
)
101 if (m_bufferIndex
> 0)
103 write(m_buffer
, m_bufferIndex
);
108 bool Printer::getRawFlag() const
113 void Printer::print(istream
& in
, const string
& docName
) throw(PrinterException
)
121 if (!m_rawFlag
&& ch
== '\n' && lastCh
!= '\r')
130 void Printer::put(unsigned char ch
) throw(PrinterException
)
132 if (m_bufferIndex
== m_bufferSize
)
134 m_buffer
[m_bufferIndex
++] = ch
;
137 void Printer::setRawFlag(bool flag
)
142 void Printer::startDoc(const string
& docName
) throw(PrinterException
)
148 di1
.pDocName
= tstr(docName
);
152 if (StartDocPrinter(m_devHandle
, 1, (LPBYTE
) &di1
) == 0)
153 throw PrinterException("StartDocPrinter error: " +
154 Win32Utils::getErrorMessage());
157 void Printer::startPage() throw(PrinterException
)
159 cout
<< "Printer::startPage()" << endl
;
160 if (!StartPagePrinter(m_devHandle
))
161 throw PrinterException("StartPagePrinter error: " +
162 Win32Utils::getErrorMessage());
165 void Printer::write(unsigned char *buf
, unsigned int size
) throw(PrinterException
)
168 if (!WritePrinter(m_devHandle
, buf
, size
, &written
))
169 throw PrinterException("error writing to device '" + m_devName
+ "': " +
170 Win32Utils::getErrorMessage());
173 //***************************************************************************
175 // Private operations
177 //***************************************************************************
179 Printer::PrinterList
Printer::enumPrinters(DWORD flags
, LPTSTR name
) throw(PrinterException
)
183 EnumPrinters(flags
, name
, 5, 0, 0, &bytesNeeded
, &numPrinters
);
184 auto_ptr
<BYTE
> enumBuffer(new BYTE
[bytesNeeded
]);
185 if (!EnumPrinters(flags
, name
, 5, enumBuffer
.get(), bytesNeeded
,
186 &bytesNeeded
, &numPrinters
))
187 throw PrinterException("unable to enumerate printers: " +
188 Win32Utils::getErrorMessage());
190 PRINTER_INFO_5
*pi
= reinterpret_cast<PRINTER_INFO_5
*>(enumBuffer
.get());
193 for (unsigned int ii
= 0; ii
< numPrinters
; ++ii
)
196 cerr
<< "Printer name: '" << pi
->pPrinterName
<< "', "
197 << "Port name: '" << pi
->pPortName
<< "'" << endl
;
198 list
.push_back(*pi
++);
204 void Printer::mapPortName() throw(PrinterException
)
208 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
210 bool isWindows9x
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
&&
211 (osvi
.dwMajorVersion
> 4 ||
212 (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
> 0)));
214 bool isWindows2K_NT4
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
&&
215 osvi
.dwMajorVersion
>= 4);
218 cout
<< "isWindows9x = " << isWindows9x
<< ", "
219 << "isWindows2K_NT4 = " << isWindows2K_NT4
<< endl
;
225 PrinterList list
= enumPrinters(PRINTER_ENUM_NAME
, empty
);
226 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
228 if (strcasecmp(m_devName
.c_str(), it
->pPortName
) == 0)
231 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
233 m_devName
= it
->pPrinterName
;
239 else if (isWindows2K_NT4
)
241 PrinterList list
= enumPrinters(PRINTER_ENUM_LOCAL
, 0);
242 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
244 if (strcasecmp(m_devName
.c_str(), it
->pPortName
) == 0)
247 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
249 m_devName
= it
->pPrinterName
;
254 list
= enumPrinters(PRINTER_ENUM_CONNECTIONS
, 0);
255 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
257 if (strcasecmp(m_devName
.c_str(), it
->pPortName
) == 0)
260 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
262 m_devName
= it
->pPrinterName
;
269 void Printer::open() throw(PrinterException
)
271 PRINTER_DEFAULTS prDef
;
274 prDef
.pDatatype
= raw
;
275 prDef
.pDevMode
= m_devMode
;
276 prDef
.DesiredAccess
= PRINTER_ACCESS_USE
;
278 if (m_devHandle
== INVALID_HANDLE_VALUE
&&
279 !OpenPrinter(tstr(m_devName
), &m_devHandle
, &prDef
))
280 throw PrinterException("can't open '" + m_devName
+ "' for writing: " +
281 Win32Utils::getErrorMessage());