]> cygwin.com Git - cygwin-apps/cygutils.git/blame - src/lpr/Printer.cc
Import relevant changes from MinGW and MSYS port
[cygwin-apps/cygutils.git] / src / lpr / Printer.cc
CommitLineData
fe3a7d70 1/*
21006e63
CW
2 * lpr for cygwin/windows
3 *
4 * Copyright (C) 2000-2003 Rick Rankin
5 * http://www.cygwin.com/ml/cygwin/2000-07/msg00320.html
6 *
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.
10 *
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.
15 *
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
19 */
20
21#include "src/lpr/Printer.hh"
22#include "src/lpr/Win32Utils.hh"
fe3a7d70 23using namespace std;
21006e63
CW
24
25inline LPTSTR tstr(const string & str)
26{
27 return const_cast<char*>(str.c_str());
28}
29
fe3a7d70
CW
30Printer::Printer(const string &name, bool debugFlag) throw(PrinterException)
31 : m_devName(name),
21006e63
CW
32 m_debugFlag(debugFlag),
33 m_devHandle(INVALID_HANDLE_VALUE),
34 m_devMode(0),
35 m_buffer(0),
36 m_bufferSize(4096),
a18d2869
CW
37 m_bufferIndex(0),
38 m_rawFlag(false)
21006e63
CW
39{
40 m_buffer = new unsigned char[m_bufferSize];
41 mapPortName();
42
43 open();
fe3a7d70 44
21006e63
CW
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),
48 NULL, NULL, 0);
49
50 m_devMode = reinterpret_cast<DEVMODE *>(new unsigned char[needed]);
fe3a7d70 51
21006e63
CW
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);
55 if (ret != IDOK)
56 throw PrinterException("error getting the default device mode: " +
57 Win32Utils::getErrorMessage());
58
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.
61 close();
62}
63
64Printer::~Printer()
65{
66 close();
67 if (m_buffer != 0)
68 delete [] m_buffer;
69 if (m_devMode != 0)
70 delete m_devMode;
71}
72
73void Printer::close()
74{
75 if (m_devHandle != INVALID_HANDLE_VALUE)
fe3a7d70
CW
76 {
77 ClosePrinter(m_devHandle);
78 m_devHandle = INVALID_HANDLE_VALUE;
79 }
21006e63
CW
80}
81
fe3a7d70 82void Printer::endDoc() throw(PrinterException)
21006e63
CW
83{
84 if (!EndDocPrinter(m_devHandle))
85 throw PrinterException("EndDocPrinter error: " +
86 Win32Utils::getErrorMessage());
87}
88
fe3a7d70 89void Printer::endPage() throw(PrinterException)
21006e63
CW
90{
91 cout << "Printer::endPage()" << endl;
92 if (!EndPagePrinter(m_devHandle))
93 throw PrinterException("EndPagePrinter error: " +
94 Win32Utils::getErrorMessage());
95}
96
fe3a7d70 97void Printer::flush(void) throw(PrinterException)
21006e63
CW
98{
99 if (m_bufferIndex > 0)
fe3a7d70
CW
100 {
101 write(m_buffer, m_bufferIndex);
102 m_bufferIndex = 0;
103 }
21006e63
CW
104}
105
a18d2869
CW
106bool Printer::getRawFlag() const
107{
108 return m_rawFlag;
109}
110
fe3a7d70 111void Printer::print(istream & in, const string & docName) throw(PrinterException)
21006e63
CW
112{
113 startDoc(docName);
114
115 char ch;
116 char lastCh = '\0';
807fb049 117 while (in.get(ch))
fe3a7d70
CW
118 {
119 if (!m_rawFlag && ch == '\n' && lastCh != '\r')
120 put('\r');
121 put(ch);
122 lastCh = ch;
123 }
21006e63
CW
124 flush();
125 endDoc();
126}
127
fe3a7d70 128void Printer::put(unsigned char ch) throw(PrinterException)
21006e63
CW
129{
130 if (m_bufferIndex == m_bufferSize)
131 flush();
132 m_buffer[m_bufferIndex++] = ch;
133}
a18d2869
CW
134
135void Printer::setRawFlag(bool flag)
136{
137 m_rawFlag = flag;
138}
139
fe3a7d70 140void Printer::startDoc(const string & docName) throw(PrinterException)
21006e63
CW
141{
142 DOC_INFO_1 di1;
fe3a7d70 143
21006e63 144 open();
fe3a7d70 145
21006e63
CW
146 di1.pDocName = tstr(docName);
147 di1.pOutputFile = 0;
148 di1.pDatatype = "RAW";
fe3a7d70 149
21006e63
CW
150 if (StartDocPrinter(m_devHandle, 1, (LPBYTE) &di1) == 0)
151 throw PrinterException("StartDocPrinter error: " +
152 Win32Utils::getErrorMessage());
153}
154
fe3a7d70 155void Printer::startPage() throw(PrinterException)
21006e63
CW
156{
157 cout << "Printer::startPage()" << endl;
158 if (!StartPagePrinter(m_devHandle))
159 throw PrinterException("StartPagePrinter error: " +
160 Win32Utils::getErrorMessage());
161}
162
fe3a7d70 163void Printer::write(unsigned char *buf, unsigned int size) throw(PrinterException)
21006e63
CW
164{
165 DWORD written;
166 if (!WritePrinter(m_devHandle, buf, size, &written))
167 throw PrinterException("error writing to device '" + m_devName + "': " +
168 Win32Utils::getErrorMessage());
169}
170
171//***************************************************************************
172//
173// Private operations
174//
175//***************************************************************************
176
fe3a7d70 177Printer::PrinterList Printer::enumPrinters(DWORD flags, LPTSTR name) throw(PrinterException)
21006e63
CW
178{
179 DWORD numPrinters;
180 DWORD bytesNeeded;
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());
187
188 PRINTER_INFO_5 *pi = reinterpret_cast<PRINTER_INFO_5 *>(enumBuffer.get());
189
190 PrinterList list;
191 for (unsigned int ii = 0; ii < numPrinters; ++ii)
fe3a7d70
CW
192 {
193 if (m_debugFlag)
194 cerr << "Printer name: '" << pi->pPrinterName << "', "
195 << "Port name: '" << pi->pPortName << "'" << endl;
196 list.push_back(*pi++);
197 }
21006e63
CW
198
199 return list;
200}
201
fe3a7d70 202void Printer::mapPortName() throw(PrinterException)
21006e63
CW
203{
204
205 OSVERSIONINFO osvi;
206 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
207 GetVersionEx(&osvi);
208 bool isWindows9x = (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
209 (osvi.dwMajorVersion > 4 ||
210 (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0)));
211
212 bool isWindows2K_NT4 = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
213 osvi.dwMajorVersion >= 4);
214
215 if (m_debugFlag)
216 cout << "isWindows9x = " << isWindows9x << ", "
217 << "isWindows2K_NT4 = " << isWindows2K_NT4 << endl;
218
219
220 if (isWindows9x)
21006e63 221 {
fe3a7d70
CW
222 PrinterList list = enumPrinters(PRINTER_ENUM_NAME, "");
223 for (PrinterList::iterator it = list.begin(); it != list.end(); ++it)
224 {
225 if (stricmp(m_devName.c_str(), it->pPortName) == 0)
226 {
227 if (m_debugFlag)
228 cout << "Mapped '" << m_devName << "' to '" << it->pPrinterName
229 << "'" << endl;
230 m_devName = it->pPrinterName;
231 return;
232 }
233 }
21006e63 234 }
21006e63
CW
235
236 else if (isWindows2K_NT4)
21006e63 237 {
fe3a7d70
CW
238 PrinterList list = enumPrinters(PRINTER_ENUM_LOCAL, 0);
239 for (PrinterList::iterator it = list.begin(); it != list.end(); ++it)
240 {
241 if (stricmp(m_devName.c_str(), it->pPortName) == 0)
242 {
243 if (m_debugFlag)
244 cout << "Mapped '" << m_devName << "' to '" << it->pPrinterName
245 << "'" << endl;
246 m_devName = it->pPrinterName;
247 return;
248 }
249 }
250
251 list = enumPrinters(PRINTER_ENUM_CONNECTIONS, 0);
252 for (PrinterList::iterator it = list.begin(); it != list.end(); ++it)
253 {
254 if (stricmp(m_devName.c_str(), it->pPortName) == 0)
255 {
256 if (m_debugFlag)
257 cout << "Mapped '" << m_devName << "' to '" << it->pPrinterName
258 << "'" << endl;
259 m_devName = it->pPrinterName;
260 return;
261 }
262 }
21006e63 263 }
21006e63
CW
264}
265
fe3a7d70 266void Printer::open() throw(PrinterException)
21006e63
CW
267{
268 PRINTER_DEFAULTS prDef;
fe3a7d70 269
21006e63
CW
270 prDef.pDatatype = "RAW";
271 prDef.pDevMode = m_devMode;
669b09e4 272 prDef.DesiredAccess = PRINTER_ACCESS_USE;
fe3a7d70 273
21006e63
CW
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());
278}
This page took 0.045935 seconds and 5 git commands to generate.