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"
25 inline LPTSTR
tstr(const string
& str
)
27 return const_cast<char*>(str
.c_str());
30 Printer::Printer(const string
&name
, bool debugFlag
) 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() throw(PrinterException
)
84 if (!EndDocPrinter(m_devHandle
))
85 throw PrinterException("EndDocPrinter error: " +
86 Win32Utils::getErrorMessage());
89 void Printer::endPage() throw(PrinterException
)
91 cout
<< "Printer::endPage()" << endl
;
92 if (!EndPagePrinter(m_devHandle
))
93 throw PrinterException("EndPagePrinter error: " +
94 Win32Utils::getErrorMessage());
97 void Printer::flush(void) throw(PrinterException
)
99 if (m_bufferIndex
> 0)
101 write(m_buffer
, m_bufferIndex
);
106 bool Printer::getRawFlag() const
111 void Printer::print(istream
& in
, const string
& docName
) throw(PrinterException
)
119 if (!m_rawFlag
&& ch
== '\n' && lastCh
!= '\r')
128 void Printer::put(unsigned char ch
) throw(PrinterException
)
130 if (m_bufferIndex
== m_bufferSize
)
132 m_buffer
[m_bufferIndex
++] = ch
;
135 void Printer::setRawFlag(bool flag
)
140 void Printer::startDoc(const string
& docName
) throw(PrinterException
)
146 di1
.pDocName
= tstr(docName
);
148 di1
.pDatatype
= "RAW";
150 if (StartDocPrinter(m_devHandle
, 1, (LPBYTE
) &di1
) == 0)
151 throw PrinterException("StartDocPrinter error: " +
152 Win32Utils::getErrorMessage());
155 void Printer::startPage() throw(PrinterException
)
157 cout
<< "Printer::startPage()" << endl
;
158 if (!StartPagePrinter(m_devHandle
))
159 throw PrinterException("StartPagePrinter error: " +
160 Win32Utils::getErrorMessage());
163 void Printer::write(unsigned char *buf
, unsigned int size
) throw(PrinterException
)
166 if (!WritePrinter(m_devHandle
, buf
, size
, &written
))
167 throw PrinterException("error writing to device '" + m_devName
+ "': " +
168 Win32Utils::getErrorMessage());
171 //***************************************************************************
173 // Private operations
175 //***************************************************************************
177 Printer::PrinterList
Printer::enumPrinters(DWORD flags
, LPTSTR name
) throw(PrinterException
)
181 EnumPrinters(flags
, name
, 5, 0, 0, &bytesNeeded
, &numPrinters
);
182 auto_ptr
<BYTE
> enumBuffer(new BYTE
[bytesNeeded
]);
183 if (!EnumPrinters(flags
, name
, 5, enumBuffer
.get(), bytesNeeded
,
184 &bytesNeeded
, &numPrinters
))
185 throw PrinterException("unable to enumerate printers: " +
186 Win32Utils::getErrorMessage());
188 PRINTER_INFO_5
*pi
= reinterpret_cast<PRINTER_INFO_5
*>(enumBuffer
.get());
191 for (unsigned int ii
= 0; ii
< numPrinters
; ++ii
)
194 cerr
<< "Printer name: '" << pi
->pPrinterName
<< "', "
195 << "Port name: '" << pi
->pPortName
<< "'" << endl
;
196 list
.push_back(*pi
++);
202 void Printer::mapPortName() throw(PrinterException
)
206 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
208 bool isWindows9x
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
&&
209 (osvi
.dwMajorVersion
> 4 ||
210 (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
> 0)));
212 bool isWindows2K_NT4
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
&&
213 osvi
.dwMajorVersion
>= 4);
216 cout
<< "isWindows9x = " << isWindows9x
<< ", "
217 << "isWindows2K_NT4 = " << isWindows2K_NT4
<< endl
;
222 PrinterList list
= enumPrinters(PRINTER_ENUM_NAME
, "");
223 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
225 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
228 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
230 m_devName
= it
->pPrinterName
;
236 else if (isWindows2K_NT4
)
238 PrinterList list
= enumPrinters(PRINTER_ENUM_LOCAL
, 0);
239 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
241 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
244 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
246 m_devName
= it
->pPrinterName
;
251 list
= enumPrinters(PRINTER_ENUM_CONNECTIONS
, 0);
252 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
254 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
257 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
259 m_devName
= it
->pPrinterName
;
266 void Printer::open() throw(PrinterException
)
268 PRINTER_DEFAULTS prDef
;
270 prDef
.pDatatype
= "RAW";
271 prDef
.pDevMode
= m_devMode
;
272 prDef
.DesiredAccess
= PRINTER_ACCESS_USE
;
274 if (m_devHandle
== INVALID_HANDLE_VALUE
&&
275 !OpenPrinter(tstr(m_devName
), &m_devHandle
, &prDef
))
276 throw PrinterException("can't open '" + m_devName
+ "' for writing: " +
277 Win32Utils::getErrorMessage());