]> cygwin.com Git - cygwin-apps/cygutils.git/blame - src/lpr/Printer.cc
lump commit
[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),
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();
44
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]);
51
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)
76 {
77 ClosePrinter(m_devHandle);
78 m_devHandle = INVALID_HANDLE_VALUE;
79 }
80}
81
82void Printer::endDoc()
83 throw(PrinterException)
84{
85 if (!EndDocPrinter(m_devHandle))
86 throw PrinterException("EndDocPrinter error: " +
87 Win32Utils::getErrorMessage());
88}
89
90void Printer::endPage()
91 throw(PrinterException)
92{
93 cout << "Printer::endPage()" << endl;
94 if (!EndPagePrinter(m_devHandle))
95 throw PrinterException("EndPagePrinter error: " +
96 Win32Utils::getErrorMessage());
97}
98
99void Printer::flush(void)
100 throw(PrinterException)
101{
102 if (m_bufferIndex > 0)
103 {
104 write(m_buffer, m_bufferIndex);
105 m_bufferIndex = 0;
106 }
107}
108
a18d2869
CW
109bool Printer::getRawFlag() const
110{
111 return m_rawFlag;
112}
113
21006e63
CW
114void Printer::print(istream & in, const string & docName)
115 throw(PrinterException)
116{
117 startDoc(docName);
118
119 char ch;
120 char lastCh = '\0';
807fb049 121 while (in.get(ch))
21006e63 122 {
a18d2869 123 if (!m_rawFlag && ch == '\n' && lastCh != '\r')
21006e63
CW
124 put('\r');
125 put(ch);
126 lastCh = ch;
127 }
128 flush();
129 endDoc();
130}
131
132void Printer::put(unsigned char ch)
133 throw(PrinterException)
134{
135 if (m_bufferIndex == m_bufferSize)
136 flush();
137 m_buffer[m_bufferIndex++] = ch;
138}
a18d2869
CW
139
140void Printer::setRawFlag(bool flag)
141{
142 m_rawFlag = flag;
143}
144
21006e63
CW
145void Printer::startDoc(const string & docName)
146 throw(PrinterException)
147{
148 DOC_INFO_1 di1;
149
150 open();
151
152 di1.pDocName = tstr(docName);
153 di1.pOutputFile = 0;
154 di1.pDatatype = "RAW";
155
156 if (StartDocPrinter(m_devHandle, 1, (LPBYTE) &di1) == 0)
157 throw PrinterException("StartDocPrinter error: " +
158 Win32Utils::getErrorMessage());
159}
160
161void Printer::startPage()
162 throw(PrinterException)
163{
164 cout << "Printer::startPage()" << endl;
165 if (!StartPagePrinter(m_devHandle))
166 throw PrinterException("StartPagePrinter error: " +
167 Win32Utils::getErrorMessage());
168}
169
170void Printer::write(unsigned char *buf, unsigned int size)
171 throw(PrinterException)
172{
173 DWORD written;
174 if (!WritePrinter(m_devHandle, buf, size, &written))
175 throw PrinterException("error writing to device '" + m_devName + "': " +
176 Win32Utils::getErrorMessage());
177}
178
179//***************************************************************************
180//
181// Private operations
182//
183//***************************************************************************
184
185Printer::PrinterList Printer::enumPrinters(DWORD flags, LPTSTR name)
186 throw(PrinterException)
187{
188 DWORD numPrinters;
189 DWORD bytesNeeded;
190 EnumPrinters(flags, name, 5, 0, 0, &bytesNeeded, &numPrinters);
191 auto_ptr<BYTE> enumBuffer(new BYTE[bytesNeeded]);
192 if (!EnumPrinters(flags, name, 5, enumBuffer.get(), bytesNeeded,
193 &bytesNeeded, &numPrinters))
194 throw PrinterException("unable to enumerate printers: " +
195 Win32Utils::getErrorMessage());
196
197 PRINTER_INFO_5 *pi = reinterpret_cast<PRINTER_INFO_5 *>(enumBuffer.get());
198
199 PrinterList list;
200 for (unsigned int ii = 0; ii < numPrinters; ++ii)
201 {
202 if (m_debugFlag)
203 cerr << "Printer name: '" << pi->pPrinterName << "', "
204 << "Port name: '" << pi->pPortName << "'" << endl;
205 list.push_back(*pi++);
206 }
207
208 return list;
209}
210
211void Printer::mapPortName()
212 throw(PrinterException)
213{
214
215 OSVERSIONINFO osvi;
216 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
217 GetVersionEx(&osvi);
218 bool isWindows9x = (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
219 (osvi.dwMajorVersion > 4 ||
220 (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0)));
221
222 bool isWindows2K_NT4 = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
223 osvi.dwMajorVersion >= 4);
224
225 if (m_debugFlag)
226 cout << "isWindows9x = " << isWindows9x << ", "
227 << "isWindows2K_NT4 = " << isWindows2K_NT4 << endl;
228
229
230 if (isWindows9x)
231 {
232 PrinterList list = enumPrinters(PRINTER_ENUM_NAME, "");
233 for (PrinterList::iterator it = list.begin(); it != list.end(); ++it)
234 {
235 if (stricmp(m_devName.c_str(), it->pPortName) == 0)
236 {
237 if (m_debugFlag)
238 cout << "Mapped '" << m_devName << "' to '" << it->pPrinterName
239 << "'" << endl;
240 m_devName = it->pPrinterName;
241 return;
242 }
243 }
244 }
245
246 else if (isWindows2K_NT4)
247 {
248 PrinterList list = enumPrinters(PRINTER_ENUM_LOCAL, 0);
249 for (PrinterList::iterator it = list.begin(); it != list.end(); ++it)
250 {
251 if (stricmp(m_devName.c_str(), it->pPortName) == 0)
252 {
253 if (m_debugFlag)
254 cout << "Mapped '" << m_devName << "' to '" << it->pPrinterName
255 << "'" << endl;
256 m_devName = it->pPrinterName;
257 return;
258 }
259 }
260
261 list = enumPrinters(PRINTER_ENUM_CONNECTIONS, 0);
262 for (PrinterList::iterator it = list.begin(); it != list.end(); ++it)
263 {
264 if (stricmp(m_devName.c_str(), it->pPortName) == 0)
265 {
266 if (m_debugFlag)
267 cout << "Mapped '" << m_devName << "' to '" << it->pPrinterName
268 << "'" << endl;
269 m_devName = it->pPrinterName;
270 return;
271 }
272 }
273 }
274}
275
276void Printer::open()
277 throw(PrinterException)
278{
279 PRINTER_DEFAULTS prDef;
280
281 prDef.pDatatype = "RAW";
282 prDef.pDevMode = m_devMode;
669b09e4 283 prDef.DesiredAccess = PRINTER_ACCESS_USE;
21006e63
CW
284
285 if (m_devHandle == INVALID_HANDLE_VALUE &&
286 !OpenPrinter(tstr(m_devName), &m_devHandle, &prDef))
287 throw PrinterException("can't open '" + m_devName + "' for writing: " +
288 Win32Utils::getErrorMessage());
289}
This page took 0.046705 seconds and 5 git commands to generate.