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