]> cygwin.com Git - cygwin-apps/cygutils.git/blame - src/lpr/Printer.cc
Reimplement lpr in C++, Rick Rankin.
[cygwin-apps/cygutils.git] / src / lpr / Printer.cc
CommitLineData
21006e63
CW
1/*
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"
23
24inline LPTSTR tstr(const string & str)
25{
26 return const_cast<char*>(str.c_str());
27}
28
29Printer::Printer(const string &name, bool debugFlag)
30 throw(PrinterException)
31 : m_devName(name),
32 m_debugFlag(debugFlag),
33 m_devHandle(INVALID_HANDLE_VALUE),
34 m_devMode(0),
35 m_buffer(0),
36 m_bufferSize(4096),
37 m_bufferIndex(0)
38{
39 m_buffer = new unsigned char[m_bufferSize];
40 mapPortName();
41
42 open();
43
44 // Initialize the DEVMODE structure
45 // Get the amount of space needed for the buffer.
46 DWORD needed = DocumentProperties(NULL, m_devHandle, tstr(m_devName),
47 NULL, NULL, 0);
48
49 m_devMode = reinterpret_cast<DEVMODE *>(new unsigned char[needed]);
50
51 // Get the default DEVMODE for the printer.
52 DWORD ret = DocumentProperties(NULL, m_devHandle, tstr(m_devName),
53 m_devMode, NULL, DM_OUT_BUFFER);
54 if (ret != IDOK)
55 throw PrinterException("error getting the default device mode: " +
56 Win32Utils::getErrorMessage());
57
58 // Close the printer, because we'll need to reopen it later, passing it
59 // the DEVMODE structure with any optional changes by the user.
60 close();
61}
62
63Printer::~Printer()
64{
65 close();
66 if (m_buffer != 0)
67 delete [] m_buffer;
68 if (m_devMode != 0)
69 delete m_devMode;
70}
71
72void Printer::close()
73{
74 if (m_devHandle != INVALID_HANDLE_VALUE)
75 {
76 ClosePrinter(m_devHandle);
77 m_devHandle = INVALID_HANDLE_VALUE;
78 }
79}
80
81void Printer::endDoc()
82 throw(PrinterException)
83{
84 if (!EndDocPrinter(m_devHandle))
85 throw PrinterException("EndDocPrinter error: " +
86 Win32Utils::getErrorMessage());
87}
88
89void Printer::endPage()
90 throw(PrinterException)
91{
92 cout << "Printer::endPage()" << endl;
93 if (!EndPagePrinter(m_devHandle))
94 throw PrinterException("EndPagePrinter error: " +
95 Win32Utils::getErrorMessage());
96}
97
98void Printer::flush(void)
99 throw(PrinterException)
100{
101 if (m_bufferIndex > 0)
102 {
103 write(m_buffer, m_bufferIndex);
104 m_bufferIndex = 0;
105 }
106}
107
108void Printer::print(istream & in, const string & docName)
109 throw(PrinterException)
110{
111 startDoc(docName);
112
113 char ch;
114 char lastCh = '\0';
115 while (!in.eof())
116 {
117 in.get(ch);
118 if (ch == '\n' && lastCh != '\r')
119 put('\r');
120 put(ch);
121 lastCh = ch;
122 }
123 flush();
124 endDoc();
125}
126
127void Printer::put(unsigned char ch)
128 throw(PrinterException)
129{
130 if (m_bufferIndex == m_bufferSize)
131 flush();
132 m_buffer[m_bufferIndex++] = ch;
133}
134
135void Printer::startDoc(const string & docName)
136 throw(PrinterException)
137{
138 DOC_INFO_1 di1;
139
140 open();
141
142 di1.pDocName = tstr(docName);
143 di1.pOutputFile = 0;
144 di1.pDatatype = "RAW";
145
146 if (StartDocPrinter(m_devHandle, 1, (LPBYTE) &di1) == 0)
147 throw PrinterException("StartDocPrinter error: " +
148 Win32Utils::getErrorMessage());
149}
150
151void Printer::startPage()
152 throw(PrinterException)
153{
154 cout << "Printer::startPage()" << endl;
155 if (!StartPagePrinter(m_devHandle))
156 throw PrinterException("StartPagePrinter error: " +
157 Win32Utils::getErrorMessage());
158}
159
160void Printer::write(unsigned char *buf, unsigned int size)
161 throw(PrinterException)
162{
163 DWORD written;
164 if (!WritePrinter(m_devHandle, buf, size, &written))
165 throw PrinterException("error writing to device '" + m_devName + "': " +
166 Win32Utils::getErrorMessage());
167}
168
169//***************************************************************************
170//
171// Private operations
172//
173//***************************************************************************
174
175Printer::PrinterList Printer::enumPrinters(DWORD flags, LPTSTR name)
176 throw(PrinterException)
177{
178 DWORD numPrinters;
179 DWORD bytesNeeded;
180 EnumPrinters(flags, name, 5, 0, 0, &bytesNeeded, &numPrinters);
181 auto_ptr<BYTE> enumBuffer(new BYTE[bytesNeeded]);
182 if (!EnumPrinters(flags, name, 5, enumBuffer.get(), bytesNeeded,
183 &bytesNeeded, &numPrinters))
184 throw PrinterException("unable to enumerate printers: " +
185 Win32Utils::getErrorMessage());
186
187 PRINTER_INFO_5 *pi = reinterpret_cast<PRINTER_INFO_5 *>(enumBuffer.get());
188
189 PrinterList list;
190 for (unsigned int ii = 0; ii < numPrinters; ++ii)
191 {
192 if (m_debugFlag)
193 cerr << "Printer name: '" << pi->pPrinterName << "', "
194 << "Port name: '" << pi->pPortName << "'" << endl;
195 list.push_back(*pi++);
196 }
197
198 return list;
199}
200
201void Printer::mapPortName()
202 throw(PrinterException)
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)
221 {
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 }
234 }
235
236 else if (isWindows2K_NT4)
237 {
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 }
263 }
264}
265
266void Printer::open()
267 throw(PrinterException)
268{
269 PRINTER_DEFAULTS prDef;
270
271 prDef.pDatatype = "RAW";
272 prDef.pDevMode = m_devMode;
273 prDef.DesiredAccess = PRINTER_ALL_ACCESS;
274
275 if (m_devHandle == INVALID_HANDLE_VALUE &&
276 !OpenPrinter(tstr(m_devName), &m_devHandle, &prDef))
277 throw PrinterException("can't open '" + m_devName + "' for writing: " +
278 Win32Utils::getErrorMessage());
279}
This page took 0.047745 seconds and 5 git commands to generate.