]> cygwin.com Git - cygwin-apps/cygutils.git/blob - src/lpr/Printer.cc
Import relevant changes from MinGW and MSYS port
[cygwin-apps/cygutils.git] / src / lpr / Printer.cc
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 using namespace std;
24
25 inline LPTSTR tstr(const string & str)
26 {
27 return const_cast<char*>(str.c_str());
28 }
29
30 Printer::Printer(const string &name, bool debugFlag) 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 m_rawFlag(false)
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
64 Printer::~Printer()
65 {
66 close();
67 if (m_buffer != 0)
68 delete [] m_buffer;
69 if (m_devMode != 0)
70 delete m_devMode;
71 }
72
73 void Printer::close()
74 {
75 if (m_devHandle != INVALID_HANDLE_VALUE)
76 {
77 ClosePrinter(m_devHandle);
78 m_devHandle = INVALID_HANDLE_VALUE;
79 }
80 }
81
82 void Printer::endDoc() throw(PrinterException)
83 {
84 if (!EndDocPrinter(m_devHandle))
85 throw PrinterException("EndDocPrinter error: " +
86 Win32Utils::getErrorMessage());
87 }
88
89 void Printer::endPage() throw(PrinterException)
90 {
91 cout << "Printer::endPage()" << endl;
92 if (!EndPagePrinter(m_devHandle))
93 throw PrinterException("EndPagePrinter error: " +
94 Win32Utils::getErrorMessage());
95 }
96
97 void Printer::flush(void) throw(PrinterException)
98 {
99 if (m_bufferIndex > 0)
100 {
101 write(m_buffer, m_bufferIndex);
102 m_bufferIndex = 0;
103 }
104 }
105
106 bool Printer::getRawFlag() const
107 {
108 return m_rawFlag;
109 }
110
111 void Printer::print(istream & in, const string & docName) throw(PrinterException)
112 {
113 startDoc(docName);
114
115 char ch;
116 char lastCh = '\0';
117 while (in.get(ch))
118 {
119 if (!m_rawFlag && ch == '\n' && lastCh != '\r')
120 put('\r');
121 put(ch);
122 lastCh = ch;
123 }
124 flush();
125 endDoc();
126 }
127
128 void Printer::put(unsigned char ch) throw(PrinterException)
129 {
130 if (m_bufferIndex == m_bufferSize)
131 flush();
132 m_buffer[m_bufferIndex++] = ch;
133 }
134
135 void Printer::setRawFlag(bool flag)
136 {
137 m_rawFlag = flag;
138 }
139
140 void Printer::startDoc(const string & docName) throw(PrinterException)
141 {
142 DOC_INFO_1 di1;
143
144 open();
145
146 di1.pDocName = tstr(docName);
147 di1.pOutputFile = 0;
148 di1.pDatatype = "RAW";
149
150 if (StartDocPrinter(m_devHandle, 1, (LPBYTE) &di1) == 0)
151 throw PrinterException("StartDocPrinter error: " +
152 Win32Utils::getErrorMessage());
153 }
154
155 void Printer::startPage() throw(PrinterException)
156 {
157 cout << "Printer::startPage()" << endl;
158 if (!StartPagePrinter(m_devHandle))
159 throw PrinterException("StartPagePrinter error: " +
160 Win32Utils::getErrorMessage());
161 }
162
163 void Printer::write(unsigned char *buf, unsigned int size) throw(PrinterException)
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
177 Printer::PrinterList Printer::enumPrinters(DWORD flags, LPTSTR name) throw(PrinterException)
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)
192 {
193 if (m_debugFlag)
194 cerr << "Printer name: '" << pi->pPrinterName << "', "
195 << "Port name: '" << pi->pPortName << "'" << endl;
196 list.push_back(*pi++);
197 }
198
199 return list;
200 }
201
202 void Printer::mapPortName() 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
266 void Printer::open() throw(PrinterException)
267 {
268 PRINTER_DEFAULTS prDef;
269
270 prDef.pDatatype = "RAW";
271 prDef.pDevMode = m_devMode;
272 prDef.DesiredAccess = PRINTER_ACCESS_USE;
273
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.046425 seconds and 5 git commands to generate.